+ * 设置下划线字体及点击事件 + *
+ */ + public static void setSpannableString(int showResId, int showUnderLineResId, OnClickListener listener, TextView view) { + String showResourceTip = ""; + if (showResId != 0) { + showResourceTip = view.getContext().getResources().getString(showResId); + } + String showUnderLineResTip = view.getContext().getResources().getString(showUnderLineResId); + String tip = showResourceTip + showUnderLineResTip; + SpannableString ss = new SpannableString(tip); + int start = showResourceTip.length(); + int end = showUnderLineResTip.length() + start; + int flag = Spanned.SPAN_EXCLUSIVE_EXCLUSIVE; + MyURLSpan mus = new MyURLSpan(view.getContext().getResources().getString(R.string.assetfont_html));// 字体 + mus.setOnClickListener(listener); + ForegroundColorSpan fcs = new ForegroundColorSpan(view.getContext().getResources() + .getColor(R.color.lc_color_4ea7f2)); + ss.setSpan(mus, start, end, flag); + ss.setSpan(fcs, start, end, flag); + view.setText(ss); + view.setMovementMethod(LinkMovementMethod.getInstance()); + } + + /** + *+ * 设置下划线字体及点击事件 + *
+ */ + public static void setSpannableString(int showResId, String showUnderLineResTip, OnClickListener listener, TextView view) { + String showResourceTip = ""; + if (showResId != 0) { + showResourceTip = view.getContext().getResources().getString(showResId); + } + if (showUnderLineResTip == null) { + showUnderLineResTip = ""; + } + String tip = showResourceTip + showUnderLineResTip; + SpannableString ss = new SpannableString(tip); + int start = showResourceTip.length(); + int end = showUnderLineResTip.length() + start; + int flag = Spanned.SPAN_EXCLUSIVE_EXCLUSIVE; + MyURLSpan mus = new MyURLSpan(view.getContext().getResources().getString(R.string.assetfont_html));// 字体 + mus.setOnClickListener(listener); + ForegroundColorSpan fcs = new ForegroundColorSpan(view.getContext().getResources() + .getColor(R.color.lc_color_4ea7f2)); + ss.setSpan(mus, start, end, flag); + ss.setSpan(fcs, start, end, flag); + view.setText(ss); + view.setMovementMethod(LinkMovementMethod.getInstance()); + } + + private static DisplayImageOptions mDeviceModeImageOptions; + + + /** + * 是否为TP1等设备,包括TP1 TC1 TK1 TC3 TK3 TC4 TC5 TC5S TP6、TP6C、TC6、TC6C、TP7 + */ + public static boolean isTp1And(String deviceModelName) { + return LCConfiguration.TYPE_TC1.equals(deviceModelName) || LCConfiguration.TYPE_TK1.equals(deviceModelName) + || LCConfiguration.TYPE_TC3.equals(deviceModelName) || LCConfiguration.TYPE_TK3.equals(deviceModelName) + || LCConfiguration.TYPE_TC4.equals(deviceModelName) || LCConfiguration.TYPE_TC5.equals(deviceModelName) + || LCConfiguration.TYPE_TC5S.equals(deviceModelName) || LCConfiguration.TYPE_TP1.equals(deviceModelName) + || LCConfiguration.TYPE_TP6.equals(deviceModelName) || LCConfiguration.TYPE_TP6C.equals(deviceModelName) + || LCConfiguration.TYPE_TC6.equals(deviceModelName) || LCConfiguration.TYPE_TC6C.equals(deviceModelName) + || LCConfiguration.TYPE_TP7.equals(deviceModelName); + } + + + //根据域名获取 + public static String getAddDeviceHelpUrl(String host) { + if (host.contains(":443")) { + host = host.split(":")[0]; + } + return "http://" + host + "/bindhelp.html"; + } + + + /** + * * 检测设备新老版本, ture 表示新版本并且DHCP打开走单播流程, false 老版本/DHCP关闭走组播加单播流程。 + * * @return + * + */ + public static boolean checkDeviceVersion(DEVICE_NET_INFO_EX deviceInfo) { + if(deviceInfo==null) + return false; + int flag = (deviceInfo.bySpecialAbility >> 2) & 0x03; + return 0x00 != flag && 0x03 != flag; + } + + + /** + * * 检测设备获取的IP是否有效, ture 有效 + * * @param deviceInfo + * * @return + * + */ + public static boolean checkEffectiveIP(DEVICE_NET_INFO_EX deviceInfo) { + if(deviceInfo==null) + return false; + int flag = (deviceInfo.bySpecialAbility >> 2) & 0x03; + return 0x02 == flag; + } + + /** + * 生成二维码 + * @param url + * @param width + * @param height + * @return + */ + public static Bitmap creatQRImage(String url, final int width, final int height) { + try { + if(TextUtils.isEmpty(url)) { + return null; + } + Hashtable+ * 伪json格式的二维码扫描结果(带NC) + *
+ */ +public class PseudoJsonNcScanResult extends ScanResult { + + private static final String TAG = "JsonScanResult"; + private static final String[] SN_TAGS = new String[]{"SN", "sN", "Sn", "sn"}; + private static final String[] DT_TAGS = new String[]{"DT", "dT", "Dt", "dt"}; + private static final String[] RD_TAGS = new String[]{"RD", "rD", "Rd", "rd"}; + private static final String[] RC_TAGS = new String[]{"RC", "rC", "Rc", "rc"}; + private static final String[] NC_TAGS = new String[]{"NC", "nC", "Nc", "nc"}; + private static final String[] SC_TAGS = new String[]{"SC", "sC", "Sc", "sc"}; + private static final String[] IMEI_TAGS = new String[]{"IMEI", "imei"}; + + /** + * 创建一个新的实例JsonScanResult. + * + * @param scanString + */ + public PseudoJsonNcScanResult(String scanString) { + super(scanString); + + //解析伪Json 类似{SN:DVRP2P00LJL0028,DT:DH/HCVR1604HG-SFD-V4/-AF-DVR-II-A/16-16,NC:QR,RC:SQ93W5} + + //替换中文":" + scanString = scanString.replace(':', ':'); + + // 补充"{" "}" + int first = scanString.indexOf("{"); + if (first < 0) { + scanString = "{" + scanString; + } + int last = scanString.indexOf("}"); + if (last < 0) { + scanString = scanString + "}"; + } + + // 补充引号""" + StringBuffer buffer = new StringBuffer(); + for(int i = 0; i < scanString.length(); i++) { + char c = scanString.charAt(i); + if(c == '{') { + buffer.append(c).append("\""); + }else if(c == ':' || c == ',' || c == ';') { + buffer.append("\"").append(c).append("\""); + } else if(c == '}') { + buffer.append("\"").append(c); + } else { + buffer.append(c); + } + } + + String sn = ""; + String dt = ""; + String rd = ""; + String nc = ""; + String sc = ""; + String imeiCode = ""; + + try { + JSONObject jsonObject = new JSONObject(buffer.toString()); + sn = getValue(jsonObject, SN_TAGS, ""); + dt = getValue(jsonObject, DT_TAGS, ""); + rd = getValue(jsonObject, RD_TAGS, ""); + rd = getValue(jsonObject, RC_TAGS, ""); + nc = getValue(jsonObject, NC_TAGS, ""); + sc = getValue(jsonObject, SC_TAGS, ""); + imeiCode = getValue(jsonObject, IMEI_TAGS, ""); + } catch (Exception e) { + e.printStackTrace(); + } + this.setSn(sn); + this.setRegcode(rd); + this.setMode(dt); + this.setNc(nc); + this.setSc(sc); + this.setImeiCode(imeiCode); + LogUtil.debugLog("PseudoJsonNcScanResult", this.toString()); + } + + private String getValue(JSONObject json, String[] tags, String defaultStr) { + for (String tag : tags) { + if (json.has(tag)) { + return json.optString(tag, defaultStr); + } + } + return defaultStr; + } + +} diff --git a/DeviceAddModule/src/main/java/com/mm/android/deviceaddmodule/mobilecommon/AppConsume/PseudoJsonScanResult.java b/DeviceAddModule/src/main/java/com/mm/android/deviceaddmodule/mobilecommon/AppConsume/PseudoJsonScanResult.java new file mode 100644 index 0000000..7fac391 --- /dev/null +++ b/DeviceAddModule/src/main/java/com/mm/android/deviceaddmodule/mobilecommon/AppConsume/PseudoJsonScanResult.java @@ -0,0 +1,157 @@ +package com.mm.android.deviceaddmodule.mobilecommon.AppConsume; + +import android.text.TextUtils; + +/** + *+ * 伪json格式的二维码扫描结果 + *
+ */ +public class PseudoJsonScanResult extends ScanResult { + + private static final String TAG = "JsonScanResult"; + private static final String[] SN_TAGS = new String[]{"SN:", "sN:", "Sn:", "sn:", "SN:", "sN:", "Sn:", "sn:"}; + private static final String[] DT_TAGS = new String[]{"DT:", "dT:", "Dt:", "dt:", "DT:", "dT:", "Dt:", "dt:"}; + private static final String[] RD_TAGS = new String[]{"RD:", "rD:", "Rd:", "rd:", "RD:", "rD:", "Rd:", "rd:"}; + private static final String[] RC_TAGS = new String[]{"RC:", "rC:", "Rc:", "rc:", "RC:", "rC:", "Rc:", "rc:"}; + + /** + * 创建一个新的实例JsonScanResult. + * + * @param scanString + */ + public PseudoJsonScanResult(String scanString) { + super(scanString); + + //解析伪Json 类似{SN:DVRP2P00LJL0028,DT:DH/HCVR1604HG-SFD-V4/-AF-DVR-II-A/16-16,RC:SQ93W5} + + String jsonStr; + int firstIndex = scanString.indexOf("{"); + if (firstIndex >= 0 && firstIndex <= scanString.length() - 1) { + jsonStr = scanString.substring(firstIndex, scanString.length()); + } else { + jsonStr = scanString; + } + + int snEndIndex = -1; + int dtEndIndex = -1; + int rdEndIndex = -1; + int snStartIndex = getStartIndex(jsonStr, SN_TAGS, -1); + int dtStartIndex = getStartIndex(jsonStr, DT_TAGS, -1); + int rdStartIndex = getStartIndex(jsonStr, RD_TAGS, -1); + rdStartIndex = getStartIndex(jsonStr, RC_TAGS, rdStartIndex); + + if (snStartIndex == -1) { + this.setSn(""); + return; + } + + + if (snStartIndex > dtStartIndex && snStartIndex > rdStartIndex) { // sn在最后 + if (dtStartIndex == -1 && rdStartIndex == -1) { // {sn:} + snEndIndex = jsonStr.length() - 1; + + } else if (dtStartIndex == -1 && rdStartIndex != -1) { // {rd:,sn:} + rdEndIndex = snStartIndex - 1; + snEndIndex = jsonStr.length() - 1; + } else if (dtStartIndex != -1 && rdStartIndex == -1) { // {dt:,sn:} + dtEndIndex = snStartIndex - 1; + snEndIndex = jsonStr.length() - 1; + } else { + if (dtStartIndex > rdStartIndex) { // {rd:,dt:,sn:} + rdEndIndex = dtStartIndex - 1; + dtEndIndex = snStartIndex - 1; + snEndIndex = jsonStr.length() - 1; + } else { // {dt:,rd:,sn:} + dtEndIndex = rdStartIndex - 1; + rdEndIndex = snStartIndex - 1; + snEndIndex = jsonStr.length() - 1; + } + } + } else if (dtStartIndex > snStartIndex && dtStartIndex > rdStartIndex) { // dt在最后 + if (rdStartIndex == -1) { + snEndIndex = dtStartIndex - 1; + dtEndIndex = jsonStr.length() - 1; + } else if (snStartIndex > rdStartIndex) { + rdEndIndex = snStartIndex - 1; + snEndIndex = dtStartIndex - 1; + dtEndIndex = jsonStr.length() - 1; + + } else if (snStartIndex < rdStartIndex) { + snEndIndex = rdStartIndex - 1; + rdEndIndex = dtStartIndex - 1; + dtEndIndex = jsonStr.length() - 1; + } + } else if (rdStartIndex > snStartIndex && rdStartIndex > dtStartIndex) { // rd在最后 + if (dtStartIndex == -1) { + snEndIndex = rdStartIndex - 1; + rdEndIndex = jsonStr.length() - 1; + } else if (snStartIndex > dtStartIndex) { + dtEndIndex = snStartIndex - 1; + snEndIndex = rdStartIndex - 1; + rdEndIndex = jsonStr.length() - 1; + + } else if (snStartIndex < dtStartIndex) { + snEndIndex = dtStartIndex - 1; + dtEndIndex = rdStartIndex - 1; + rdEndIndex = jsonStr.length() - 1; + } + } + + if (rdStartIndex != -1) { + this.setRegcode(filterInvalidString(jsonStr.substring(rdStartIndex + 2, rdEndIndex))); + } else { + this.setRegcode(""); + } + + if (dtStartIndex != -1) { + this.setMode(filterInvalidString4Type(jsonStr.substring(dtStartIndex + 2, dtEndIndex))); + } else { + this.setMode(""); + } + this.setSn(filterInvalidString(jsonStr.substring(snStartIndex + 2, snEndIndex))); + + } + + private int getStartIndex(String jsonStr, String[] tags, int startIndex) { + for (String dttag : tags) { + if (jsonStr.contains(dttag)) { + return jsonStr.indexOf(dttag) + 1; + } + } + return startIndex; + } + + public static String filterInvalidString(String str) { + if (TextUtils.isEmpty(str)) { + return str; + } + String numberAndAbc = "[a-zA-Z0-9]"; + StringBuilder buffer = new StringBuilder(); + int len = str.length(); + for (int i = 0; i < len; ++i) { + String temp = str.substring(i, i + 1); + if (temp.matches(numberAndAbc)) { + buffer.append(temp); + } + } + return buffer.toString(); + } + + public static String filterInvalidString4Type(String str) { + if (TextUtils.isEmpty(str)) { + return str; + } + String numberAndAbc = "[a-zA-Z0-9-/\\\\]"; + StringBuilder buffer = new StringBuilder(); + int len = str.length(); + for (int i = 0; i < len; ++i) { + String temp = str.substring(i, i + 1); + if (temp.matches(numberAndAbc)) { + buffer.append(temp); + } + } + return buffer.toString(); + } + +} diff --git a/DeviceAddModule/src/main/java/com/mm/android/deviceaddmodule/mobilecommon/AppConsume/ScanResult.java b/DeviceAddModule/src/main/java/com/mm/android/deviceaddmodule/mobilecommon/AppConsume/ScanResult.java new file mode 100644 index 0000000..8d3c2e9 --- /dev/null +++ b/DeviceAddModule/src/main/java/com/mm/android/deviceaddmodule/mobilecommon/AppConsume/ScanResult.java @@ -0,0 +1,124 @@ +package com.mm.android.deviceaddmodule.mobilecommon.AppConsume; + +/** + *+ * 二维码扫描结果基类 + *
+ */ +public class ScanResult { + /** + * 设备序列号 + */ + private String sn = ""; + + /** + * 设备型号 + */ + private String mode = ""; + + /** + * 设备验证码、设备安全码 + */ + private String regcode = ""; + + /** + * 设备随机码,备用 + */ + private String rd = ""; + + /** + * 设备能力 + */ + private String nc = ""; + + /** + * 设备安全验证码 + */ + private String sc = ""; + + private String imeiCode = ""; + + /** + * 创建一个新的实例ScanResult. + * + * @param scanString + */ + public ScanResult(String scanString) { + // TODO Auto-generated constructor stub + } + + /** + * 创建一个新的实例ScanResult. + */ + public ScanResult() { + // TODO Auto-generated constructor stub + } + + public String getSn() { + return sn; + } + + public void setSn(String sn) { + this.sn = sn; + } + + public String getRegcode() { + return regcode; + } + + public void setRegcode(String regcode) { + this.regcode = regcode; + } + + public String getRd() { + return rd; + } + + public void setRd(String rd) { + this.rd = rd; + } + + public String getMode() { + return mode; + } + + public void setMode(String mode) { + this.mode = mode; + } + + public String getNc() { + return nc; + } + + public void setNc(String nc) { + this.nc = nc; + } + + public String getSc() { + return sc; + } + + public void setSc(String sc) { + this.sc = sc; + } + + public String getImeiCode() { + return imeiCode; + } + + public void setImeiCode(String imeiCode) { + this.imeiCode = imeiCode; + } + + @Override + public String toString() { + return "ScanResult{" + + "sn='" + sn + '\'' + + ", mode='" + mode + '\'' + + ", regcode='" + regcode + '\'' + + ", nc='" + nc + '\'' + + ", sc='" + sc + '\'' + + ", imeiCode='" + imeiCode + '\'' + + '}'; + } +} diff --git a/DeviceAddModule/src/main/java/com/mm/android/deviceaddmodule/mobilecommon/AppConsume/ScanResultFactory.java b/DeviceAddModule/src/main/java/com/mm/android/deviceaddmodule/mobilecommon/AppConsume/ScanResultFactory.java new file mode 100644 index 0000000..8dff8d4 --- /dev/null +++ b/DeviceAddModule/src/main/java/com/mm/android/deviceaddmodule/mobilecommon/AppConsume/ScanResultFactory.java @@ -0,0 +1,140 @@ +package com.mm.android.deviceaddmodule.mobilecommon.AppConsume; + +import android.text.TextUtils; + +import com.mm.android.deviceaddmodule.mobilecommon.common.LCConfiguration; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + *+ * 根据二维码扫描结果生成相应的类 + *
+ */ +public class ScanResultFactory { + // 工厂方法.注意 返回类型为抽象产品角色 + private static String tag = "www.hsview.com"; + private static String tag_lc = "www.lechange.cn"; + + public static ScanResult scanResult(String scanString) { + if (ProviderManager.getAppProvider().getAppType() == LCConfiguration.APP_LECHANGE_OVERSEA) {//海外二维码规则 + // 带NC标签的 + final String[] NC_ARRAYS = new String[]{"NC:", "nC:", "Nc:", "nc:", "NC:", "nC:", "Nc:", "nc:"}; + // 带SC标签的 + final String[] SC_ARRAYS = new String[]{"SC:", "sC:", "Sc:", "Sc:", "SC:", "sC:", "Sc:", "sc:"}; + boolean hasNc = hasTag(scanString, NC_ARRAYS); + boolean hasSc = hasTag(scanString, SC_ARRAYS); + if((hasNc || hasSc) && scanString.contains("{")) { + return new PseudoJsonNcScanResult(scanString); + } else { + String deviceSN = ""; + String deviceSerial = ""; + if (scanString.contains(",")) { //逗号分割,{SN:2J021B3PAK00120,DT:IPC-HFW1120SP-W-0280B,RC:564897} + scanString = scanString.substring(1, scanString.length() - 1); //去掉收尾花括号 + String[] array = scanString.split(","); + for (String strArray : array) { + if (strArray.contains("SN:")) { + deviceSN = strArray.substring(strArray.indexOf("SN:") + 3, strArray.length()); + } + if (strArray.contains("DT:")) { + deviceSerial = strArray.substring(strArray.indexOf("DT:") + 3, strArray.length()); + } + } + } else if (scanString.contains(";")) {//分号分割,{SN:2J021B3PAK00120;DT:IPC-HFW1120SP-W-0280B;RC:564897} + scanString = scanString.substring(1, scanString.length() - 1); //去掉收尾花括号 + String[] array = scanString.split(";"); + for (String strArray : array) { + if (strArray.contains("SN:")) { + deviceSN = strArray.substring(strArray.indexOf("SN:") + 3, strArray.length()); + } + if (strArray.contains("DT:")) { + deviceSerial = strArray.substring(strArray.indexOf("DT:") + 3, strArray.length()); + } + } + } else if (scanString.contains(":")) { //2M047C9PAN00005:DHI-ARD1611-W:PJ0V46 + String[] array = scanString.split(":"); + deviceSN = array[0]; + deviceSerial = array[1]; + } else { + deviceSN = scanString; + } + // 兼容 俄语区Q4的订单采用标签二维码内容异常 格式为:DH-IPC-C35P,4K002C6PAJA49A7 + if(TextUtils.isEmpty(deviceSN)) { + String[] array = scanString.split(","); + if(array != null && array.length == 2) { + deviceSN = array[1]; + } + } + + ScanResult scanResult = new ScanResult(); + scanResult.setSn(deviceSN); + scanResult.setMode(deviceSerial); + return scanResult; + } + } else {//国内二维码规则 + if(scanString.contains(tag) || scanString.contains(tag_lc)){ + if(scanString.contains("{")){ + // 兼容TC1 + ScanResult scanResult = new PseudoJsonScanResult(scanString); + return scanResult; + } + // 兼容老乐橙设备 + int index = scanString.indexOf('='); + String sn = scanString.substring(index + 1, scanString.length()); + ScanResult scanResult = new ScanResult(); + scanResult.setSn(sn); + return scanResult; + } else if (scanString.contains("{")) { + ScanResult result = new PseudoJsonNcScanResult(scanString); + return result; + } else if (!scanString.contains("SN:") || !scanString.contains("SN=") || !scanString.contains("SN =") || + !scanString.contains("sn:") || !scanString.contains("sn=") || !scanString.contains("sn =")) { + if (!checkString(scanString)) { + String[] strings = scanString.split(":"); + if (strings != null && !scanString.startsWith("http://") && strings.length == 3) { + return new TwoColonsScanResult(scanString); + + } else if (strings != null && !scanString.startsWith("http://") && strings.length == 2) { + return new OneColonScanResult(scanString); + } + } else { + ScanResult scanResult = new ScanResult(); + scanResult.setSn(scanString); + return scanResult; + } + } + } + return new ScanResult(); + } + + // 判断是否有tag + private static boolean hasTag(String scanString, String[] tagArrays) { + boolean hasTag = false; + for (String tag : tagArrays) { + if (scanString.contains(tag)) { + hasTag = true; + break; + } + } + return hasTag; + } + + /** + * 判断是否只包含数字或大小写字母 + * + * @param str + * @return + */ + public static boolean checkString(String str) { + String regEx = "[0-9A-Za-z]*"; // 只能是数字以及个别字符 + Pattern p = Pattern.compile(regEx); + Matcher m = p.matcher(str); + if (m.matches()) { + return true; + } else { + return false; + } + } + +} \ No newline at end of file diff --git a/DeviceAddModule/src/main/java/com/mm/android/deviceaddmodule/mobilecommon/AppConsume/ThreadPool.java b/DeviceAddModule/src/main/java/com/mm/android/deviceaddmodule/mobilecommon/AppConsume/ThreadPool.java new file mode 100644 index 0000000..565d1dc --- /dev/null +++ b/DeviceAddModule/src/main/java/com/mm/android/deviceaddmodule/mobilecommon/AppConsume/ThreadPool.java @@ -0,0 +1,60 @@ +package com.mm.android.deviceaddmodule.mobilecommon.AppConsume; + +import android.os.Process; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.ThreadFactory; + +public class ThreadPool { + private volatile static ExecutorService cachedThreadPool; + + // 提交线程 + public static Future> submit(Runnable mRunnable) { + + if (cachedThreadPool == null) { + synchronized (ExecutorService.class) { + if (cachedThreadPool == null) { + cachedThreadPool = Executors.newFixedThreadPool(Runtime + .getRuntime().availableProcessors() * 2,new DefaultFactory()); + } + } + } + return cachedThreadPool.submit(mRunnable); + } + + // 关闭 + public static void shutdown() { + if (cachedThreadPool != null && !cachedThreadPool.isShutdown()) + cachedThreadPool.shutdown(); + cachedThreadPool = null; + } + + static class DefaultFactory implements ThreadFactory { + + @Override + public Thread newThread(Runnable r) { + + Thread thread = new Thread(new FactoryRunnable(r)); + + return thread; + } + } + + static class FactoryRunnable implements Runnable { + Runnable runnable; + + public FactoryRunnable(Runnable runnable) { + this.runnable = runnable; + } + + @Override + public void run() { + Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); + runnable.run(); + } + + } + +} diff --git a/DeviceAddModule/src/main/java/com/mm/android/deviceaddmodule/mobilecommon/AppConsume/TwoColonsScanResult.java b/DeviceAddModule/src/main/java/com/mm/android/deviceaddmodule/mobilecommon/AppConsume/TwoColonsScanResult.java new file mode 100644 index 0000000..409fac8 --- /dev/null +++ b/DeviceAddModule/src/main/java/com/mm/android/deviceaddmodule/mobilecommon/AppConsume/TwoColonsScanResult.java @@ -0,0 +1,25 @@ +package com.mm.android.deviceaddmodule.mobilecommon.AppConsume; +import static com.mm.android.deviceaddmodule.mobilecommon.AppConsume.PseudoJsonScanResult.filterInvalidString; +import static com.mm.android.deviceaddmodule.mobilecommon.AppConsume.PseudoJsonScanResult.filterInvalidString4Type; + +/** + *+ * xxx:xxx:xxx格式二维码 + *
+ */ +public class TwoColonsScanResult extends ScanResult { + + /** + * 创建一个新的实例TwoColonsScanResult. + * + * @param scanString + */ + public TwoColonsScanResult(String scanString) { + super(scanString); + String[] resultStrings = scanString.split(":"); + this.setSn(filterInvalidString(resultStrings[0])); + this.setMode(filterInvalidString4Type(resultStrings[1])); + this.setRegcode(filterInvalidString(resultStrings[2])); + } + +} diff --git a/DeviceAddModule/src/main/java/com/mm/android/deviceaddmodule/mobilecommon/annotation/DeviceAbility.java b/DeviceAddModule/src/main/java/com/mm/android/deviceaddmodule/mobilecommon/annotation/DeviceAbility.java new file mode 100644 index 0000000..2a87b43 --- /dev/null +++ b/DeviceAddModule/src/main/java/com/mm/android/deviceaddmodule/mobilecommon/annotation/DeviceAbility.java @@ -0,0 +1,164 @@ +package com.mm.android.deviceaddmodule.mobilecommon.annotation; + +import android.support.annotation.StringDef; + +import java.lang.annotation.Retention; + +import static com.mm.android.deviceaddmodule.mobilecommon.annotation.DeviceAbility.*; +import static java.lang.annotation.RetentionPolicy.SOURCE; + +@Retention(SOURCE) +@StringDef({WLAN, AlarmPIR, AlarmMD, AudioTalk, AudioTalkV1, VVP2P, DHP2P, PTZ, PT, HSEncrypt, CloudStorage, AGW, BreathingLight, + PlaybackByFilename, LocalStorage, RegCode, RemoteControl, Panorama, RD, SLAlarm, CK, AudioEncodeOff, MDS, MDW, HeaderDetect, + SR, AGWDisarm, CollectionPoint, TimedCruise, SmartTrack, ZoomFocus, SmartLocate, LocalRecord, XUpgrade, Auth, NumberStat, + + HoveringAlarm, BeOpenedDoor, NonAccessoriesAdd, CloseCamera, MobileDetect, Siren, LinkageSiren, WhiteLight, WLV2, Dormant, + /*NoVA, */NoAccessories, UnsupportLiveShare, RTSV1, PBSV1, SearchLight, CallByRtsp, SirenTime,NVM, LEDS, TimingGraphics, HumanDetect, AlarmPIRV2, HUBAlarmPIRV2, + AlarmPIRV3, AlarmPIRV4, LocalStorageEnable, DaySummerTime, WeekSummerTime,SummerTimeOffset, AiHuman, AiCar, Electric, WIFI, DLOCS, OpenDoorByFace, OpenDoorByTouch, + PlaySoundModify, WideDynamic, TalkSoundModify, LinkDevAlarm, LinkAccDevAlarm, AbAlarmSound, CheckAbDecible, Reboot, PlaySound, + AudioEncodeControl, SceneMode, SIMCA, TimeFormat, SASQ, MGOCS, ModifyName, ElecInfo, SigInfo, ACT, AlarmSound, DDT, OnlyArmed, TSV1, NoPlan, ChnLocalStorage, + AccessoryAlarmSound, RingAlarmSound, SCCode, CustomRing, InfraredLight, AudioEncodeControlV2, InstantDisAlarm,IDAP, RDV2,RDV3, DeviceAlarmSound, FaceDetect, + CallAbility, CAV2, HAV2, Ring, RTSV2, PBSV2, TSV2, PT1, AX, HAV3, VideoMotionSMD, TLSEnable, TCM, CLDA, ChnWhiteLight, ChnSiren, LED, + CCR, CLS, CLW, ""}) + +public @interface DeviceAbility { + String WLAN = "WLAN"; // 设备支持接入无线局域网 + String AlarmPIR = "AlarmPIR"; // 设备支持人体红外报警 + String AlarmMD = "AlarmMD"; // 设备支持动检报警 + String AudioTalk = "AudioTalk"; // 设备支持语音对讲 + String AudioTalkV1 = "AudioTalkV1"; // 通道支持语音对讲 + String VVP2P = "VVP2P"; // 设备支持威威网络P2P服务 + String DHP2P = "DHP2P"; // 设备支持大华P2P服务 + String PTZ = "PTZ"; // 设备支持云台方向操作,及云台缩放 + String PT = "PT"; // 设备支持云台方向操作 + String PT1 = "PT1"; // 设备支持云台四方向操作 + String HSEncrypt = "HSEncrypt"; // 设备支持华视微讯码流加密 + String CloudStorage = "CloudStorage"; // 设备支持华视微讯平台云存储 + String CloudUpdate = "CloudUpdate"; // easy4ip支持云升级,自己本地判断使用 + String AGW = "AGW"; // 设备支持网关功能 + String BreathingLight = "BreathingLight"; // 设备有呼吸灯 + String PlaybackByFilename = "PlaybackByFilename"; // 设备支持根据文件名回放 + String LocalStorage = "LocalStorage"; // 支持设备本地存储,如有SD卡或硬盘 + String RegCode = "RegCode"; // 设备添加需要支持验证码 + String RemoteControl = "RemoteControl"; // 支持远程联动 + String Panorama = "Panorama"; //支持全景图 + String RD = "RD"; //设备具有远程调试能力(Remote Debug) + String RDV2 = "RDV2"; //支持RD能力,支持数据埋点控制,支持调试日志上传 对应设备体验计划开关 + String RDV3 = "RDV3"; //支持RD能力,支持数据埋点控制,支持级别控制 + String SLAlarm = "SLAlarm"; //设备支持声光告警(sound and light alarm) + String CK = "CK"; // 设备视频加密 + String AudioEncodeOff = "AudioEncodeOff"; //支持音频编码关闭(无伴音) AudioEncode:支持音频编码(伴音) 老设备不上报,因此只需要使用AudioEncodeOff进行判断即可 + String MDS = "MDS"; //通道 motion-detect-sensitive支持动检灵敏度设置 + String MDW = "MDW"; //通道 motion-detect-window支持动检窗口设置 + String HeaderDetect = "HeaderDetect"; //通道 支持人头检测 + String SR = "SR"; ////设备,设备支持语音识别 + String AGWDisarm = "AGWDisarm"; // 网关告警解除配置(APP2.8,网关支持布撤防(过滤配件告警,但保留告警配置)功能) + String CollectionPoint = "CollectionPoint"; //支持收藏点 + String TimedCruise = "TimedCruise"; //支持定时巡航 + String SmartTrack = "SmartTrack"; //智能追踪 + String ZoomFocus = "ZoomFocus"; //支持变倍聚焦 变焦相机能力集 + String SmartLocate = "SmartLocate"; //听声辨位 + String LocalRecord = "LocalRecord"; //支持设备设备录像设置 + String XUpgrade = "XUpgrade"; // 云升级 + String Auth = "Auth"; // 设备端环回RTSP需认证 + String NumberStat = "NumberStat"; // 客流量数据采集 + String HoveringAlarm = "HoveringAlarm"; //徘徊报警 + String BeOpenedDoor = "BeOpenedDoor"; //普通开门,即成功开门(K5电池门锁) + String NonAccessoriesAdd = "NonAccessoriesAdd"; //表示不支持C端信令添加方式 + String CloseCamera = "CloseCamera"; //支持关闭摄像头 + String MobileDetect = "MobileDetect"; //动检+PIR + String Siren = "Siren"; //警笛 + String LinkageSiren = "LinkageSiren"; //报警联动警笛 + String WhiteLight = "WhiteLight"; //白光灯 + String WLV2 = "WLV2"; // 白光灯,不支持亮度调节能力 + String Dormant = "Dormant"; //可休眠,具有唤醒、休眠状态 + // String NoVA = "NoVA"; //不支持语音播报(Voice Announcements) + String NoAccessories = "NoAccessories"; //不支持配件使能(不支持布撤防) + String UnsupportLiveShare = "UnsupportLiveShare"; //是否支持直播分享,easy4ip独有, 客户端自己的能力级,相当于控制开关 + String RTSV1 = "RTSV1";//实时流支持私有协议拉流 + String PBSV1 = "PBSV1";//回放流支持私有协议拉流 + String TSV1 = "TSV1"; //对讲支持私有协议拉流 + String RTSV2 = "RTSV2";//实时流支持私有协议拉流(TLS) + String PBSV2 = "PBSV2";//回放流支持私有协议拉流(TLS) + String TSV2 = "TSV2"; //对讲支持私有协议拉流(TLS) + String TimingGraphics = "TimingGraphics"; //人形录像服务能力 + String HumanDetect = "HumanDetect"; //人形检测(海外) + String AlarmPIRV2 = "AlarmPIRV2"; //支持PIR开关 + String HUBAlarmPIRV2 = "HUBAlarmPIRV2"; //支持Hub PIR开关 + String AlarmPIRV3 = "AlarmPIRV3"; //支持PIR扇形区域,同时支持PIR使能开关 + String AlarmPIRV4 = "AlarmPIRV4"; //支持PIR扇形区域 + String LocalStorageEnable = "LocalStorageEnable"; //支持录像存储开关 + String SearchLight = "SearchLight"; //探照灯 + String CallByRtsp = "CallByRtsp"; //表示接听、挂断可直接基于RTSP协议实现 + String SirenTime = "SirenTime"; //支持警笛时长设置 + String NVM = "NVM"; //支持夜视模式设置 + String LEDS = "LEDS"; //支持补光灯灵敏度 + String DaySummerTime = "DaySummerTime"; //按日夏令时 + String WeekSummerTime = "WeekSummerTime";//按周夏令时 + String SummerTimeOffset = "SummerTimeOffset"; //支持夏令时偏移量设置 + String TimeFormat = "TimeFormat";//支持时间格式设置 + String SceneMode = "SceneMode"; //支持布撤防情景模式设置 + String SIMCA = "SIMCA"; //支持SIM卡相关配置 + String SASQ = "SASQ";//配件防拆状态能力集 + String MGOCS = "MGOCS";//支持门磁开关状态获取 + String ModifyName = "ModifyName";//配件支持修改名称 + String ElecInfo = "ElecInfo";//支持电量信息查询上报 + String SigInfo = "SigInfo";//支持信号信息查询上报 + String ACT = "ACT";//支持报警持续时间配置 + String AlarmSound = "AlarmSound"; //支持报警音设置 + String AiHuman = "AiHuman";//人形智能 TF8P + String AiCar = "AiCar";//车辆智能 TF8P + String Electric = "Electric";//设备支持电池电量能力 + String WIFI = "WIFI";//设备支持获取WIFI信号强度能力 + String DLOCS = "DLOCS";//门锁开关状态 + + String DDT = "DDT"; //支持布防延时能力 + String OnlyArmed = "OnlyArmed"; //只支持布防(永久布防) + String NoPlan = "NoPlan";//不支持布防计划 + String OpenDoorByFace = "OpenDoorByFace";//人脸开门 + String OpenDoorByTouch = "OpenDoorByTouch";// 触摸开门 + String PlaySoundModify = "PlaySoundModify";// 设备提示音调节能力 + String TalkSoundModify = "TalkSoundModify";//对讲音量调节 + String WideDynamic = "WideDynamic";// 宽动态 + String LinkDevAlarm = "LinkDevAlarm";//关联设备报警 + String LinkAccDevAlarm = "LinkAccDevAlarm";//关联配件报警 + String AbAlarmSound = "AbAlarmSound";//异常报警音 + String CheckAbDecible = "CheckAbDecible";//异常检测音分贝阈值 + String Reboot = "Reboot";//设备重启 + String PlaySound = "PlaySound"; //设备提示音开关能力 + String AudioEncodeControl = "AudioEncodeControl"; //支持音频编码控制(开或关) + String AudioEncodeControlV2 = "AudioEncodeControlV2";//支持音频编码控制(开或关),只影响实时视频、录像音频,不影响对讲音频控制 + String AccessoryAlarmSound = "AccessoryAlarmSound";//支持报警网关配件报警音效设置 + String DeviceAlarmSound = "DeviceAlarmSound"; //设备报警音效设置 + String RingAlarmSound = "RingAlarmSound";//支持门铃音量设置 + String ChnLocalStorage = "ChnLocalStorage";//支持通道本地存储 + + String SCCode = "SCCode"; // 设备支持SC安全码 + String CustomRing = "CustomRing";//自定义铃声 + String InfraredLight = "InfraredLight";//红外灯能力集 + String InstantDisAlarm = "InstantDisAlarm";//支持一键撤防能力 + String IDAP = "IDAP";//支持一键撤防能力 + String FaceDetect = "FaceDetect"; //支持人脸检测 + + String CallAbility = "CallAbility"; //支持呼叫能力 + String CAV2 = "CAV2"; //支持呼叫能力,且拒接时可选择播放自定义铃声 + String HAV2 = "HAV2"; //徘徊报警V2,支持统一的检测距离设置及逗留时长设置 + String Ring = "Ring"; //仅支持铃声设置 LoginAfter DS11,去除根据设备型号兼容逻辑 2019-4-3 + String AX = "AX"; // 安消一体机 + String HAV3 = "HAV3"; // 徘徊报警V3,V2降级版,不支持逗留时长立即设置 + String VideoMotionSMD = "VideoMotionSMD";//包含人形和车辆能力 + + /*3.15.0*/ + String TCM = "TCM"; //支持3码合一(Three code megre) + String TLSEnable = "TLSEnable";// 2019-8-20 支持拉流、图片和云录像链路加密传输 + + /*5.0.0*/ + String CLW = "CLW"; //通道报警联动白光灯 + String CLS = "CLS"; //通道报警联动警笛 + String CCR = "CCR"; //通道自定义铃声 + String LED = "LED"; //补光灯 + String ChnSiren = "ChnSiren"; //警笛 + String ChnWhiteLight = "ChnWhiteLight"; //通道白光灯 + String CLDA = "CLDA"; //通道关联设备报警 + +} diff --git a/DeviceAddModule/src/main/java/com/mm/android/deviceaddmodule/mobilecommon/annotation/DeviceState.java b/DeviceAddModule/src/main/java/com/mm/android/deviceaddmodule/mobilecommon/annotation/DeviceState.java new file mode 100644 index 0000000..f11f214 --- /dev/null +++ b/DeviceAddModule/src/main/java/com/mm/android/deviceaddmodule/mobilecommon/annotation/DeviceState.java @@ -0,0 +1,24 @@ +package com.mm.android.deviceaddmodule.mobilecommon.annotation; + +import android.support.annotation.StringDef; + +import java.lang.annotation.Retention; + +import static com.mm.android.deviceaddmodule.mobilecommon.annotation.DeviceState.OFFLINE; +import static com.mm.android.deviceaddmodule.mobilecommon.annotation.DeviceState.ONLINE; +import static com.mm.android.deviceaddmodule.mobilecommon.annotation.DeviceState.SLEEP; +import static com.mm.android.deviceaddmodule.mobilecommon.annotation.DeviceState.UPGRADE; +import static java.lang.annotation.RetentionPolicy.SOURCE; + +/** + * 设备在离线状态枚举值 + */ +@Retention(SOURCE) +@StringDef({ONLINE, OFFLINE, SLEEP,UPGRADE, ""}) +public @interface DeviceState { + String ONLINE = "online"; + String OFFLINE = "offline"; + String SLEEP = "sleep"; + String UPGRADE = "upgrading"; + +} diff --git a/DeviceAddModule/src/main/java/com/mm/android/deviceaddmodule/mobilecommon/base/ActivityManager.java b/DeviceAddModule/src/main/java/com/mm/android/deviceaddmodule/mobilecommon/base/ActivityManager.java new file mode 100644 index 0000000..ede087b --- /dev/null +++ b/DeviceAddModule/src/main/java/com/mm/android/deviceaddmodule/mobilecommon/base/ActivityManager.java @@ -0,0 +1,71 @@ +package com.mm.android.deviceaddmodule.mobilecommon.base; + +import android.app.Activity; + +import java.util.Stack; + +/** + *+ * activity 栈管理 + *
+ */ +public class ActivityManager { + private static Stack+ * 检测快速双击事件 + *
+ * + * @return + */ + public Boolean isWindowLocked() { + long current = SystemClock.elapsedRealtime(); + if (current - mLastOnClickTime > 500) { + mLastOnClickTime = current; + return false; + } + return true; + } + + protected void dissmissProgressDialog() { + if (mProgressDialog != null && mProgressDialog.isShowing()) { + mProgressDialog.dismiss(); + } + } + + protected void showProgressDialog(int layoutId) { + if (mProgressDialog != null && !mProgressDialog.isShowing()) { + mProgressDialog.show(); + mProgressDialog.setContentView(layoutId); + } + } + + protected void cancleProgressDialog() { + if (mProgressDialog != null && mProgressDialog.isShowing()) { + mProgressDialog.cancel(); + } + } + + protected void setProgressDialogCancle(boolean flag) { + if (mProgressDialog != null) { + mProgressDialog.setCancelable(flag); + } + } + + protected void toast(int res) { + String content =""; + try { + content = getString(res); + }catch (Resources.NotFoundException e){ + LogUtil.debugLog("toast", "resource id not found!!!"); + } + toast(content); + } + + protected void toast(String content) { + //系统版本大于等于android 9.0之后的版本 + if(Build.VERSION_CODES.O_MR1 < Build.VERSION.SDK_INT){ + Toast.makeText(mContext,content,Toast.LENGTH_SHORT).show(); + }else{ + if (mToast == null) { + mToast = Toast.makeText(mContext, content, Toast.LENGTH_SHORT); + } else { + mToast.setText(content); + mToast.setDuration(Toast.LENGTH_SHORT); + } + mToast.show(); + } + } + + /** + * 带错误码的toast + * @param errorCode + */ + public void toast(int res, int errorCode) { + //系统版本大于等于android 9.0之后的版本 + if(Build.VERSION_CODES.O_MR1 < Build.VERSION.SDK_INT){ + Toast.makeText(mContext,getString(res) + "(" + errorCode + ")",Toast.LENGTH_SHORT).show(); + }else { + if (mToast == null) { + mToast = Toast.makeText(mContext, getString(res) + "(" + errorCode + ")", Toast.LENGTH_SHORT); + } else { + mToast.setText(getString(res) + "(" + errorCode + ")"); + } + mToast.show(); + } + } + + protected void toastInCenter(int res) { + String content =""; + try { + content = getString(res); + }catch (Resources.NotFoundException e){ + LogUtil.debugLog("toast", "resource id not found!!!"); + } + toastInCenter(content); + + } + + protected void toastInCenter(String content) { + //系统版本大于等于android 9.0之后的版本 + if(Build.VERSION_CODES.O_MR1 < Build.VERSION.SDK_INT){ + Toast toastInCenter = Toast.makeText(mContext, content, Toast.LENGTH_SHORT); + toastInCenter.setGravity(Gravity.CENTER, 0, 0); + TextView tv = toastInCenter.getView().findViewById(android.R.id.message); + tv.setGravity(Gravity.CENTER); + toastInCenter.show(); + + }else{ + if (mToastInCenter == null) { + mToastInCenter = Toast.makeText(mContext, content, Toast.LENGTH_SHORT); + mToastInCenter.setGravity(Gravity.CENTER, 0, 0); + TextView tv = mToastInCenter.getView().findViewById(android.R.id.message); + tv.setGravity(Gravity.CENTER); + } else { + mToastInCenter.setText(content); + mToastInCenter.setDuration(Toast.LENGTH_SHORT); + } + mToastInCenter.show(); + } + } + + @Override + public void startActivity(Intent intent) { + super.startActivity(intent); + overridePendingTransition(R.anim.mobile_common_slide_in_right, R.anim.mobile_common_slide_out_left); + } + + public void startActivityNoAnimation(Intent intent){ + super.startActivity(intent); + } + + @Override + public void startActivityFromFragment(Fragment fragment, Intent intent, int requestCode) { + super.startActivityFromFragment(fragment, intent, requestCode); + overridePendingTransition(R.anim.mobile_common_slide_in_right, R.anim.mobile_common_slide_out_left); + } + + @Override + public void startActivityForResult(Intent intent, int requestCode) { + super.startActivityForResult(intent, requestCode); + } + + public void startActivityForResultWithAnimation(Intent intent, int requestCode){ + super.startActivityForResult(intent, requestCode); + overridePendingTransition(R.anim.mobile_common_slide_in_right, R.anim.mobile_common_slide_out_left); + } + + @Override + public void finish() { + super.finish(); + overridePendingTransition( + R.anim.mobile_common_slide_left_back_in, + R.anim.mobile_common_slide_right_back_out); + } + + public void finishNoAnimation(){ + super.finish(); + } + + protected final+ * 适配器的基类 + *
+ */ +public abstract class CommonAdapter+ *
+ * @param Key + * @return + */ + public boolean getMessagePushBoolean(String Key) { + SharedPreferences config = getConfig(); + boolean result = config.getBoolean(Key, true); + return result; + } + + /** + * 若不存在Key,则返回 0 + * @param Key + * @return + */ + public long getLong(String Key){ + SharedPreferences config = getConfig(); + long result = config.getLong(Key, 0); + return result; + } + + public long getLong(String Key, long defValue){ + SharedPreferences config = getConfig(); + long result = config.getLong(Key, defValue); + return result; + } + + public void set(String key, String value){ + SharedPreferences config = getConfig(); + SharedPreferences.Editor editor = config.edit(); + editor.putString(key, value); + editor.commit(); + } + + public void set(String key, int value){ + SharedPreferences config = getConfig(); + SharedPreferences.Editor editor = config.edit(); + editor.putInt(key, value); + editor.commit(); + } + + public void set(String key, boolean value){ + SharedPreferences config = getConfig(); + SharedPreferences.Editor editor = config.edit(); + editor.putBoolean(key, value); + editor.commit(); + editor.apply(); + } + + public void set(String key, long value){ + SharedPreferences config = getConfig(); + SharedPreferences.Editor editor = config.edit(); + editor.putLong(key, value); + editor.commit(); + } + + public void set(String key, float value){ + SharedPreferences config = getConfig(); + SharedPreferences.Editor editor = config.edit(); + editor.putFloat(key, value); + editor.commit(); + } + + public void set(String key, List+ *
+ * + * @param dateStr + * @param format + * @return + */ + public static Date stringToDate(String dateStr, String format) { + SimpleDateFormat formatter = TimeUtils.getDateFormatWithUS(format); + Date strtodate = null; + try { + strtodate = formatter.parse(dateStr); + } catch (ParseException e) { + e.printStackTrace(); + return new Date(); + } + return strtodate; + } + + /** + * 服务器0时区字符串转换才本地时间 + * @param dateStr + * @param format + * @return + */ + public static long getLocalTimeByString(String dateStr, String format){ + if(TextUtils.isEmpty(dateStr)){ + return 0; + } + + long time = TimeUtils.stringToDate(dateStr, format).getTime(); + return time = time + getTimeZone() * 1000; //加偏移量 + } + + + /** + * long转String + *+ *
+ * @param milliseconds + * the number of milliseconds since Jan. 1, 1970 GMT. + * @param formatStr + * 要转化成的时间格式 + * @return + */ + public static String long2String(long milliseconds, String formatStr) { + Date date = new Date(milliseconds); + SimpleDateFormat format = TimeUtils.getDateFormatWithUS(formatStr); + return format.format(date); + } + + /** + * string2String + *+ *
+ * @param dateStr + * 被转换的时间字符串 + * @param formatFrom + * 转化前的时间格式 + * @param formatTo + * 转化后的时间格式 + * @return + */ + public static String string2String(String dateStr, String formatFrom, String formatTo) { + SimpleDateFormat formatF = TimeUtils.getDateFormatWithUS(formatFrom); + try { + Date date = formatF.parse(dateStr); + SimpleDateFormat formatT = TimeUtils.getDateFormatWithUS(formatTo); + return formatT.format(date); + } catch (ParseException e1) { + e1.printStackTrace(); + return dateStr; + } + } + + public static String string2StringForReport(String dateStr, String formatFrom, String formatTo) { + SimpleDateFormat formatF = TimeUtils.getDateFormatWithUS(formatFrom); + try { + Date date = formatF.parse(dateStr); + SimpleDateFormat formatT = TimeUtils.getDateFormatWithUS(formatTo); + return formatT.format(date); + } catch (ParseException e1) { + e1.printStackTrace(); + return "--"; + } + } + + /** + * date2Str + *+ *
+ * @param d + * 被转化的Date + * @param format + * 转化格式 + * @return + */ + public static String date2String(Date d, String format) { + if(d == null) { + return ""; + } + SimpleDateFormat formatter = TimeUtils.getDateFormatWithUS(format); + return formatter.format(d); + } + + public static Date string2hhmm(String strDate) { + Date mDate = stringToDate2(strDate, LONG_FORMAT); + if (mDate == null) { + mDate = stringToDate2(strDate, SHORT_FORMAT); + } + if (mDate == null) { + mDate = stringToDate2(strDate, SIMPLE_FORMAT); + } + return mDate; + } + + private static Date stringToDate2(String dateStr, String format) { + SimpleDateFormat formatter = TimeUtils.getDateFormatWithUS(format); + Date strtodate = null; + try { + strtodate = formatter.parse(dateStr); + } catch (ParseException e) { + e.printStackTrace(); + } + return strtodate; + } + + + + public static String getNewRequestTime(long time){ + Date d = new Date(time); + return date2String(d,REQUEST_DATE_FORMAT)+"T"+date2String(d,SHORT_FORMAT2); + } + + public static long getResponseTime(String dateString){ + if(dateString==null) + return 0; + if(dateString.contains("T")){ + dateString = dateString.replace("T" ,""); + } + Date date = stringToDate(dateString,REQUEST_FORMAT); + if (date == null) + return 0; + return date.getTime(); + } + + /** + * 获取时间戳 + * @param dateString 0时区的时间 + * @return + */ + public static long getResponseStamp(String dateString){ + if(dateString==null) + return 0; + if(dateString.contains("T")){ + dateString = dateString.replace("T" ,""); + } + + SimpleDateFormat formatter = TimeUtils.getDateFormatWithUS(REQUEST_FORMAT); + formatter.setTimeZone(TimeZone.getTimeZone("UTC")); + Date strtodate = null; + try { + strtodate = formatter.parse(dateString); + } catch (ParseException e) { + e.printStackTrace(); + } + + if (strtodate == null) + return 0; + return strtodate.getTime(); + } + public static String setOnceTime(String time) { + Date d = string2hhmm(time); + Date now = new Date(); + if (d!=null && d.before(now)) { + // 加一天 + long tomorro = d.getTime() + 24 * 60 * 60 * 1000; + Date tomorr = new Date(tomorro); + return date2String(tomorr, LONG_FORMAT); + } + return date2String(d, LONG_FORMAT); + } + + /** + * 格式化显示时间 + * + * @param inputTime + * 毫秒 + * @param inputTime 输入时间(UNIX时间戳毫秒) + * @return + */ + public static String displayTime(long inputTime, String todayFormatStr, String yesterdayFormatStr, + String otherFormatStr) { + // 日期格式化 + SimpleDateFormat todayFormat = todayFormatStr != null ? TimeUtils.getDateFormatWithUS(todayFormatStr) : null; + SimpleDateFormat yesterdayFormat = yesterdayFormatStr != null ? TimeUtils.getDateFormatWithUS(yesterdayFormatStr) : null; + SimpleDateFormat otherFormat = otherFormatStr != null ? TimeUtils.getDateFormatWithUS(otherFormatStr) : null; + String timeStr = null; + + // 获取当前凌晨时间 + Calendar c = Calendar.getInstance(); + String getYear = String.valueOf(c.get(Calendar.YEAR)); + String getMonth = String.valueOf(c.get(Calendar.MONTH) + 1); + String getDayOfMonth = String.valueOf(c.get(Calendar.DAY_OF_MONTH)); + if (getMonth.length() == 1) { + getMonth = "0" + getMonth; + } + if (getDayOfMonth.length() == 1) { + getDayOfMonth = "0" + getDayOfMonth; + } + String currentStartTimeStr = getYear + "-" + getMonth + "-" + getDayOfMonth + " 00:00:00"; + + // 当前凌晨时间格式转换 + java.sql.Timestamp currentStartTime = java.sql.Timestamp.valueOf(currentStartTimeStr); + long currentStart = currentStartTime.getTime(); + + // 与当前凌晨时间相差秒数 + long timeGap = (currentStart - inputTime) / 1000; + + // 输入时间:年 + if (timeGap <= 0) { + timeStr = todayFormat != null ? todayFormat.format(inputTime) : "今天 "; // 今天格式:10:00 + } else if (timeGap > 0 && timeGap <= 24 * 60 * 60) { + timeStr = yesterdayFormat != null ? yesterdayFormat.format(inputTime) : "昨天 "; // 昨天格式:昨天 + } else { + timeStr = otherFormat != null ? otherFormat.format(inputTime) : String.valueOf(inputTime); // 其他格式:15/09/03 + } + + return timeStr; + } + + /** + * 我的文件、报警消息列表悬停头的文案 今天 、昨天、 05/07、15/12/19 + * + * @param strTimestamp + * 输入时间(格式:"yyyy-MM-dd HH:mm:ss") + * @return + */ + public static String getStickxinzaieader(String strTimestamp) { + // 日期格式化 + SimpleDateFormat xinzai = TimeUtils.getDateFormatWithUS("yy/MM/dd"); + SimpleDateFormat mh = TimeUtils.getDateFormatWithUS("MM/dd"); + SimpleDateFormat y = TimeUtils.getDateFormatWithUS("yyyy"); + String timeStr = null; + + // 获取当前凌晨时间 + Calendar c = Calendar.getInstance(); + String getYear = String.valueOf(c.get(Calendar.YEAR)); + String getMonth = String.valueOf(c.get(Calendar.MONTH) + 1); + String getDayOfMonth = String.valueOf(c.get(Calendar.DAY_OF_MONTH)); + if (getMonth.length() == 1) { + getMonth = "0" + getMonth; + } + if (getDayOfMonth.length() == 1) { + getDayOfMonth = "0" + getDayOfMonth; + } + String currentStartTimeStr = getYear + "-" + getMonth + "-" + getDayOfMonth + " 00:00:00"; + + // 当前凌晨时间格式转换 + java.sql.Timestamp currentStartTime = java.sql.Timestamp.valueOf(currentStartTimeStr); + long currentStart = currentStartTime.getTime(); + + // 输入时间格式转换 + java.sql.Timestamp time = java.sql.Timestamp.valueOf(strTimestamp); + long timestamp = time.getTime(); + + // 与当前凌晨时间相差秒数 + long timeGap = (currentStart - timestamp) / 1000; + + // 输入时间:年 + String year = y.format(timestamp); + + if (timeGap <= 0) { + timeStr = "今天 "; // 格式:今天 + } else if (timeGap > 0 && timeGap <= 24 * 60 * 60) { + timeStr = "昨天 "; // 格式:昨天 + } else if (year.equals(String.valueOf(getYear))) { + timeStr = mh.format(timestamp); // (年内)MM月dd日 + } else { + timeStr = xinzai.format(timestamp); // (年前)格式:yyyy年MM月dd日 + } + + return timeStr; + } + + /** + * 我的文件、报警消息列表悬停头的文案 今天 、昨天、 05/07、15/12/19 + * + * @param timestamp 输入时间UNIX时间戳毫秒 + * @return + */ + public static String getStickxinzaieader(long timestamp) { + // 日期格式化 + SimpleDateFormat xinzai = TimeUtils.getDateFormatWithUS("yy/MM/dd"); + SimpleDateFormat mh = TimeUtils.getDateFormatWithUS("MM/dd"); + SimpleDateFormat y = TimeUtils.getDateFormatWithUS("yyyy"); + String timeStr = null; + + // 获取当前凌晨时间 + Calendar c = Calendar.getInstance(); + String getYear = String.valueOf(c.get(Calendar.YEAR)); + String getMonth = String.valueOf(c.get(Calendar.MONTH) + 1); + String getDayOfMonth = String.valueOf(c.get(Calendar.DAY_OF_MONTH)); + if (getMonth.length() == 1) { + getMonth = "0" + getMonth; + } + if (getDayOfMonth.length() == 1) { + getDayOfMonth = "0" + getDayOfMonth; + } + String currentStartTimeStr = getYear + "-" + getMonth + "-" + getDayOfMonth + " 00:00:00"; + + // 当前凌晨时间格式转换 + java.sql.Timestamp currentStartTime = java.sql.Timestamp.valueOf(currentStartTimeStr); + long currentStart = currentStartTime.getTime(); + + // 与当前凌晨时间相差秒数 + long timeGap = (currentStart - timestamp) / 1000; + + // 输入时间:年 + String year = y.format(timestamp); + + if (timeGap <= 0) { + timeStr = "今天 "; // 格式:今天 + } else if (timeGap > 0 && timeGap <= 24 * 60 * 60) { + timeStr = "昨天 "; // 格式:昨天 + } else if (year.equals(String.valueOf(getYear))) { + timeStr = mh.format(timestamp); // (年内)MM月dd日 + } else { + timeStr = xinzai.format(timestamp); // (年前)格式:yyyy年MM月dd日 + } + + return timeStr; + } + + /** + * 获取当前年的第一天 + *+ *
+ * + * @return + */ + public static Date getCurrentYearFirst() { + Calendar calendar = Calendar.getInstance(); + int year = calendar.get(Calendar.YEAR); + return getYearFirst(year); + } + /** + * 获取某一年的第一天 + *+ *
+ * @param year + * @return + */ + public static Date getYearFirst(int year) { + Calendar calendar = Calendar.getInstance(); + calendar.clear(); + calendar.set(Calendar.YEAR, year); + Date firstDay = calendar.getTime(); + return firstDay; + } + + /** + * 获取当前年的最后一天 + *+ *
+ * @return + */ + public static Date getCurrentYearLast() { + Calendar calendar = Calendar.getInstance(); + int year = calendar.get(Calendar.YEAR); + return getYearLast(year); + } + /** + * 获取某一年的最后一天 + *+ *
+ * @param year + * @return + */ + public static Date getYearLast(int year) { + Calendar calendar = Calendar.getInstance(); + calendar.clear(); + calendar.set(Calendar.YEAR, year); + calendar.roll(Calendar.DAY_OF_YEAR, -1); + Date lastDay = calendar.getTime(); + return lastDay; + } + + /** + * 在输入Date的基础上加/减某段时间,返回一个新的Date + *+ *
+ * @param date + * @param field + * @param value + * @return + */ + public static Date add(Date date, int field, int value) { + Calendar calendar = Calendar.getInstance(); + calendar.clear(); + calendar.setTime(date); + calendar.add(field, value); + return calendar.getTime(); + } + + + /** + * 直播分享时间格式 + */ + public static String getTime(long time) { + time = time +System.currentTimeMillis(); + Date date = new Date(time); + SimpleDateFormat format = TimeUtils.getDateFormatWithUS("MM月dd日 HH:mm"); + return format.format(date); + + } + + public static String getTimeSec() { + Date date = new Date(System.currentTimeMillis()); + SimpleDateFormat format = TimeUtils.getDateFormatWithUS("yyyy-MM-dd HH:mm:ss"); + return format.format(date); + + } + + /*用户融合添加*/ + + /*获取手机时区----UTC格式*/ + public static int getTimeZone(){ + Calendar cal = Calendar.getInstance(Locale.getDefault()); + int zoneOffset = cal.get(Calendar.ZONE_OFFSET); + int zone = zoneOffset/1000; + + return zone; + } + + /*获取时间字符串:从yyyyMMddTHHmmssZ时间格式到yyyy-MM-dd HH:mm*/ + public static String getTimeFromUTC(String timeStr) { + if(TextUtils.isEmpty(timeStr)) { + return ""; + } + Date timeDate = TimeUtils.stringToDate(timeStr, "yyyyMMdd'T'HHmmss'Z'"); + if(timeDate == null) { + return ""; + } + long time = timeDate.getTime(); +// time = time + getTimeZone() * 1000; //加偏移量 + Date date = new Date(time); + SimpleDateFormat sdf = TimeUtils.getDateFormatWithUS("yyyy-MM-dd HH:mm"); + return sdf.format(date); + } + + /** + * 我的文件、报警消息列表悬停头的文案 今天 、昨天、 05/07、15/12/19 + * + * @param context 上下文 + * @param timestamp 输入时间UNIX时间戳毫秒 + * @return + */ + public static String getStickxinzaieader(Context context,long timestamp) { + // 日期格式化 + SimpleDateFormat xinzai = TimeUtils.getDateFormatWithUS("yy/MM/dd"); + SimpleDateFormat mh = TimeUtils.getDateFormatWithUS("MM/dd"); + SimpleDateFormat y = TimeUtils.getDateFormatWithUS("yyyy"); + String timeStr = null; + + // 获取当前凌晨时间 + Calendar c = Calendar.getInstance(); + String getYear = String.valueOf(c.get(Calendar.YEAR)); + String getMonth = String.valueOf(c.get(Calendar.MONTH) + 1); + String getDayOfMonth = String.valueOf(c.get(Calendar.DAY_OF_MONTH)); + if (getMonth.length() == 1) { + getMonth = "0" + getMonth; + } + if (getDayOfMonth.length() == 1) { + getDayOfMonth = "0" + getDayOfMonth; + } + String currentStartTimeStr = getYear + "-" + getMonth + "-" + getDayOfMonth + " 00:00:00"; + + // 当前凌晨时间格式转换 + java.sql.Timestamp currentStartTime = java.sql.Timestamp.valueOf(currentStartTimeStr); + long currentStart = currentStartTime.getTime(); + + // 与当前凌晨时间相差秒数 + long timeGap = (currentStart - timestamp) / 1000; + + // 输入时间:年 + String year = y.format(timestamp); + + if (timeGap <= 0) { + timeStr = context.getResources().getString(R.string.common_today); // 格式:今天 + } else if (timeGap > 0 && timeGap <= 24 * 60 * 60) { + timeStr = context.getResources().getString(R.string.common_yesterday); // 格式:昨天 + } else if (year.equals(String.valueOf(getYear))) { + timeStr = mh.format(timestamp); // (年内)MM月dd日 + } else { + timeStr = xinzai.format(timestamp); // (年前)格式:yyyy年MM月dd日 + } + + return timeStr; + } + + //获取当前时区与0时区差值 + public static int getTimeOffset(){ + Calendar calendar=Calendar.getInstance(TimeZone.getDefault()); + int offset=calendar.get(Calendar.ZONE_OFFSET); + return offset/1000; + } + + /** + * + * @param time 带时区的时间戳(时间单位为mS) + * @return + */ + public static long change2UTC(long time) { + SimpleDateFormat format = TimeUtils.getDateFormatWithUS("yyyy-MM-dd HH:mm:ss"); + format.setTimeZone(TimeZone.getTimeZone("UTC")); + String timeStr=format.format(new Date(time)); + Date date = string2hhmm(timeStr); + return date != null ? date.getTime() : 0; + } + + /** + * + * @param time UTC时间戳(时间单位为mS) + * @return + */ + public static long change2Local(long time){ + SimpleDateFormat format = TimeUtils.getDateFormatWithUS("yyyy-MM-dd HH:mm:ss"); + format.setTimeZone(TimeZone.getDefault()); + String timeStr=format.format(new Date(time + getTimeOffset() * 1000)); + Date date = string2hhmm(timeStr); + return date != null ? date.getTime() : 0; + } + + /** + *将服务返回的时间字串格式转换为yyyy-MM-dd HH:mm:ss格式 + * @param time 服务返回设备时间 + * @return + */ + public static String changeTimeFormat2Standard(String time){ + SimpleDateFormat format = TimeUtils.getDateFormatWithUS("yyyyMMdd'T'HHmmss"); + Date date=null; + try { + date=format.parse(time); + } catch (ParseException e) { + e.printStackTrace(); + } + SimpleDateFormat standardFormat = TimeUtils.getDateFormatWithUS("yyyy-MM-dd HH:mm:ss"); + String standardTimeStr=date==null?"":standardFormat.format(date); + return standardTimeStr; + } + + /** + *将服务返回的时间字串格式转换为MM-dd HH:mm格式 + * @param time 服务返回设备时间 + * @return + */ + public static String changeTimeFormat2StandardNoYear(String time){ + SimpleDateFormat format = TimeUtils.getDateFormatWithUS("yyyyMMdd'T'HHmmss"); + Date date=null; + try { + date=format.parse(time); + } catch (ParseException e) { + e.printStackTrace(); + } + SimpleDateFormat standardFormat = TimeUtils.getDateFormatWithUS("MM-dd HH:mm:ss"); + String standardTimeStr=date==null?"":standardFormat.format(date); + return standardTimeStr; + } + + /** + *将服务返回的时间字串格式转换为yyyy-MM-dd HH:mm格式 + * @param time 服务返回设备时间 + * @return + */ + public static String changeTimeFormat2StandardMin(String time){ + SimpleDateFormat format = TimeUtils.getDateFormatWithUS("yyyyMMdd'T'HHmmss"); + Date date=null; + try { + date=format.parse(time); + } catch (ParseException e) { + e.printStackTrace(); + } + SimpleDateFormat standardFormat = TimeUtils.getDateFormatWithUS("yyyy-MM-dd HH:mm"); + String standardTimeStr=date==null?"":standardFormat.format(date); + return standardTimeStr; + } + + /** + *将服务返回的时间字串格式转换为长整型 + * @param time 服务返回设备时间 + * @return + */ + public static long changeTimeStrToStamp(String time){ + SimpleDateFormat format = TimeUtils.getDateFormatWithUS("yyyyMMdd'T'HHmmss"); + Date date=null; + try { + date=format.parse(time); + } catch (ParseException e) { + e.printStackTrace(); + } + long timeStamp=date==null?0:date.getTime(); + return timeStamp; + } + + /** + *将服务返回的时间字串格式转换为outTimeformat格式 + * @param time 服务返回设备时间 + * @param outTimeformat 自定义时间格式 , 0时区时间转换 + * @return + */ + public static String changeTimeFormat2StandardMinByDateFormat(String time,String outTimeformat){ + SimpleDateFormat format = TimeUtils.getDateFormatWithUS("yyyyMMdd'T'HHmmss'Z'"); + Date date=null; + try { + date=format.parse(time); + } catch (ParseException e) { + e.printStackTrace(); + }catch (NullPointerException e){ + e.printStackTrace(); + } + SimpleDateFormat standardFormat = TimeUtils.getDateFormatWithUS(outTimeformat); + if(date == null)return ""; + date.setTime(date.getTime()+ TimeUtils.getTimeZone() * 1000);//加偏移量 + String standardTimeStr= standardFormat.format(date); + return standardTimeStr; + } + + //返回 0时区 毫秒值 + public static long changeTime2UTCStamp(String time, String dateFormat) { + SimpleDateFormat format = TimeUtils.getDateFormatWithUS(dateFormat); + format.setTimeZone(TimeZone.getTimeZone("UTC")); + Date date = null; + try { + date = format.parse(time); + } catch (ParseException e) { + e.printStackTrace(); + } + return date == null ? 0 : date.getTime(); + } + + /** + * 不带年份的时间转时间戳 + * @param time + * @return + */ + public static long changeDateToUnix(String time) { + SimpleDateFormat sdf = TimeUtils.getDateFormatWithUS("MM-dd HH:mm"); + Date date = new Date(); + try { + date = sdf.parse(time); + } catch (ParseException e) { + e.printStackTrace(); + } + return date.getTime(); + } + + + /** + * 转成大华标准时间 yyyyMMddTHHmmss + * @return + */ + public static String changeTimeFormat(String timeFormat) { + try { + Calendar calendar = Calendar.getInstance(); + calendar.setTimeInMillis(System.currentTimeMillis()); + return String.format(timeFormat, + calendar.get(Calendar.YEAR), + (calendar.get(Calendar.MONTH) + 1), + calendar.get(Calendar.DAY_OF_MONTH), + calendar.get(Calendar.HOUR_OF_DAY), + calendar.get(Calendar.MINUTE), + calendar.get(Calendar.SECOND)); + } catch (Exception e) { + e.printStackTrace(); + } + return ""; + } + + /** + * 按周设置夏令时,保存时将 + * Mar 2nd Sun 00:00 + * 格式转换成 + * 3-2-0 00:00:00 格式 + * 3--1-1 代表三月最后一个周一 + * 月份 "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec" + 第几个 "1st","2nd","3rd","4th","5th" + 周几 "Mon","Tue","Wed","Thu","Fri","Sat","Sun" + + 月,是从1开始,1~12 + 周是从1开始,1~4,以及-1,-1表示最后一周,或第四周是最后一周,也可以用4表示 + 从0~6,0表示周日 + + * @param time + * @return + */ + private static final String[] months = new String[]{"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"}; + private static final String[] numweeks = new String[]{"1st","2nd","3rd","4th","last"}; + private static final String[] weekDays = new String[]{"Mon","Tue","Wed","Thu","Fri","Sat","Sun"}; + + public static String changeEngStrToNumStr(String time) + { + StringBuffer buffer = new StringBuffer(); + if(!TextUtils.isEmpty(time)) + { + String[] array = time.split(" "); + if(array!=null && array.length==4) + { + String month = array[0]; + String numWeek = array[1]; + String weekDay = array[2]; + String date = array[3]; + + for(int i=0; i+ * @param selected + * @param views + */ + public static void setSelected(boolean selected, View... views) { + for (View view : views) { + view.setSelected(selected); + } + } + + /** + * 设置空间是否可用(不置灰) + *
+ *
+ * @param enabled + * @param views + */ + public static void setEnabled(boolean enabled, View... views) { + for (View view : views) { + view.setEnabled(enabled); + } + } + + /** + * 启用/禁用控件,包括所有子控件 + *+ *
+ * @param enabled + */ + public static void setEnabledSub(boolean enabled, ViewGroup... viewGroups) { + for (ViewGroup viewGroup : viewGroups) { + viewGroup.setEnabled(enabled); + for (int i = 0; i < viewGroup.getChildCount(); i++) { + View v = viewGroup.getChildAt(i); + if (v instanceof ViewGroup) { + setEnabledSub(enabled, (ViewGroup) v); + } else { + setEnabled(enabled, v); + } + } + } + } + + /** + * 设置控件可用与否 (置灰) + * + * @param enabled + * 是否可用 + */ + public static void setEnabledEX(boolean enabled, View... views) { + for (View view : views) { + if (enabled) { + view.setEnabled(enabled); + view.clearAnimation(); + } else { + Animation aniAlp = new AlphaAnimation(1f, 0.5f); + aniAlp.setDuration(0); + aniAlp.setInterpolator(new AccelerateDecelerateInterpolator()); + aniAlp.setFillEnabled(true); + aniAlp.setFillAfter(true); + view.startAnimation(aniAlp); + view.setEnabled(enabled); + } + } + } + + /** + * 遍历布局,禁用/启用所有子控件 + *+ *
+ * @param enabled + */ + public static void setEnabledSubEX(boolean enabled, ViewGroup... viewGroups) { + for (ViewGroup viewGroup : viewGroups) { + setEnabledEX(enabled, viewGroup); + for (int i = 0; i < viewGroup.getChildCount(); i++) { + View v = viewGroup.getChildAt(i); + if (v instanceof ViewGroup) { + setEnabledSubEX(enabled, (ViewGroup) v); + } else { + setEnabledEX(enabled, v); + } + } + } + } + + /** + * 隐藏/显示 + *+ *
+ * @param visibility + * @param views + */ + public static void setVisibility(int visibility, View... views) { + for (View view : views) { + view.setVisibility(visibility); + } + } +} diff --git a/DeviceAddModule/src/main/java/com/mm/android/deviceaddmodule/mobilecommon/utils/UIUtils.java b/DeviceAddModule/src/main/java/com/mm/android/deviceaddmodule/mobilecommon/utils/UIUtils.java new file mode 100644 index 0000000..6991ec8 --- /dev/null +++ b/DeviceAddModule/src/main/java/com/mm/android/deviceaddmodule/mobilecommon/utils/UIUtils.java @@ -0,0 +1,989 @@ +package com.mm.android.deviceaddmodule.mobilecommon.utils; + +import android.annotation.SuppressLint; +import android.app.Activity; +import android.app.ActivityManager; +import android.content.ComponentName; +import android.content.Context; +import android.graphics.Rect; +import android.graphics.drawable.GradientDrawable; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentActivity; +import android.support.v4.app.FragmentManager; +import android.text.TextPaint; +import android.util.DisplayMetrics; +import android.util.TypedValue; +import android.view.TouchDelegate; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; +import android.view.animation.AccelerateDecelerateInterpolator; +import android.view.animation.AlphaAnimation; +import android.view.animation.Animation; +import android.widget.EditText; +import android.widget.TextView; + +import com.mm.android.deviceaddmodule.R; + +import java.lang.reflect.Field; +import java.util.List; + +public class UIUtils { + private static final String TAG = "UIUtils"; + private static long mLastClickTime; + + private static float sDensity = -1; + + /** + * 获取屏幕像素密度 + */ + public static float getScreenDensity(Context context) { + if(context == null)return sDensity; + DisplayMetrics dm = context.getApplicationContext().getResources().getDisplayMetrics(); + sDensity = dm.density; + + return dm.density; + } + + + // 将px值转换为dip或dp值,保证尺寸大小不变 + public static int px2dip(DisplayMetrics dM, float pxValue) { + final float scale = dM.density; + return (int) (pxValue / scale + 0.5f); + } + + // 将dip或dp值转换为px值,保证尺寸大小不变 + public static int dip2px(DisplayMetrics dM, float dipValue) { + final float scale = dM.density; + return (int) (dipValue * scale + 0.5f); + } + + /** + * 获取当前屏幕宽度 + */ + public static int getDefaultDialogWidth(Context context) { + return getScreenWidth(context) * 4 / 5; + } + /** + * 获取当前屏幕宽度 + */ + public static int getScreenWidth(Context context) { + if(context == null)return -1; + DisplayMetrics dm = context.getApplicationContext().getResources().getDisplayMetrics(); + return dm.widthPixels; + } + + public static int getDefaultDialogWidthWithLandscape(Context context){ + return getScreenHeight(context) * 4 / 5; + } + + /** + * 获取当前屏幕高度 + */ + public static int getScreenHeight(Context context) { + if(context == null)return -1; + DisplayMetrics dm = context.getApplicationContext().getResources().getDisplayMetrics(); + return dm.heightPixels; + } + + // 将px值转换为dip或dp值,保证尺寸大小不变 + public static int px2dip(Context context, float pxValue) { + final float scale = context.getResources().getDisplayMetrics().density; + return (int) (pxValue / scale + 0.5f); + } + + // 将dip或dp值转换为px值,保证尺寸大小不变 + public static int dip2px(Context context, float dipValue) { + final float scale = context.getResources().getDisplayMetrics().density; + return (int) (dipValue * scale + 0.5f); + } + + + // 将px值转换为sp值,保证文字大小不变 + public static int px2sp(Context context, float pxValue) { + final float fontScale = context.getResources().getDisplayMetrics().scaledDensity; + return (int) (pxValue / fontScale + 0.5f); + } + + // 将sp值转换为px值,保证文字大小不变 + public static int sp2px(Context context, float spValue) { + final float fontScale = context.getResources().getDisplayMetrics().scaledDensity; + return (int) (spValue * fontScale + 0.5f); + } + + // 屏幕宽度(像素) + public static int getWindowWidth(Activity context) { + DisplayMetrics metric = new DisplayMetrics(); + context.getWindowManager().getDefaultDisplay().getMetrics(metric); + return metric.widthPixels; + } + + // 屏幕高度(像素) + public static int getWindowHeight(Activity context) { + DisplayMetrics metric = new DisplayMetrics(); + context.getWindowManager().getDefaultDisplay().getMetrics(metric); + return metric.heightPixels; + } + + + /** + * 检测是否重复点击事件,默认时间为800毫秒 + * + * @return + */ + public static boolean isFastDoubleClick() { + long time = System.currentTimeMillis(); + long timeD = time - mLastClickTime; + if (0 < timeD && timeD < 800) { + return true; + } + mLastClickTime = time; + return false; + } + + /** + * 将当前activity拉到前台 + * + * @param paramActivity + */ + public static void goForeground(Activity paramActivity) { + if (paramActivity == null) return; + Window localWindow = paramActivity.getWindow(); + if (localWindow != null) { + localWindow.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); + localWindow.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED); + localWindow.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON); + } + } + + + /** + * 检测在规定的时间里面是否重复点击事件 + * + * @return + */ + public static boolean isFastDoubleClick(long elapse) { + long time = System.currentTimeMillis(); + long timeD = time - mLastClickTime; + if (0 < timeD && timeD < elapse) { + return true; + } + mLastClickTime = time; + return false; + } + /** + * 检测在100ms规定的时间里面是否快速触发相同方法两次,针对误触发情况的兼容 + * + * @return + */ + public static boolean isFastCallFuncTwice() { + long time = System.currentTimeMillis(); + long timeD = time - mLastClickTime; + if (0 < timeD && timeD < 100) { + return true; + } + mLastClickTime = time; + return false; + } + /** + * 进入全屏 + * + * @param activity + */ + public static void setFullScreen(Activity activity) { + activity.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + } + + /** + * 退出全屏 + * + * @param activity + */ + public static void quitFullScreen(Activity activity) { + if (activity == null) { + return; + } + final WindowManager.LayoutParams attrs = activity.getWindow().getAttributes(); + attrs.flags &= (~WindowManager.LayoutParams.FLAG_FULLSCREEN); + activity.getWindow().setAttributes(attrs); + activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); + } + + /** + * 输入框禁止复制,粘贴 + * + * @param editText + */ + public static void UnCopyAble(EditText editText) { + if (editText == null) { + return; + } + editText.setLongClickable(false); + } + + /** + * 获取状态栏高度 + *+ *
+ */ + public static int getStatusBarHeight(Context context) { + Class> c = null; + Object object = null; + Field field = null; + int x = 0; + int statusBar = 0; + try { + c = Class.forName("com.android.internal.R$dimen"); + object = c.newInstance(); + field = c.getField("status_bar_height"); + x = Integer.parseInt(field.get(object).toString()); + statusBar = context.getResources().getDimensionPixelSize(x); + } catch (Exception e) { + e.printStackTrace(); + } + return statusBar == 0 ? dp2px(context, 20) : statusBar; + } + + /** + * 设置按钮选中与否 + *+ *
+ * + * @param selected + * @param views + */ + public static void setSelected(boolean selected, View... views) { + for (View view : views) { + view.setSelected(selected); + } + } + + public static void setSelected(boolean selected, ViewGroup... viewGroups) { + for (ViewGroup viewGroup : viewGroups) { + viewGroup.setSelected(selected); + for (int i = 0; i < viewGroup.getChildCount(); i++) { + View v = viewGroup.getChildAt(i); + if (v instanceof ViewGroup) { + setSelected(selected, (ViewGroup) v); + } else { + setSelected(selected, v); + } + } + } + } + + /** + * 设置空间是否可用(不置灰) + *+ *
+ * + * @param enabled + * @param views + */ + public static void setEnabled(boolean enabled, View... views) { + for (View view : views) { + view.setEnabled(enabled); + } + } + + /** + * 启用/禁用控件,包括所有子控件 + */ + public static void setEnabledSub(boolean enabled, ViewGroup... viewGroups) { + for (ViewGroup viewGroup : viewGroups) { + viewGroup.setEnabled(enabled); + for (int i = 0; i < viewGroup.getChildCount(); i++) { + View v = viewGroup.getChildAt(i); + if (v instanceof ViewGroup) { + setEnabledSub(enabled, (ViewGroup) v); + } else { + setEnabled(enabled, v); + } + } + } + } + + /** + * 启用/禁用 item + * + * @param enabled + * @param viewGroup + * @param tv + */ + public static void setDevDetailItemEnable(boolean enabled, ViewGroup viewGroup, TextView tv) { + setEnabledSub(enabled, viewGroup); + + if (tv == null) { + return; + } + if (enabled) { + tv.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.mobile_common_icon_nextarrow, 0); + } else { + tv.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0); + } + } + + /** + * 设置控件可用与否 (置灰) + * + * @param views 被设置的控件 + * @param enabled 是否可用 + */ + public static void setEnabledEX(boolean enabled, View... views) { + for (View view : views) { + if (enabled) { + view.setEnabled(enabled); + view.clearAnimation(); + } else { + Animation aniAlp = new AlphaAnimation(1f, 0.5f); + aniAlp.setDuration(0); + aniAlp.setInterpolator(new AccelerateDecelerateInterpolator()); + aniAlp.setFillEnabled(true); + aniAlp.setFillAfter(true); + view.startAnimation(aniAlp); + view.setEnabled(enabled); + } + } + } + + /** + * 遍历布局,禁用/启用所有子控件 + *+ *
+ * + * @param viewGroup + * @param enabled + */ + public static void setEnabledSubControls(ViewGroup viewGroup, boolean enabled) { + setEnabledEX(enabled, viewGroup); + for (int i = 0; i < viewGroup.getChildCount(); i++) { + View v = viewGroup.getChildAt(i); + if (v instanceof ViewGroup) { + setEnabledSubControls((ViewGroup) v, enabled); + } else { + setEnabledEX(enabled, v); + } + } + } + + /** + * 隐藏/显示 + *+ *
+ * + * @param visibility + * @param views + */ + public static void setVisibility(int visibility, View... views) { + for (View view : views) { + view.setVisibility(visibility); + } + } + + public static void expandViewTouchDelegate(final View view, final int top, final int bottom, final int left, + final int right) { + + ((View) view.getParent()).post(new Runnable() { + + @Override + public void run() { + Rect bounds = new Rect(); + view.setEnabled(true); + view.getHitRect(bounds); + + bounds.top -= top; + bounds.bottom += bottom; + bounds.left -= left; + bounds.right += right; + + TouchDelegate touchDelegate = new TouchDelegate(bounds, view); + + if (View.class.isInstance(view.getParent())) { + ((View) view.getParent()).setTouchDelegate(touchDelegate); + } + + } + }); + } + + + /** + * 设置一组控件显隐 + * + * @param views + * @param flags + */ + public static void setViewsVisibility(View[] views, int[] flags) { + if (views == null) { + return; + } + for (int i = 0; i < views.length; i++) { + if (views[i] != null) views[i].setVisibility(i < flags.length ? flags[i] : View.GONE); + } + } + + /** + * 设置控件显隐 + * + * @param view + * @param flag + */ + public static void setViewVisibility(View view, int flag) { + if (view == null) { + return; + } + view.setVisibility(flag); + } + + public static void setEnableWithAlphaChanged(View view, boolean enable) { + if (view == null) { + return; + } + view.setEnabled(enable); + view.setAlpha(enable ? 1f : 0.5f); + } + + public static void setEnabledAllInGroup(ViewGroup viewGroup, boolean enabled) { + if (viewGroup == null) { + return; + } + viewGroup.setEnabled(enabled); + for (int i = 0; i < viewGroup.getChildCount(); i++) { + View v = viewGroup.getChildAt(i); + if (v instanceof ViewGroup) { + setEnabledAllInGroup((ViewGroup) v, enabled); + } else { + v.setEnabled(enabled); + } + } + } + + public static int getEncryV2(int byAuthMode, int byEncrAlgr) { + int nEncryption = 0; + + if(byAuthMode == 6 && byEncrAlgr == 0) + { + nEncryption = 0; + } + else if(byAuthMode == 0 && byEncrAlgr == 0) + { + nEncryption = 1; + } + else if(byAuthMode == 0 && byEncrAlgr == 4) + { + nEncryption = 2; + } + else if(byAuthMode == 1 && byEncrAlgr == 4) + { + nEncryption = 3; + } + else if(byAuthMode == 2 && byEncrAlgr == 5) + { + nEncryption = 4; + } + else if(byAuthMode == 3 && byEncrAlgr == 5) + { + nEncryption = 5; + } + else if(byAuthMode == 4 && byEncrAlgr == 5) + { + nEncryption = 6; + } + else if(byAuthMode == 5 && byEncrAlgr == 5) + { + nEncryption = 7; + } + else if(byAuthMode == 2 && byEncrAlgr == 6) + { + nEncryption = 8; + } + else if(byAuthMode == 3 && byEncrAlgr == 6) + { + nEncryption = 9; + } + else if(byAuthMode == 4 && byEncrAlgr == 6) + { + nEncryption = 10; + } + else if(byAuthMode == 5 && byEncrAlgr == 6) + { + nEncryption = 11; + } + else if(byAuthMode == 2 && byEncrAlgr == 7) + { + nEncryption = 8; // 4或者8 + } + else if(byAuthMode == 3 && byEncrAlgr == 7) + { + nEncryption = 9; // 5或9 + } + else if(byAuthMode == 4 && byEncrAlgr == 7) + { + nEncryption = 10; // 6或10 + } + else if(byAuthMode == 5 && byEncrAlgr == 7) + { + nEncryption = 11; // 7或11 + } + else if(byAuthMode == 7) // 混合模式WPA-PSK|WPA2-PSK 3或5 + { + if(byEncrAlgr == 5) { + nEncryption = 7; // 5或7 + } + else if(byEncrAlgr == 6) + { + nEncryption = 11; // 9或11 + } + else if(byEncrAlgr == 7) + { + nEncryption = 11; // 5或7或9或11 + } + else + { + nEncryption = 12; + } + } + else if(byAuthMode == 8) // 混合模式WPA|WPA2 2或4 + { + if(byEncrAlgr == 5) { + nEncryption = 6; // 4或6 + } + else if(byEncrAlgr == 6) + { + nEncryption = 10; // 8或10 + } + else if(byEncrAlgr == 7) + { + nEncryption = 10; // 4或6或8或10 + } + else + { + nEncryption = 12; + } + } + else if(byAuthMode == 9) // 混合模式WPA|WPA-PSK 2或3 + { + if(byEncrAlgr == 5) { + nEncryption = 5; // 4或5 + } + else if(byEncrAlgr == 6) + { + nEncryption = 9; // 8或9 + } + else if(byEncrAlgr == 7) + { + nEncryption = 9; // 4或5或8或9 + } + else + { + nEncryption = 12; + } + } + else if(byAuthMode == 10) // 混合模式WPA2|WPA2-PSK 4或5 + { + if(byEncrAlgr == 5) { + nEncryption = 7; // 6或7 + } + else if(byEncrAlgr == 6) + { + nEncryption = 11; // 10或11 + } + else if(byEncrAlgr == 7) + { + nEncryption = 11; // 6或7或10或11 + } + else + { + nEncryption = 12; + } + } + else if(byAuthMode == 11) // 混合模式WPA|WPA-PSK|WPA2|WPA2-PSK 2或3或4或5 + { + if(byEncrAlgr == 5) { + nEncryption = 7; // 4或5或6或7 + } + else if(byEncrAlgr == 6) + { + nEncryption = 11; // 8或9或10或11 + } + else if(byEncrAlgr == 7) + { + nEncryption = 11; // 4或5或6或7或8或9或10或11 + } + else + { + nEncryption = 12; + } + } else { + nEncryption = 12; + } + return nEncryption; + } + + public static int getEncry(int byAuthMode, int byEncrAlgr) { + int nEncryption = 0; + + if(byAuthMode == 6 && byEncrAlgr == 0) + { + nEncryption = 0; + } + else if(byAuthMode == 0 && byEncrAlgr == 0) + { + nEncryption = 1; + } + else if(byAuthMode == 0 && byEncrAlgr == 1) + { + nEncryption = 2; + } + else if(byAuthMode == 1 && byEncrAlgr == 1) + { + nEncryption = 3; + } + else if(byAuthMode == 2 && byEncrAlgr == 2) + { + nEncryption = 4; + } + else if(byAuthMode == 3 && byEncrAlgr == 2) + { + nEncryption = 5; + } + else if(byAuthMode == 4 && byEncrAlgr == 2) + { + nEncryption = 6; + } + else if(byAuthMode == 5 && byEncrAlgr == 2) + { + nEncryption = 7; + } + else if(byAuthMode == 2 && byEncrAlgr == 3) + { + nEncryption = 8; + } + else if(byAuthMode == 3 && byEncrAlgr == 3) + { + nEncryption = 9; + } + else if(byAuthMode == 4 && byEncrAlgr == 3) + { + nEncryption = 10; + } + else if(byAuthMode == 5 && byEncrAlgr == 3) + { + nEncryption = 11; + } + else if(byAuthMode == 2 && byEncrAlgr == 4) + { + nEncryption = 8; // 4或者8 + } + else if(byAuthMode == 3 && byEncrAlgr == 4) + { + nEncryption = 9; // 5或9 + } + else if(byAuthMode == 4 && byEncrAlgr == 4) + { + nEncryption = 10; // 6或10 + } + else if(byAuthMode == 5 && byEncrAlgr == 4) + { + nEncryption = 11; // 7或11 + } + else if(byAuthMode == 7) // 混合模式WPA-PSK|WPA2-PSK 3或5 + { + if(byEncrAlgr == 2) { + nEncryption = 7; // 5或7 + } + else if(byEncrAlgr == 3) + { + nEncryption = 11; // 9或11 + } + else if(byEncrAlgr == 4) + { + nEncryption = 11; // 5或7或9或11 + } + else + { + nEncryption = 12; + } + } + else if(byAuthMode == 8) // 混合模式WPA|WPA2 2或4 + { + if(byEncrAlgr == 2) { + nEncryption = 6; // 4或6 + } + else if(byEncrAlgr == 3) + { + nEncryption = 10; // 8或10 + } + else if(byEncrAlgr == 4) + { + nEncryption = 10; // 4或6或8或10 + } + else + { + nEncryption = 12; + } + } + else if(byAuthMode == 9) // 混合模式WPA|WPA-PSK 2或3 + { + if(byEncrAlgr == 2) { + nEncryption = 5; // 4或5 + } + else if(byEncrAlgr == 3) + { + nEncryption = 9; // 8或9 + } + else if(byEncrAlgr == 4) + { + nEncryption = 9; // 4或5或8或9 + } + else + { + nEncryption = 12; + } + } + else if(byAuthMode == 10) // 混合模式WPA2|WPA2-PSK 4或5 + { + if(byEncrAlgr == 2) { + nEncryption = 7; // 6或7 + } + else if(byEncrAlgr == 3) + { + nEncryption = 11; // 10或11 + } + else if(byEncrAlgr == 4) + { + nEncryption = 11; // 6或7或10或11 + } + else + { + nEncryption = 12; + } + } + else if(byAuthMode == 11) // 混合模式WPA|WPA-PSK|WPA2|WPA2-PSK 2或3或4或5 + { + if(byEncrAlgr == 2) { + nEncryption = 7; // 4或5或6或7 + } + else if(byEncrAlgr == 3) + { + nEncryption = 11; // 8或9或10或11 + } + else if(byEncrAlgr == 4) + { + nEncryption = 11; // 4或5或6或7或8或9或10或11 + } + else + { + nEncryption = 12; + } + } else { + nEncryption = 12; + } + return nEncryption; + } + + public static int getEncry4Sc(int byAuthMode, int byEncrAlgr) { + + int nEncryption = 0; + + if (byAuthMode == 6 && byEncrAlgr == 0) { + nEncryption = 0; + } else if (byAuthMode == 0 && byEncrAlgr == 0) { + nEncryption = 1; + } else if (byAuthMode == 0 && byEncrAlgr == 4) { + nEncryption = 13; + } else if (byAuthMode == 1 && byEncrAlgr == 4) { + nEncryption = 14; + } else if (byAuthMode == 2 && byEncrAlgr == 5) { + nEncryption = 8; + } else if (byAuthMode == 3 && byEncrAlgr == 5) { + nEncryption = 4; + } else if (byAuthMode == 4 && byEncrAlgr == 5) { + nEncryption = 10; + } else if (byAuthMode == 5 && byEncrAlgr == 5) { + nEncryption = 6; + } else if (byAuthMode == 2 && byEncrAlgr == 6) { + nEncryption = 9; + } else if (byAuthMode == 3 && byEncrAlgr == 6) { + nEncryption = 5; + } else if (byAuthMode == 4 && byEncrAlgr == 6) { + nEncryption = 11; + } else if (byAuthMode == 5 && byEncrAlgr == 6) { + nEncryption = 7; + } else if (byAuthMode == 2 && byEncrAlgr == 7) { + nEncryption = 9; // 8或者9 + } else if (byAuthMode == 3 && byEncrAlgr == 7) { + nEncryption = 5; // 4或5 + } else if (byAuthMode == 4 && byEncrAlgr == 7) { + nEncryption = 11; // 10或11 + } else if (byAuthMode == 5 && byEncrAlgr == 7) { + nEncryption = 7; // 6或7 + } else if (byAuthMode == 7) // 混合模式WPA-PSK|WPA2-PSK 3或5 + { + if (byEncrAlgr == 5) { + nEncryption = 6; // 4或6 + } else if (byEncrAlgr == 6) { + nEncryption = 7; // 5或7 + } else if (byEncrAlgr == 7) { + nEncryption = 7; // 4或5或6或7 + } else { + nEncryption = 12; + } + } else if (byAuthMode == 8) // 混合模式WPA|WPA2 2或4 + { + if (byEncrAlgr == 5) { + nEncryption = 10; // 8或10 + } else if (byEncrAlgr == 6) { + nEncryption = 11; // 9或11 + } else if (byEncrAlgr == 7) { + nEncryption = 10; // 8或9或10或11 + } else { + nEncryption = 12; + } + } else if (byAuthMode == 9) // 混合模式WPA|WPA-PSK 2或3 + { + if (byEncrAlgr == 5) { + nEncryption = 8; // 4或8 + } else if (byEncrAlgr == 6) { + nEncryption = 9; // 5或9 + } else if (byEncrAlgr == 7) { + nEncryption = 9; // 4或5或8或9 + } else { + nEncryption = 12; + } + } else if (byAuthMode == 10) // 混合模式WPA2|WPA2-PSK 4或5 + { + if (byEncrAlgr == 5) { + nEncryption = 10; // 6或10 + } else if (byEncrAlgr == 6) { + nEncryption = 11; // 7或11 + } else if (byEncrAlgr == 7) { + nEncryption = 11; // 6或7或10或11 + } else { + nEncryption = 12; + } + } else if (byAuthMode == 11) // 混合模式WPA|WPA-PSK|WPA2|WPA2-PSK 2或3或4或5 + { + if (byEncrAlgr == 5) { + nEncryption = 10; // 4或6或8或10 + } else if (byEncrAlgr == 6) { + nEncryption = 11; // 5或7或9或11 + } else if (byEncrAlgr == 7) { + nEncryption = 11; // 4或5或6或7或8或9或10或11 + } else { + nEncryption = 12; + } + } else { + nEncryption = 12; + } + return nEncryption; + } + + public static Fragment getVisibleFragment(FragmentActivity activity) { + FragmentManager fragmentManager = activity.getSupportFragmentManager(); + @SuppressLint("RestrictedApi") List+ * 工具类使用说明:左按钮,左内按钮,中间按钮,右内按钮,右按钮,均支持图片和文字背景二选一,左右按钮默认支持图片,中间按钮默认支持文字 + *
+ *+ * xml使用注意:需要在xml文件中使用style="@style/common_titile" + *
+ *+ * 函数使用介绍: + *
+ *+ * initView(int tvLeftResId, int tvRightResId, int tvCenterResId) 初始化控件:左按钮,中间按钮,右按钮,属于普通用法 + *
+ *+ * getTextViewXXX() 获取xxx按钮,进行自定义功能扩展操作。例如,实现展开下来listview的功能 + *
+ *+ * setTitleXXXView(int resId, int colorId, int textSizeDimenId) 设置xxx按钮的文字,文字颜色,文字大小 + *
+ *+ * setTitleXXX(int resId) 设置xxx按钮图片或文字 + *
+ *+ * setTextColorXXX(int colorId) 设置xxx按钮文字的颜色资源 + *
+ *+ * setTextSizeXXX(int textSizeDimenId) 设置xxx按钮文字的大小 + *
+ *+ * setTitleTextXXX(int resId) 通过resId设置xxx按钮的文字 + *
+ *+ * setTitleTextXXX(String titleTextXXX) 通过String设置xxx按钮的文字 + *
+ *+ * setVisibleXXX(int flag) 通过flag设置xxx是否隐藏,flag:View.GONE,View.INVISIBLE,View.VISIBLE; + *
+ */ +public class CommonSubTitle extends RelativeLayout +// implements OnClickListener +{ + /** + * 左侧按钮ID + */ + public static final int ID_LEFT = 0; + + /** + * 左侧内按钮ID + */ + public static final int ID_LEFT_2 = 1; + + /** + * 右侧按钮ID + */ + public static final int ID_RIGHT = 2; + + /** + * 右侧内按钮ID + */ + public static final int ID_RIGHT_2 = 3; + + /** + * 中间按钮ID, 暂时不加监听器 + */ + public static final int ID_CENTER = 4; + + /** + * 中间下方按钮ID, 暂时不加监听器 + */ + public static final int ID_CENTER_SUB = 5; + + /** + * 左侧按钮/ 左侧按钮LinearLayout + */ + private TextView mTitleLeftTv; + + private LinearLayout mTitleLeftLl; + + /** + * 左侧按钮(靠内) /左侧按钮(靠内)LinearLayout + */ + private TextView mTitleLeft2Tv; + + private LinearLayout mTitleLeft2Ll; + + /** + * 右侧按钮 /右侧按钮LinearLayout + */ + private TextView mTitleRightTv; + + private LinearLayout mTitleRightLl; + + /** + * 右侧按钮(靠内) /右侧按钮(靠内)LinearLayout + */ + private TextView mTitleRight2Tv; + + private LinearLayout mTitleRight2Ll; + + /** + * 大标题(上)/小标题(下)LinearLayout + */ + private LinearLayout mTitleCenterLl; + + private TextView mTitleCenterTv; + + private TextView mTitleCenterSubTv; + + /** + * 点击监听 + */ + private OnTitleSubClickListener mListener; + + private View mBottomV; + + /** + * 默认隐藏左2和右2的按钮 ,创建一个新的实例CommonTitle. + * + * @param context + * @param attrs + */ + public CommonSubTitle(Context context, AttributeSet attrs) { + super(context, attrs); + LayoutInflater.from(context).inflate(R.layout.widget_common_sub_title, this); + initView(); + setListeners(); + setVisibleLeft2(View.GONE); + setVisibleRight2(View.GONE); + } + + private void initView() { + mBottomV = findViewById(R.id.v_bottom_line); + mTitleLeftLl = findViewById(R.id.ll_title_left); + mTitleLeft2Ll = findViewById(R.id.ll_title_left2); + mTitleRightLl = findViewById(R.id.ll_title_right); + mTitleRight2Ll = findViewById(R.id.ll_title_right2); + mTitleCenterLl = findViewById(R.id.ll_title_center); + + mTitleLeftTv = findViewById(R.id.tv_title_left); + mTitleLeft2Tv = findViewById(R.id.tv_title_left2); + mTitleRightTv = findViewById(R.id.tv_title_right); + mTitleRight2Tv = findViewById(R.id.tv_title_right2); + mTitleCenterTv = findViewById(R.id.tv_title_center); + mTitleCenterSubTv = findViewById(R.id.tv_title_center_sub); + + mTitleLeftTv.setTextColor(getResources().getColor(R.color.common_title_text_color)); + mTitleLeft2Tv.setTextColor(getResources().getColor(R.color.common_title_text_color)); + mTitleRightTv.setTextColor(getResources().getColor(R.color.common_title_text_color)); + mTitleRight2Tv.setTextColor(getResources().getColor(R.color.common_title_text_color)); + mTitleCenterTv.setTextColor(getResources().getColor(R.color.c2)); + + mTitleLeftTv.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources() + .getDimensionPixelSize(R.dimen.text_size_mid)); + mTitleLeft2Tv.setTextSize(TypedValue.COMPLEX_UNIT_PX, + getResources().getDimensionPixelSize(R.dimen.text_size_mid)); + mTitleRightTv.setTextSize(TypedValue.COMPLEX_UNIT_PX, + getResources().getDimensionPixelSize(R.dimen.text_size_mid)); + mTitleRight2Tv.setTextSize(TypedValue.COMPLEX_UNIT_PX, + getResources().getDimensionPixelSize(R.dimen.text_size_mid)); + mTitleCenterTv.setTextSize(TypedValue.COMPLEX_UNIT_PX, + getResources().getDimensionPixelSize(R.dimen.text_size_large)); + } + + private void setListeners() { + mTitleLeftLl.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + if (mListener != null) { + mListener.onCommonTitleClick(ID_LEFT); + } + + } + }); + + mTitleLeft2Ll.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + if (mListener != null) { + mListener.onCommonTitleClick(ID_LEFT_2); + } + + } + }); + + mTitleRightLl.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + if (mListener != null) { + mListener.onCommonTitleClick(ID_RIGHT); + } + + } + }); + + mTitleRight2Ll.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + if (mListener != null) + mListener.onCommonTitleClick(ID_RIGHT_2); + } + }); + + mTitleCenterLl.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + if (mListener != null) + mListener.onCommonTitleClick(ID_CENTER); + } + }); + } + + /** + *+ * 初始化参数,按钮均可支持图片或者文字背景 + * @param tvLeftResId + * 左按钮 + * @param tvRightResId + * 右按钮 + * @param tvCenterResId + * 中间按钮 + */ + + public void initView(int tvLeftResId, int tvRightResId, int tvCenterResId) { + setTitleLeftView(tvLeftResId, 0, 0); + setTitleRightView(tvRightResId, 0, 0); + setTitleCenterView(tvCenterResId, 0, 0); + } + + public TextView getTextViewCenter() { + return mTitleCenterTv; + } + + public TextView getTextViewCenterSub() { + return mTitleCenterSubTv; + } + + /** + *
+ * 设置是否选中按钮 + *
+ * @param selected + * {true,false} + * @param id + * {ID_LEFT ,ID_LEFT_2,ID_RIGHT,ID_RIGHT_2,ID_CENTER} + */ + public void setTitleSelected(boolean selected, int id) { + View v = findViewByID(id); + if (v != null) { + v.setSelected(selected); + } + } + + /** + *+ * 设置按钮是否可用 + *
+ */ + public void setTitleEnabled(boolean enabled, int id) { + View v = findParentViewById(id); + if (v != null) { + UIUtils.setEnabledEX(enabled, v); + } + } + + private View findParentViewById(int id) { + switch (id) { + case ID_LEFT: + return mTitleLeftLl; + case ID_LEFT_2: + return mTitleLeft2Ll; + case ID_RIGHT: + return mTitleRightLl; + case ID_RIGHT_2: + return mTitleRight2Ll; + case ID_CENTER: + return mTitleCenterLl; + default: + return null; + } + } + + private View findViewByID(int id) { + switch (id) { + case ID_LEFT: + return mTitleLeftTv; + case ID_LEFT_2: + return mTitleLeft2Tv; + case ID_RIGHT: + return mTitleRightTv; + case ID_RIGHT_2: + return mTitleRight2Tv; + case ID_CENTER: + return mTitleCenterTv; + case ID_CENTER_SUB: + return mTitleCenterSubTv; + default: + return null; + } + } + + /*------------------------------------------getTextView END------------------------------*/ + + /*-----------------------------------setTitleView START---------------------------------*/ + public void setTitleLeftView(int resId, int colorId, int textSizeDimenId) { + setTitleLeft(resId); + setTextColorLeft(colorId); + setTextSizeLeft(textSizeDimenId); + } + + public void setTitleRightView(int resId, int colorId, int textSizeDimenId) { + setTitleRight(resId); + setTextColorRight(colorId); + setTextSizeRight(textSizeDimenId); + } + + public void setTitleCenterView(int resId, int colorId, int textSizeDimenId) { + setTitleCenter(resId); + setTextColorCenter(colorId); + setTextSizeCenter(textSizeDimenId); + } + + /*-----------------------------------setTitleView END---------------------------------*/ + /*------------------------------------------setTitle START------------------------------*/ + /** + *+ * 设置左边按钮图片或文字 + *
+ * @param leftResId + */ + public void setTitleLeft(int leftResId) { + if (mTitleLeftTv != null) { + if (leftResId != 0) { + if (mTitleLeftLl != null && mTitleLeftLl.getVisibility() != View.VISIBLE) + mTitleLeftLl.setVisibility(VISIBLE); + Drawable drawable = null; + try { + drawable = getResources().getDrawable(leftResId); + } catch (Exception e) { + // e.printStackTrace(); + } finally { + if (drawable != null) { + mTitleLeftTv.setBackgroundResource(leftResId); + mTitleLeftTv.setText(null); + } else { + mTitleLeftTv.setText(leftResId); + mTitleLeftTv.setBackgroundResource(0); + } + } + } else { + if (mTitleLeftLl != null) + mTitleLeftLl.setVisibility(INVISIBLE); + } + } + } + + /** + *+ * 设置左边按钮图片或文字 + *
+ */ + public void setTitleLeft2(int left2ResId) { + if (mTitleLeft2Tv != null) { + if (left2ResId != 0) { + if (mTitleLeft2Ll != null && mTitleLeft2Ll.getVisibility() != View.VISIBLE) + mTitleLeft2Ll.setVisibility(VISIBLE); + Drawable drawable = null; + try { + drawable = getResources().getDrawable(left2ResId); + } catch (Exception e) { + // e.printStackTrace(); + } finally { + if (drawable != null) { + mTitleLeft2Tv.setBackgroundResource(left2ResId); + mTitleLeft2Tv.setText(null); + } else { + mTitleLeft2Tv.setText(left2ResId); + mTitleLeft2Tv.setBackgroundResource(0); + } + } + } else { + if (mTitleLeft2Ll != null) + mTitleLeft2Ll.setVisibility(INVISIBLE); + } + } + } + + /** + *+ * 设置右边按钮图片或文字 + *
+ * + * @param rightResId + */ + public void setTitleRight(int rightResId) { + if (mTitleRightTv != null) { + if (rightResId != 0) { + if (mTitleRightLl != null && mTitleRightLl.getVisibility() != View.VISIBLE) + mTitleRightLl.setVisibility(VISIBLE); + Drawable drawable = null; + try { + drawable = getResources().getDrawable(rightResId); + } catch (Exception e) { + // e.printStackTrace(); + } finally { + if (drawable != null) { + mTitleRightTv.setBackgroundResource(rightResId); + mTitleRightTv.setText(null); + } else { + mTitleRightTv.setText(rightResId); + mTitleRightTv.setBackgroundResource(0); + } + + } + } else { + if (mTitleRightLl != null) + mTitleRightLl.setVisibility(INVISIBLE); + } + } + } + + public void setTitleRight2(int right2ResId) { + if (mTitleRight2Tv != null) { + if (right2ResId != 0) { + if (mTitleRight2Ll != null && mTitleRight2Ll.getVisibility() != View.VISIBLE) + mTitleRight2Ll.setVisibility(VISIBLE); + Drawable drawable = null; + try { + drawable = getResources().getDrawable(right2ResId); + } catch (Exception e) { + // e.printStackTrace(); + } finally { + if (drawable != null) { + mTitleRight2Tv.setBackgroundResource(right2ResId); + mTitleRight2Tv.setText(null); + } else { + mTitleRight2Tv.setText(right2ResId); + mTitleRight2Tv.setBackgroundResource(0); + } + } + } else { + if (mTitleRight2Ll != null) + mTitleRight2Ll.setVisibility(INVISIBLE); + } + } + } + + /** + *+ * 设置中间按钮图片或文字 + *
+ * + * @param centerResId + */ + public void setTitleCenter(int centerResId) { + if (mTitleCenterTv != null) { + if (centerResId != 0) { + if (mTitleCenterLl != null && mTitleCenterLl.getVisibility() != View.VISIBLE) + mTitleCenterLl.setVisibility(VISIBLE); + Drawable drawable = null; + try { + drawable = getResources().getDrawable(centerResId); + } catch (Exception e) { + // e.printStackTrace(); + } finally { + if (drawable != null) { + mTitleCenterTv.setBackgroundResource(centerResId); + mTitleCenterTv.setText(null); + } else { + mTitleCenterTv.setText(centerResId); + mTitleCenterTv.setBackgroundResource(0); + } + } + } else { + if (mTitleCenterLl != null) + mTitleCenterLl.setVisibility(INVISIBLE); + } + } + } + + /** + *+ * 设置中间下方按钮图片或文字 + *
+ * + * @param centerResId + */ + public void setTitleCenterSub(int centerResId) { + if (mTitleCenterSubTv != null) { + if (centerResId != 0) { + if (mTitleCenterLl != null && mTitleCenterLl.getVisibility() != View.VISIBLE) + mTitleCenterLl.setVisibility(VISIBLE); + Drawable drawable = null; + try { + drawable = getResources().getDrawable(centerResId); + } catch (Exception e) { + // e.printStackTrace(); + } finally { + if (drawable != null) { + mTitleCenterSubTv.setBackgroundResource(centerResId); + mTitleCenterSubTv.setText(null); + } else { + mTitleCenterSubTv.setText(centerResId); + mTitleCenterSubTv.setBackgroundResource(0); + } + } + } else { + if (mTitleCenterLl != null) + mTitleCenterLl.setVisibility(INVISIBLE); + } + } + } + + /*------------------------------------------setTitle END------------------------------*/ + /*-----------------------------------------setTextColor START--------------------------------------*/ + public void setTextColorLeft(int colorId) { + if (mTitleLeftTv != null) { + mTitleLeftTv.setTextColor(colorId != 0 ? getResources().getColor(colorId) : getResources().getColor( + R.color.common_title_text_color)); + } + } + + public void setTextColorLeft2(int colorId) { + if (mTitleLeft2Tv != null) { + mTitleLeft2Tv.setTextColor(colorId != 0 ? getResources().getColor(colorId) : getResources().getColor( + R.color.common_title_text_color)); + } + } + + public void setTextColorRight(int colorId) { + if (mTitleRightTv != null) { + mTitleRightTv.setTextColor(colorId != 0 ? getResources().getColorStateList(colorId) : getResources() + .getColorStateList(R.color.common_title_text_color)); + } + } + + public void setTextColorRight2(int colorId) { + if (mTitleRight2Tv != null) { + mTitleRight2Tv.setTextColor(colorId != 0 ? getResources().getColor(colorId) : getResources().getColor( + R.color.c43)); + } + } + + public void setTextColorCenter(int colorId) { + if (mTitleCenterTv != null) { + mTitleCenterTv.setTextColor(colorId != 0 ? getResources().getColor(colorId) : getResources().getColor( + R.color.c2)); + } + } + + public void setTextColorCenterSub(int colorId) { + if (mTitleCenterSubTv != null) { + mTitleCenterSubTv.setTextColor(colorId != 0 ? getResources().getColor(colorId) : getResources().getColor( + R.color.c2)); + } + } + + /*-----------------------------------------setTextColor END--------------------------------------*/ + /*-----------------------------------------setTextSize START--------------------------------------*/ + public void setTextSizeLeft(int textSizeDimenId) { + if (mTitleLeftTv != null) { + mTitleLeftTv.setTextSize(TypedValue.COMPLEX_UNIT_PX, + textSizeDimenId != 0 ? getResources().getDimensionPixelSize(textSizeDimenId) : getResources() + .getDimensionPixelSize(R.dimen.text_size_mid)); + } + } + + public void setTextSizeLeft2(int textSizeDimenId) { + if (mTitleLeft2Tv != null) { + mTitleLeft2Tv.setTextSize(TypedValue.COMPLEX_UNIT_PX, + textSizeDimenId != 0 ? getResources().getDimensionPixelSize(textSizeDimenId) : getResources() + .getDimensionPixelSize(R.dimen.text_size_mid)); + } + } + + public void setTextSizeRight(int textSizeDimenId) { + if (mTitleRightTv != null) { + mTitleRightTv.setTextSize(TypedValue.COMPLEX_UNIT_PX, + textSizeDimenId != 0 ? getResources().getDimensionPixelSize(textSizeDimenId) : getResources() + .getDimensionPixelSize(R.dimen.text_size_mid)); + } + } + + public void setTextSizeRight2(int textSizeDimenId) { + if (mTitleRight2Tv != null) { + mTitleRight2Tv.setTextSize(TypedValue.COMPLEX_UNIT_PX, + textSizeDimenId != 0 ? getResources().getDimensionPixelSize(textSizeDimenId) : getResources() + .getDimensionPixelSize(R.dimen.text_size_mid)); + } + } + + public void setTextSizeCenter(int textSizeDimenId) { + if (mTitleCenterTv != null) { + mTitleCenterTv.setTextSize(TypedValue.COMPLEX_UNIT_PX, + textSizeDimenId != 0 ? getResources().getDimensionPixelSize(textSizeDimenId) : getResources() + .getDimensionPixelSize(R.dimen.text_size_large)); + } + } + + public void setTextSizeCenterSub(int textSizeDimenId) { + if (mTitleCenterSubTv != null) { + mTitleCenterSubTv.setTextSize(TypedValue.COMPLEX_UNIT_PX, + textSizeDimenId != 0 ? getResources().getDimensionPixelSize(textSizeDimenId) : getResources() + .getDimensionPixelSize(R.dimen.text_size_small)); + } + } + + /*-----------------------------------------setTextSize END--------------------------------------*/ + + /*-----------------------------------------setIcon START--------------------------------------*/ + + public void setIconLeft(int resId) { + if (mTitleLeftLl != null) { + if (mTitleLeftLl.getVisibility() != View.VISIBLE) { + mTitleLeftLl.setVisibility(View.VISIBLE); + } + setTitleLeft(resId); + } + } + + public void setIconLeft2(int resId) { + if (mTitleLeft2Ll != null) { + if (mTitleLeft2Ll.getVisibility() != View.VISIBLE) { + mTitleLeft2Ll.setVisibility(View.VISIBLE); + } + setTitleLeft2(resId); + } + } + + public void setIconRight(int resId) { + if (mTitleRightLl != null) { + if (mTitleRightLl.getVisibility() != View.VISIBLE) { + mTitleRightLl.setVisibility(View.VISIBLE); + } + setTitleRight(resId); + } + } + + public void setIconRight2(int resId) { + if (mTitleRight2Ll != null) { + if (mTitleRight2Ll.getVisibility() != View.VISIBLE) { + mTitleRight2Ll.setVisibility(View.VISIBLE); + } + setTitleRight2(resId); + } + } + + public void setIconCenter(int resId) { + if (mTitleCenterLl != null) { + if (mTitleCenterLl.getVisibility() != View.VISIBLE) { + mTitleCenterLl.setVisibility(View.VISIBLE); + } + setTitleCenter(resId); + } + } + + /*-----------------------------------------setIcon END--------------------------------------*/ + /*-----------------------------------------setTextById START--------------------------------------*/ + + public void setTitleTextLeft(int resId) { + if (mTitleLeftLl != null) { + if (mTitleLeftLl.getVisibility() != View.VISIBLE) { + mTitleLeftLl.setVisibility(View.VISIBLE); + } + setTitleLeft(resId); + } + } + + public void setTitleTextLeft2(int resId) { + if (mTitleLeft2Ll != null) { + if (mTitleLeft2Ll.getVisibility() != View.VISIBLE) { + mTitleLeft2Ll.setVisibility(View.VISIBLE); + } + setTitleLeft(resId); + } + } + + public void setTitleTextRight(int resId) { + if (mTitleRightLl != null) { + if (mTitleRightLl.getVisibility() != View.VISIBLE) { + mTitleRightLl.setVisibility(View.VISIBLE); + } + setTitleRight(resId); + } + } + + public void setTitleTextRight2(int resId) { + if (mTitleRight2Ll != null) { + if (mTitleRight2Ll.getVisibility() != View.VISIBLE) { + mTitleRight2Ll.setVisibility(View.VISIBLE); + } + setTitleRight2(resId); + } + } + + public void setTitleTextCenter(int resId) { + if (mTitleCenterLl != null) { + if (mTitleCenterLl.getVisibility() != View.VISIBLE) { + mTitleCenterLl.setVisibility(View.VISIBLE); + } + setTitleCenter(resId); + } + } + + public void setTitleTextCenterSub(int resId) { + if (mTitleCenterLl != null) { + if (mTitleCenterLl.getVisibility() != View.VISIBLE) { + mTitleCenterLl.setVisibility(View.VISIBLE); + } + setTitleCenterSub(resId); + } + } + + /*-----------------------------------------setTextById END--------------------------------------*/ + /*-----------------------------------------setTextByString START--------------------------------------*/ + public void setTitleTextLeft(String titleTextLeft) { + if (mTitleLeftTv != null) { + if (mTitleLeftTv.getVisibility() != View.VISIBLE) { + mTitleLeftTv.setVisibility(View.VISIBLE); + } + mTitleLeftTv.setText(titleTextLeft); + mTitleLeftTv.setBackgroundResource(0); + } + } + + public void setTitleTextLeft2(String titleTextLeft2) { + if (mTitleLeft2Tv != null) { + if (mTitleLeft2Tv.getVisibility() != View.VISIBLE) { + mTitleLeft2Tv.setVisibility(View.VISIBLE); + } + mTitleLeft2Tv.setText(titleTextLeft2); + mTitleLeft2Tv.setBackgroundResource(0); + } + } + + public void setTitleTextRight(String titleTextRight) { + if (mTitleRightTv != null) { + if (mTitleRightTv.getVisibility() != View.VISIBLE) { + mTitleRightTv.setVisibility(View.VISIBLE); + } + mTitleRightTv.setText(titleTextRight); + mTitleRightTv.setBackgroundResource(0); + } + } + + public void setTitleTextRight2(String titleTextRight2) { + if (mTitleRight2Tv != null) { + if (mTitleRight2Tv.getVisibility() != View.VISIBLE) { + mTitleRight2Tv.setVisibility(View.VISIBLE); + } + mTitleRight2Tv.setText(titleTextRight2); + mTitleRight2Tv.setBackgroundResource(0); + } + } + + public void setTitleTextCenter(String titleTextCenter) { + if (mTitleCenterLl != null) { + if (mTitleCenterLl.getVisibility() != View.VISIBLE) { + mTitleCenterLl.setVisibility(View.VISIBLE); + } + mTitleCenterTv.setText(titleTextCenter); + mTitleCenterTv.setBackgroundResource(0); + } + } + + public void setTitleTextCenterSub(String titleTextCenter) { + if (mTitleCenterLl != null) { + if (mTitleCenterLl.getVisibility() != View.VISIBLE) { + mTitleCenterLl.setVisibility(View.VISIBLE); + } + mTitleCenterSubTv.setText(titleTextCenter); + mTitleCenterSubTv.setBackgroundResource(0); + } + } + + /*-----------------------------------------setTextByString END--------------------------------------*/ + /*-----------------------------------------setVisible START--------------------------------------*/ + + public void setVisibleLeft(int flag) { + if (mTitleLeftLl != null) { + mTitleLeftLl.setVisibility(flag); + } + } + + public void setVisibleLeft2(int flag) { + if (mTitleLeft2Ll != null) { + mTitleLeft2Ll.setVisibility(flag); + } + } + + public void setVisibleRight(int flag) { + if (mTitleRightLl != null) { + mTitleRightLl.setVisibility(flag); + } + } + + public void setVisibleRight2(int flag) { + if (mTitleRight2Ll != null) { + mTitleRight2Ll.setVisibility(flag); + } + } + + public void setVisibleCenter(int flag) { + if (mTitleCenterLl != null) { + mTitleCenterLl.setVisibility(flag); + } + } + + public void setVisibleCenterSub(int flag) { + if (mTitleCenterSubTv != null) { + mTitleCenterSubTv.setVisibility(flag); + } + } + + public void setVisibleBottom(int flag) { + if (mBottomV != null) { + mBottomV.setVisibility(flag); + } + } + + /*-----------------------------------------setVisible END--------------------------------------*/ + public void setOnTitleSubClickListener(OnTitleSubClickListener listener) { + mListener = listener; + } + + public interface OnTitleSubClickListener { + public void onCommonTitleClick(int id); + } +} diff --git a/DeviceAddModule/src/main/java/com/mm/android/deviceaddmodule/mobilecommon/widget/CommonSwitchTitle.java b/DeviceAddModule/src/main/java/com/mm/android/deviceaddmodule/mobilecommon/widget/CommonSwitchTitle.java new file mode 100644 index 0000000..a48752f --- /dev/null +++ b/DeviceAddModule/src/main/java/com/mm/android/deviceaddmodule/mobilecommon/widget/CommonSwitchTitle.java @@ -0,0 +1,485 @@ +package com.mm.android.deviceaddmodule.mobilecommon.widget; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.support.annotation.DrawableRes; +import android.support.annotation.StringRes; +import android.util.AttributeSet; +import android.util.TypedValue; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.mm.android.deviceaddmodule.R; +import com.mm.android.deviceaddmodule.mobilecommon.utils.UIUtils; + + +/** + *+ * xml使用注意:需要在xml文件中使用style="@style/common_switch_titile" + *
+ *+ * 函数使用介绍: + *
+ *+ * initView(int left, int right, int midleft, int midright) 初始化控件:左按钮,中间左按钮,中间右按钮,右按钮,属于普通用法 + *
+ */ +public class CommonSwitchTitle extends RelativeLayout { + + /** + * 左侧按钮ID + */ + public static final int ID_LEFT = 0; + + /** + * 右侧按钮ID + */ + public static final int ID_MID_LEFT = 1; + + /** + * 左侧按钮ID + */ + public static final int ID_MID_RIGHT = 2; + + /** + * 左侧按钮ID + */ + public static final int ID_RIGHT = 3; + + /** + * 左侧按钮 + */ + private TextView mTitleLeftTv; + + private LinearLayout mTitleLeftLl; + + /** + * 右侧按钮 + */ + private TextView mTitleRightTv; + + private LinearLayout mTitleRightLl; + + /** + * 文字标题(左) + */ + private TextView mMidLeftTv; + + /** + * 文字标题(右) + */ + private TextView mMidRightTv; + + /** + * 点击监听 + */ + private OnTitleClickListener mListener; + /** + * 底部横线 + */ + private View mBottomV; + /** + * tab切换区域 + */ + private ViewGroup mSwitchBtnLl; + /** + * 标题 + */ + private TextView mTitleTv; + + /** + * 记录中间的左右是文字还是图片,主要兼容国内外差异 + */ + private boolean mIsMidLeftDrawable; + + public CommonSwitchTitle(Context context, AttributeSet attrs) { + super(context, attrs); + + LayoutInflater.from(context).inflate(R.layout.mobile_common_widget_switch_title, this); + initView(); + setListeners(); + } + + private void initView() { + mTitleLeftLl = findViewById(R.id.ll_title_left); + mTitleRightLl = findViewById(R.id.ll_title_right); + mTitleLeftTv = findViewById(R.id.tv_title_left); + mTitleRightTv = findViewById(R.id.tv_title_right); + mMidLeftTv = findViewById(R.id.tag_left); + mMidRightTv = findViewById(R.id.tag_right); + mBottomV = findViewById(R.id.bottom_divider); + mTitleLeftTv.setTextColor(getResources().getColor(R.color.c0)); + mTitleRightTv.setTextColor(getResources().getColor(R.color.c0)); + mMidLeftTv.setTextColor(getResources().getColor(R.color.common_title_tab_text_color)); + mMidRightTv.setTextColor(getResources().getColor(R.color.common_title_tab_text_color)); + + mTitleLeftTv.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources() + .getDimensionPixelSize(R.dimen.mobile_common_text_size_mid)); + mTitleRightTv.setTextSize(TypedValue.COMPLEX_UNIT_PX, + getResources().getDimensionPixelSize(R.dimen.mobile_common_text_size_mid)); + mMidLeftTv.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources().getDimensionPixelSize(R.dimen.text_size_mid)); + mMidRightTv + .setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources().getDimensionPixelSize(R.dimen.text_size_mid)); + mSwitchBtnLl = findViewById(R.id.ll_switch_btn); + mTitleTv = findViewById(R.id.tv_title_center); + } + + + public void setSelect(boolean isRight) { + mSwitchBtnLl.setSelected(isRight); + mMidLeftTv.setTextColor(isRight ? getResources().getColor(R.color.c5) : getResources().getColor(R.color.c0)); + mMidRightTv.setTextColor(isRight?getResources().getColor(R.color.c0) : getResources().getColor(R.color.c5)); + } + + /** + * 切换标题栏展示样式 + * + * @param isSwitchMode + */ + public void changeTitleMode(boolean isSwitchMode) { + if (isSwitchMode) { + mSwitchBtnLl.setVisibility(VISIBLE); + mTitleTv.setVisibility(GONE); + } else { + mSwitchBtnLl.setVisibility(GONE); + mTitleTv.setVisibility(VISIBLE); + } + } + + /** + * 设置标题栏中间内容 + * + * @param resId + */ + public void setTitleCenter(int resId) { + mTitleTv.setText(getResources().getString(resId)); + } + + + private void setListeners() { + mTitleLeftLl.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View v) { + if (mListener != null) + mListener.onCommonTitleClick(ID_LEFT); + + } + }); + mTitleRightLl.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View v) { + if (mListener != null) + mListener.onCommonTitleClick(ID_RIGHT); + } + }); + mMidLeftTv.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View v) { + if (mIsMidLeftDrawable){ + UIUtils.setEnabled(false, v); + UIUtils.setEnabled(true, mMidRightTv); + }else{ + mSwitchBtnLl.setSelected(false); + } + + if (mListener != null) + mListener.onCommonTitleClick(ID_MID_LEFT); + } + }); + mMidRightTv.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View v) { + if (mIsMidLeftDrawable){ + UIUtils.setEnabled(false, v); + UIUtils.setEnabled(true, mMidLeftTv); + }else{ + mSwitchBtnLl.setSelected(true); + } + + if (mListener != null) + mListener.onCommonTitleClick(ID_MID_RIGHT); + } + }); + + } + + /** + * 初始化 + * + * @param left + * @param right + * @param midLeft + * @param midRight + */ + public void initView(int left, int right, int midLeft, int midRight) { + setTitleLeftView(left, 0, 0); + setTitleRightView(right, 0, 0); + Drawable drawable = null; + try { + drawable = getResources().getDrawable(midLeft); + } catch (Exception e) { + // e.printStackTrace(); + } finally { + if (drawable != null) { + mIsMidLeftDrawable = true; + setMidLeftImageSrc(midLeft); + } else { + mIsMidLeftDrawable = false; + setMidLeftText(midLeft); + } + } + try { + drawable = getResources().getDrawable(midRight); + } catch (Exception e) { + // e.printStackTrace(); + } finally { + if (drawable != null) { + setMidRightImageSrc(midRight); + } else { + setMidRightText(midRight); + } + } + } + + /*-----------------------------------setTitleXXXView setMidXXXView START---------------------------------*/ + public void setTitleLeftView(int resId, int colorId, int textSizeDimenId) { + setTitleLeft(resId); + setTextColorLeft(colorId); + setTextSizeLeft(textSizeDimenId); + } + + public void setTitleRightView(int resId, int colorId, int textSizeDimenId) { + setTitleRight(resId); + setTextColorRight(colorId); + setTextSizeRight(textSizeDimenId); + } + + + /*-----------------------------------setTitleXXXView setMidXXXView END---------------------------------*/ + /*------------------------------------------setTitle START------------------------------*/ + public void setTitleLeft(int leftResId) { + if (mTitleLeftTv != null) { + if (leftResId != 0) { + if (mTitleLeftLl != null && mTitleLeftLl.getVisibility() != View.VISIBLE) + mTitleLeftLl.setVisibility(VISIBLE); + Drawable drawable = null; + try { + drawable = getResources().getDrawable(leftResId); + } catch (Exception e) { + // e.printStackTrace(); + } finally { + if (drawable != null) { + mTitleLeftTv.setBackgroundResource(leftResId); + mTitleLeftTv.setText(null); + } else { + mTitleLeftTv.setText(leftResId); + mTitleLeftTv.setBackgroundResource(0); + } + } + } else { + if (mTitleLeftLl != null) + mTitleLeftLl.setVisibility(INVISIBLE); + } + } + } + + public void setTitleRight(int rightResId) { + if (mTitleRightTv != null) { + if (rightResId != 0) { + if (mTitleRightLl != null && mTitleRightLl.getVisibility() != View.VISIBLE) + mTitleRightLl.setVisibility(VISIBLE); + Drawable drawable = null; + try { + drawable = getResources().getDrawable(rightResId); + } catch (Exception e) { + // e.printStackTrace(); + } finally { + if (drawable != null) { + mTitleRightTv.setBackgroundResource(rightResId); + mTitleRightTv.setText(null); + } else { + mTitleRightTv.setText(rightResId); + mTitleRightTv.setBackgroundResource(0); + } + } + } else { + if (mTitleRightLl != null) + mTitleRightLl.setVisibility(INVISIBLE); + } + } + } + + public void setMidLeftText(@StringRes int midLeftResId) { + if (mMidLeftTv != null) { + if (midLeftResId != 0) { + if (mMidLeftTv.getVisibility() != View.VISIBLE) { + mMidLeftTv.setVisibility(View.VISIBLE); + } + mMidLeftTv.setText(midLeftResId); + } else { + mMidLeftTv.setVisibility(INVISIBLE); + } + } + } + + public void setMidLeftImageSrc(@DrawableRes int midLeftResId) { + if (mMidLeftTv != null) { + if (midLeftResId != 0) { + if (mMidLeftTv.getVisibility() != View.VISIBLE) { + mMidLeftTv.setVisibility(View.VISIBLE); + } + mMidLeftTv.setBackgroundResource(midLeftResId); + } else { + mMidLeftTv.setVisibility(INVISIBLE); + } + } + } + + public void setMidRightText(@StringRes int midRightResId) { + if (mMidRightTv != null) { + if (midRightResId != 0) { + if (mMidRightTv.getVisibility() != View.VISIBLE) { + mMidRightTv.setVisibility(View.VISIBLE); + } + mMidRightTv.setText(midRightResId); + } else { + mMidRightTv.setVisibility(INVISIBLE); + } + } + } + + public void setMidRightImageSrc(@DrawableRes int midRightResId) { + if (mMidRightTv != null) { + if (midRightResId != 0) { + if (mMidRightTv.getVisibility() != View.VISIBLE) { + mMidRightTv.setVisibility(View.VISIBLE); + } + mMidRightTv.setBackgroundResource(midRightResId); + } else { + mMidRightTv.setVisibility(INVISIBLE); + } + } + } + + /*-----------------------------------------setTextColor START--------------------------------------*/ + public void setTextColorLeft(int colorResId) { + if (mTitleLeftTv != null) { + mTitleLeftTv.setTextColor(colorResId != 0 ? getResources().getColor(colorResId) : getResources().getColor( + R.color.c0)); + } + } + + public void setTextColorRight(int colorResId) { + if (mTitleRightTv != null) { + mTitleRightTv.setTextColor(colorResId != 0 ? getResources().getColor(colorResId) : getResources().getColor( + R.color.c0)); + } + } + + + /*-----------------------------------------setTextColor END--------------------------------------*/ + /*-----------------------------------------setTextSize START--------------------------------------*/ + public void setTextSizeLeft(int textSizeDimenId) { + if (mTitleLeftTv != null) { + mTitleLeftTv.setTextSize(TypedValue.COMPLEX_UNIT_PX, + textSizeDimenId != 0 ? getResources().getDimensionPixelSize(textSizeDimenId) : getResources() + .getDimensionPixelSize(R.dimen.mobile_common_text_size_mid)); + } + } + + public void setTextSizeRight(int textSizeDimenId) { + if (mTitleRightTv != null) { + mTitleRightTv.setTextSize(TypedValue.COMPLEX_UNIT_PX, + textSizeDimenId != 0 ? getResources().getDimensionPixelSize(textSizeDimenId) : getResources() + .getDimensionPixelSize(R.dimen.mobile_common_text_size_mid)); + } + } + + + /*-----------------------------------------setTextSize END--------------------------------------*/ + /*-----------------------------------------setIcon START--------------------------------------*/ + + public void setIconLeft(int resId) { + if (mTitleLeftLl != null) { + if (mTitleLeftLl.getVisibility() != View.VISIBLE) { + mTitleLeftLl.setVisibility(View.VISIBLE); + } + setTitleLeft(resId); + } + } + + public void setIconRight(int resId) { + if (mTitleRightLl != null) { + if (mTitleRightLl.getVisibility() != View.VISIBLE) { + mTitleRightLl.setVisibility(View.VISIBLE); + } + setTitleRight(resId); + } + } + + + public void setVisibleBottomDivider(int flag) { + if (mBottomV != null) { + mBottomV.setVisibility(flag); + } + } + + + public void setEnabled(boolean enabled, int id) { + View parent = findParentViewById(id); + if (parent != null) { + + View v = findViewByID(id); + if (v != null) { + + parent.setEnabled(enabled); + v.setEnabled(enabled); + } + } + } + + + private View findParentViewById(int id) { + switch (id) { + case ID_LEFT: + return mTitleLeftLl; + + case ID_RIGHT: + return mTitleRightLl; + + default: + return null; + } + } + + public View findViewByID(int id) { + switch (id) { + case ID_LEFT: + return mTitleLeftTv; + case ID_RIGHT: + return mTitleRightTv; + case ID_MID_LEFT: + return mMidLeftTv; + case ID_MID_RIGHT: + return mMidRightTv; + default: + return null; + } + } + + public void setOnTitleClickListener(OnTitleClickListener listener) { + mListener = listener; + } + + public interface OnTitleClickListener { + void onCommonTitleClick(int id); + } +} diff --git a/DeviceAddModule/src/main/java/com/mm/android/deviceaddmodule/mobilecommon/widget/CommonTitle.java b/DeviceAddModule/src/main/java/com/mm/android/deviceaddmodule/mobilecommon/widget/CommonTitle.java new file mode 100644 index 0000000..3ead001 --- /dev/null +++ b/DeviceAddModule/src/main/java/com/mm/android/deviceaddmodule/mobilecommon/widget/CommonTitle.java @@ -0,0 +1,841 @@ +package com.mm.android.deviceaddmodule.mobilecommon.widget; + +import android.content.Context; +import android.content.res.Configuration; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.util.DisplayMetrics; +import android.util.TypedValue; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.mm.android.deviceaddmodule.R; + + +/** + *+ * 工具类使用说明:左按钮,左内按钮,中间按钮,右内按钮,右按钮,均支持图片和文字背景二选一,左右按钮默认支持图片,中间按钮默认支持文字 + *
+ *+ * xml使用注意:需要在xml文件中使用style="@style/common_titile" + *
+ *+ * 函数使用介绍: + *
+ *+ * initView(int tvLeftResId, int tvRightResId, int tvCenterResId) 初始化控件:左按钮,中间按钮,右按钮,属于普通用法 + *
+ *+ * getTextViewXXX() 获取xxx按钮,进行自定义功能扩展操作。例如,实现展开下来listview的功能 + *
+ *+ * setTitleXXXView(int resId, int colorId, int textSizeDimenId) 设置xxx按钮的文字,文字颜色,文字大小 + *
+ *+ * setTitleXXX(int resId) 设置xxx按钮图片或文字 + *
+ *+ * setTextColorXXX(int colorId) 设置xxx按钮文字的颜色资源 + *
+ *+ * setTextSizeXXX(int textSizeDimenId) 设置xxx按钮文字的大小 + *
+ *+ * setTitleTextXXX(int resId) 通过resId设置xxx按钮的文字 + *
+ *+ * setTitleTextXXX(String titleTextXXX) 通过String设置xxx按钮的文字 + *
+ *+ * setVisibleXXX(int flag) 通过flag设置xxx是否隐藏,flag:View.GONE,View.INVISIBLE,View.VISIBLE; + *
+ */ +public class CommonTitle extends RelativeLayout +// implements OnClickListener +{ + /** + * 左侧按钮ID + */ + public static final int ID_LEFT = 0; + + /** + * 左侧内按钮ID + */ + public static final int ID_LEFT_2 = 1; + + /** + * 右侧按钮ID + */ + public static final int ID_RIGHT = 2; + + /** + * 右侧内按钮ID + */ + public static final int ID_RIGHT_2 = 3; + + /** + * 中间按钮ID, 暂时不加监听器 + */ + public static final int ID_CENTER = 4; + + /** + * 左侧按钮/ 左侧按钮LinearLayout + */ + private TextView mTitleLeftTv; + + private LinearLayout mTitleLeftLl; + + /** + * 左侧按钮(靠内) /左侧按钮(靠内)LinearLayout + */ + private TextView mTitleLeft2Tv; + + private LinearLayout mTitleLeft2Ll; + + /** + * 右侧按钮 /右侧按钮LinearLayout + */ + private TextView mTitleRightTv; + + private LinearLayout mTitleRightLl; + + /** + * 右侧按钮(靠内) /右侧按钮(靠内)LinearLayout + */ + private TextView mTitleRight2Tv; + + private LinearLayout mTitleRight2Ll; + + /** + * 文字标题/文字标题LinearLayout + */ + private TextView mTitleCenterTv; + + private LinearLayout mTitleCenterLl; + + /** + * 点击监听 + */ + private OnTitleClickListener mListener; + + private View mBottomV; + private boolean mIsSupportChangeCenterWidth =false; + /** + * 默认隐藏左2和右2的按钮 ,创建一个新的实例CommonTitle. + * + * @param context + * @param attrs + */ + public CommonTitle(Context context, AttributeSet attrs) { + super(context, attrs); + LayoutInflater.from(context).inflate(R.layout.mobile_common_widget_common_title, this); + initView(); + setListeners(); + setVisibleLeft2(View.GONE); + setVisibleRight2(View.GONE); + } + + private void initView() { + mBottomV = findViewById(R.id.v_bottom_line); + mTitleLeftLl = findViewById(R.id.ll_title_left); + mTitleLeft2Ll = findViewById(R.id.ll_title_left2); + mTitleRightLl = findViewById(R.id.ll_title_right); + mTitleRight2Ll = findViewById(R.id.ll_title_right2); + mTitleCenterLl = findViewById(R.id.ll_title_center); + + mTitleLeftTv = findViewById(R.id.tv_title_left); + mTitleLeft2Tv = findViewById(R.id.tv_title_left2); + mTitleRightTv = findViewById(R.id.tv_title_right); + mTitleRight2Tv = findViewById(R.id.tv_title_right2); + mTitleCenterTv = findViewById(R.id.tv_title_center); + + mTitleLeftTv.setTextColor(getResources().getColor(R.color.c43)); + mTitleLeft2Tv.setTextColor(getResources().getColor(R.color.c43)); + mTitleRightTv.setTextColor(getResources().getColor(R.color.c43)); + mTitleRight2Tv.setTextColor(getResources().getColor(R.color.c43)); + mTitleCenterTv.setTextColor(getResources().getColor(R.color.c2)); + + mTitleLeftTv.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources() + .getDimensionPixelSize(R.dimen.mobile_common_common_title_text_size_mid)); + mTitleLeft2Tv.setTextSize(TypedValue.COMPLEX_UNIT_PX, + getResources().getDimensionPixelSize(R.dimen.mobile_common_common_title_text_size_mid)); + mTitleRightTv.setTextSize(TypedValue.COMPLEX_UNIT_PX, + getResources().getDimensionPixelSize(R.dimen.mobile_common_common_title_text_size_mid)); + mTitleRight2Tv.setTextSize(TypedValue.COMPLEX_UNIT_PX, + getResources().getDimensionPixelSize(R.dimen.mobile_common_common_title_text_size_mid)); + mTitleCenterTv.setTextSize(TypedValue.COMPLEX_UNIT_PX, + getResources().getDimensionPixelSize(R.dimen.mobile_common_common_title_text_size_large)); + + //横屏时不显示,只支持竖屏下的宽度设置。 //初始化时,写死中间标题的宽度 + DisplayMetrics dm = getContext().getResources().getDisplayMetrics(); + int commonTitleWidth = dm.widthPixels; + if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT){ + commonTitleWidth = dm.widthPixels; + }else if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE){ + commonTitleWidth = dm.heightPixels; + } + + int centerTitleWidth = commonTitleWidth - 4 * dp2px(dm, 48);// 减去4个按钮的占用空间 + + mTitleCenterTv.setWidth(centerTitleWidth); + } + + private int dp2px(DisplayMetrics dm , float dp){ + final float scale = dm.density; + return (int) (dp * scale + 0.5f); + } + + private void setListeners() { + mTitleLeftLl.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + if (mListener != null) { + mListener.onCommonTitleClick(ID_LEFT); + } + + } + }); + + mTitleLeft2Ll.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + if (mListener != null) { + mListener.onCommonTitleClick(ID_LEFT_2); + } + + } + }); + + mTitleRightLl.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + if (mListener != null) { + mListener.onCommonTitleClick(ID_RIGHT); + } + + } + }); + + mTitleRight2Ll.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + if (mListener != null) + mListener.onCommonTitleClick(ID_RIGHT_2); + } + }); + + mTitleCenterLl.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + if (mListener != null) + mListener.onCommonTitleClick(ID_CENTER); + } + }); + } + + /** + *+ * 初始化参数,按钮均可支持图片或者文字背景 + *
+ * @param tvLeftResId + * 左按钮 + * @param tvRightResId + * 右按钮 + * @param tvCenterResId + * 中间按钮 + */ + + public void initView(int tvLeftResId, int tvRightResId, int tvCenterResId) { + setTitleLeftView(tvLeftResId, 0, 0); + setTitleRightView(tvRightResId, 0, 0); + setTitleCenterView(tvCenterResId, 0, 0); + } + + public TextView getTextViewRight() { + return mTitleRightTv; + } + + // + public TextView getTextViewRight2() { + return mTitleRight2Tv; + } + // + public TextView getTextViewCenter() { + return mTitleCenterTv; + } + + /** + *+ * 设置是否选中按钮 + *
+ * @param selected + * {true,false} + * @param id + * {ID_LEFT ,ID_LEFT_2,ID_RIGHT,ID_RIGHT_2,ID_CENTER} + */ + public void setTitleSelected(boolean selected, int id) { + View v = findViewByID(id); + if (v != null) { + v.setSelected(selected); + } + } + + /** + *+ * 设置按钮是否可用 + *
+ */ + + + public void setEnabled(boolean enabled, int id) { + View parent = findParentViewById(id); + if (parent != null) { + + View v = findViewByID(id); + if (v != null) { + + parent.setEnabled(enabled); + v.setEnabled(enabled); + } + } + + } + + public boolean isEnable(int id){ + View parent = findParentViewById(id); + if (parent != null) { + + View v = findViewByID(id); + if (v != null) { + return v.isEnabled(); + } + } + + return false; + } + + private View findParentViewById(int id) { + switch (id) { + case ID_LEFT: + return mTitleLeftLl; + case ID_LEFT_2: + return mTitleLeft2Ll; + case ID_RIGHT: + return mTitleRightLl; + case ID_RIGHT_2: + return mTitleRight2Ll; + case ID_CENTER: + return mTitleCenterLl; + default: + return null; + } + } + + private View findViewByID(int id) { + switch (id) { + case ID_LEFT: + return mTitleLeftTv; + case ID_LEFT_2: + return mTitleLeft2Tv; + case ID_RIGHT: + return mTitleRightTv; + case ID_RIGHT_2: + return mTitleRight2Tv; + case ID_CENTER: + return mTitleCenterTv; + default: + return null; + } + } + + /*------------------------------------------getTextView END------------------------------*/ + + /*-----------------------------------setTitleView START---------------------------------*/ + public void setTitleLeftView(int resId, int colorId, int textSizeDimenId) { + setTitleLeft(resId); + setTextColorLeft(colorId); + setTextSizeLeft(textSizeDimenId); + } + + public void setTitleRightView(int resId, int colorId, int textSizeDimenId) { + setTitleRight(resId); + setTextColorRight(colorId); + setTextSizeRight(textSizeDimenId); + } + + public void setTitleCenterView(int resId, int colorId, int textSizeDimenId) { + setTitleCenter(resId); + setTextColorCenter(colorId); + setTextSizeCenter(textSizeDimenId); + } + + /*-----------------------------------setTitleView END---------------------------------*/ + /*------------------------------------------setTitle START------------------------------*/ + /** + *+ * 设置左边按钮图片或文字 + *
+ * @param leftResId + */ + public void setTitleLeft(int leftResId) { + if (mTitleLeftTv != null) { + if (leftResId != 0) { + if (mTitleLeftLl != null && mTitleLeftLl.getVisibility() != View.VISIBLE) + mTitleLeftLl.setVisibility(VISIBLE); + Drawable drawable = null; + try { + drawable = getResources().getDrawable(leftResId); + } catch (Exception e) { + // e.printStackTrace(); + } finally { + if (drawable != null) { + mTitleLeftTv.setBackgroundResource(leftResId); + mTitleLeftTv.setText(null); + } else { + mTitleLeftTv.setText(leftResId); + mTitleLeftTv.setBackgroundResource(0); + } + } + } else { + if (mTitleLeftLl != null) + mTitleLeftLl.setVisibility(GONE); + } + } + } + + /** + *+ * 设置左边按钮图片或文字 + *
+ * @param left2ResId + */ + public void setTitleLeft2(int left2ResId) { + if (mTitleLeft2Tv != null) { + if (left2ResId != 0) { + if (mTitleLeft2Ll != null && mTitleLeft2Ll.getVisibility() != View.VISIBLE) + mTitleLeft2Ll.setVisibility(VISIBLE); + Drawable drawable = null; + try { + drawable = getResources().getDrawable(left2ResId); + } catch (Exception e) { + // e.printStackTrace(); + } finally { + if (drawable != null) { + mTitleLeft2Tv.setBackgroundResource(left2ResId); + mTitleLeft2Tv.setText(null); + } else { + mTitleLeft2Tv.setText(left2ResId); + mTitleLeft2Tv.setBackgroundResource(0); + } + } + } else { + if (mTitleLeft2Ll != null) + mTitleLeft2Ll.setVisibility(INVISIBLE); + } + } + } + + /** + *+ * 设置右边按钮图片或文字 + *
+ * @param rightResId + */ + public void setTitleRight(int rightResId) { + if (mTitleRightTv != null) { + if (rightResId != 0) { + if (mTitleRightLl != null && mTitleRightLl.getVisibility() != View.VISIBLE) + mTitleRightLl.setVisibility(VISIBLE); + Drawable drawable = null; + try { + drawable = getResources().getDrawable(rightResId); + } catch (Exception e) { + // e.printStackTrace(); + } finally { + if (drawable != null) { + mTitleRightTv.setBackgroundResource(rightResId); + mTitleRightTv.setText(null); + } else { + mTitleRightTv.setText(rightResId); + mTitleRightTv.setBackgroundResource(0); + } + + } + } else { + if (mTitleRightLl != null) + mTitleRightLl.setVisibility(INVISIBLE); + } + } + } + + public void setTitleRight2(int right2ResId) { + if (mTitleRight2Tv != null) { + if (right2ResId != 0) { + if (mTitleRight2Ll != null && mTitleRight2Ll.getVisibility() != View.VISIBLE) + mTitleRight2Ll.setVisibility(VISIBLE); + Drawable drawable = null; + try { + drawable = getResources().getDrawable(right2ResId); + } catch (Exception e) { + // e.printStackTrace(); + } finally { + if (drawable != null) { + mTitleRight2Tv.setBackgroundResource(right2ResId); + mTitleRight2Tv.setText(null); + } else { + mTitleRight2Tv.setText(right2ResId); + mTitleRight2Tv.setBackgroundResource(0); + } + } + } else { + if (mTitleRight2Ll != null) + mTitleRight2Ll.setVisibility(INVISIBLE); + } + } + } + + /** + *+ * 设置中间按钮图片或文字 + *
+ * @param centerResId + */ + public void setTitleCenter(int centerResId) { + if (mTitleCenterTv != null) { + if (centerResId != 0) { + if (mTitleCenterLl != null && mTitleCenterLl.getVisibility() != View.VISIBLE) + mTitleCenterLl.setVisibility(VISIBLE); + Drawable drawable = null; + try { + drawable = getResources().getDrawable(centerResId); + } catch (Exception e) { + // e.printStackTrace(); + } finally { + if (drawable != null) { + mTitleCenterTv.setBackgroundResource(centerResId); + mTitleCenterTv.setText(null); + } else { + mTitleCenterTv.setText(centerResId); + mTitleCenterTv.setBackgroundResource(0); + setTitleCenterWidth(); + } + } + } else { + if (mTitleCenterLl != null) + mTitleCenterLl.setVisibility(INVISIBLE); + } + } + } + + /*------------------------------------------setTitle END------------------------------*/ + /*-----------------------------------------setTextColor START--------------------------------------*/ + public void setTextColorLeft(int colorId) { + if (mTitleLeftTv != null) { + mTitleLeftTv.setTextColor(colorId != 0 ? getResources().getColor(colorId) : getResources().getColor( + R.color.c50)); + } + } + + public void setTextColorLeft2(int colorId) { + if (mTitleLeft2Tv != null) { + mTitleLeft2Tv.setTextColor(colorId != 0 ? getResources().getColor(colorId) : getResources().getColor( + R.color.c50)); + } + } + + public void setTextColorRight(int colorId) { + if (mTitleRightTv != null) { + mTitleRightTv.setTextColor(colorId != 0 ? getResources().getColorStateList(colorId) : getResources() + .getColorStateList(R.color.mobile_common_title_text_color_selector)); + } + } + + public void setTextColorRight2(int colorId) { + if (mTitleRight2Tv != null) { + mTitleRight2Tv.setTextColor(colorId != 0 ? getResources().getColor(colorId) : getResources().getColor( + R.color.c43)); + } + } + + public void setTextColorCenter(int colorId) { + if (mTitleCenterTv != null) { + mTitleCenterTv.setTextColor(colorId != 0 ? getResources().getColor(colorId) : getResources().getColor( + R.color.c2)); + } + } + + /*-----------------------------------------setTextColor END--------------------------------------*/ + /*-----------------------------------------setTextSize START--------------------------------------*/ + public void setTextSizeLeft(int textSizeDimenId) { + if (mTitleLeftTv != null) { + mTitleLeftTv.setTextSize(TypedValue.COMPLEX_UNIT_PX, + textSizeDimenId != 0 ? getResources().getDimensionPixelSize(textSizeDimenId) : getResources() + .getDimensionPixelSize(R.dimen.mobile_common_common_title_text_size_mid)); + } + } + + public void setTextSizeLeft2(int textSizeDimenId) { + if (mTitleLeft2Tv != null) { + mTitleLeft2Tv.setTextSize(TypedValue.COMPLEX_UNIT_PX, + textSizeDimenId != 0 ? getResources().getDimensionPixelSize(textSizeDimenId) : getResources() + .getDimensionPixelSize(R.dimen.mobile_common_common_title_text_size_mid)); + } + } + + public void setTextSizeRight(int textSizeDimenId) { + if (mTitleRightTv != null) { + mTitleRightTv.setTextSize(TypedValue.COMPLEX_UNIT_PX, + textSizeDimenId != 0 ? getResources().getDimensionPixelSize(textSizeDimenId) : getResources() + .getDimensionPixelSize(R.dimen.mobile_common_common_title_text_size_mid)); + } + } + + public void setTextSizeRight2(int textSizeDimenId) { + if (mTitleRight2Tv != null) { + mTitleRight2Tv.setTextSize(TypedValue.COMPLEX_UNIT_PX, + textSizeDimenId != 0 ? getResources().getDimensionPixelSize(textSizeDimenId) : getResources() + .getDimensionPixelSize(R.dimen.mobile_common_common_title_text_size_mid)); + } + } + + public void setTextSizeCenter(int textSizeDimenId) { + if (mTitleCenterTv != null) { + mTitleCenterTv.setTextSize(TypedValue.COMPLEX_UNIT_PX, + textSizeDimenId != 0 ? getResources().getDimensionPixelSize(textSizeDimenId) : getResources() + .getDimensionPixelSize(R.dimen.mobile_common_common_title_text_size_large)); + } + } + + /*-----------------------------------------setTextSize END--------------------------------------*/ + + /*-----------------------------------------setIcon START--------------------------------------*/ + + public void setIconLeft(int resId) { + if (mTitleLeftLl != null) { + if (mTitleLeftLl.getVisibility() != View.VISIBLE) { + mTitleLeftLl.setVisibility(View.VISIBLE); + } + setTitleLeft(resId); + } + } + + public void setIconLeft2(int resId) { + if (mTitleLeft2Ll != null) { + if (mTitleLeft2Ll.getVisibility() != View.VISIBLE) { + mTitleLeft2Ll.setVisibility(View.VISIBLE); + } + setTitleLeft2(resId); + } + } + + public void setIconRight(int resId) { + if (mTitleRightLl != null) { + if (mTitleRightLl.getVisibility() != View.VISIBLE) { + mTitleRightLl.setVisibility(View.VISIBLE); + } + setTitleRight(resId); + } + } + + public void setIconRight2(int resId) { + if (mTitleRight2Ll != null) { + if (mTitleRight2Ll.getVisibility() != View.VISIBLE) { + mTitleRight2Ll.setVisibility(View.VISIBLE); + } + setTitleRight2(resId); + } + } + + public void setIconCenter(int resId) { + if (mTitleCenterLl != null) { + if (mTitleCenterLl.getVisibility() != View.VISIBLE) { + mTitleCenterLl.setVisibility(View.VISIBLE); + } + setTitleCenter(resId); + } + } + + /*-----------------------------------------setIcon END--------------------------------------*/ + /*-----------------------------------------setTextById START--------------------------------------*/ + + public void setTitleTextLeft(int resId) { + if (mTitleLeftLl != null) { + if (mTitleLeftLl.getVisibility() != View.VISIBLE) { + mTitleLeftLl.setVisibility(View.VISIBLE); + } + setTitleLeft(resId); + } + } + + public void setTitleTextLeft2(int resId) { + if (mTitleLeft2Ll != null) { + if (mTitleLeft2Ll.getVisibility() != View.VISIBLE) { + mTitleLeft2Ll.setVisibility(View.VISIBLE); + } + setTitleLeft(resId); + } + } + + public void setTitleTextRight(int resId) { + if (mTitleRightLl != null) { + if (mTitleRightLl.getVisibility() != View.VISIBLE) { + mTitleRightLl.setVisibility(View.VISIBLE); + } + setTitleRight(resId); + } + } + + public void setTitleTextRight2(int resId) { + if (mTitleRight2Ll != null) { + if (mTitleRight2Ll.getVisibility() != View.VISIBLE) { + mTitleRight2Ll.setVisibility(View.VISIBLE); + } + setTitleRight2(resId); + } + } + + public void setTitleTextCenter(int resId) { + if (mTitleCenterLl != null) { + if (mTitleCenterLl.getVisibility() != View.VISIBLE) { + mTitleCenterLl.setVisibility(View.VISIBLE); + } + setTitleCenter(resId); + } + } + + /*-----------------------------------------setTextById END--------------------------------------*/ + /*-----------------------------------------setTextByString START--------------------------------------*/ + public void setTitleTextLeft(String titleTextLeft) { + if (mTitleLeftTv != null) { + if (mTitleLeftTv.getVisibility() != View.VISIBLE) { + mTitleLeftTv.setVisibility(View.VISIBLE); + } + mTitleLeftTv.setText(titleTextLeft); + mTitleLeftTv.setBackgroundResource(0); + } + } + + public void setTitleTextLeft2(String titleTextLeft2) { + if (mTitleLeft2Tv != null) { + if (mTitleLeft2Tv.getVisibility() != View.VISIBLE) { + mTitleLeft2Tv.setVisibility(View.VISIBLE); + } + mTitleLeft2Tv.setText(titleTextLeft2); + mTitleLeft2Tv.setBackgroundResource(0); + } + } + + public void setTitleTextRight(String titleTextRight) { + if (mTitleRightTv != null) { + if (mTitleRightTv.getVisibility() != View.VISIBLE) { + mTitleRightTv.setVisibility(View.VISIBLE); + } + mTitleRightTv.setText(titleTextRight); + mTitleRightTv.setBackgroundResource(0); + } + } + + public void setTitleTextRight2(String titleTextRight2) { + if (mTitleRight2Tv != null) { + if (mTitleRight2Tv.getVisibility() != View.VISIBLE) { + mTitleRight2Tv.setVisibility(View.VISIBLE); + } + mTitleRight2Tv.setText(titleTextRight2); + mTitleRight2Tv.setBackgroundResource(0); + } + } + + public void setTitleTextCenter(String titleTextCenter) { + if (mTitleCenterLl != null) { + if (mTitleCenterLl.getVisibility() != View.VISIBLE) { + mTitleCenterLl.setVisibility(View.VISIBLE); + } + mTitleCenterTv.setText(titleTextCenter); + mTitleCenterTv.setBackgroundResource(0); + setTitleCenterWidth(); + } + } + /** + * + *+ * 为了支持显示网页回调中标题字数过多的问题,增加动态修改中间的宽度功能 + * 只支持web修改标题宽度 + *
+ * @param isSupportChangeCenterWidth + */ + public void setChangeCenterWidthForWebView(boolean isSupportChangeCenterWidth){ + mIsSupportChangeCenterWidth = isSupportChangeCenterWidth; + } + + @Deprecated + private void setTitleCenterWidth(){ + + } + /*-----------------------------------------setTextByString END--------------------------------------*/ + /*-----------------------------------------setVisible START--------------------------------------*/ + + public void setVisibleLeft(int flag) { + if (mTitleLeftLl != null) { + mTitleLeftLl.setVisibility(flag); + } + } + + public void setVisibleLeft2(int flag) { + if (mTitleLeft2Ll != null) { + mTitleLeft2Ll.setVisibility(flag); + } + } + + public void setVisibleRight(int flag) { + if (mTitleRightLl != null) { + mTitleRightLl.setVisibility(flag); + } + } + + public void setEnableRight(boolean enable) { + if (mTitleRightLl != null) { + mTitleRightLl.setEnabled(enable); + } + } + + public boolean getEnableRight() { + return mTitleRightLl.isEnabled(); + } + + public void setVisibleRight2(int flag) { + if (mTitleRight2Ll != null) { + mTitleRight2Ll.setVisibility(flag); + } + } + + public void setVisibleCenter(int flag) { + if (mTitleCenterLl != null) { + mTitleCenterLl.setVisibility(flag); + } + } + + public void setVisibleBottom(int flag) { + if (mBottomV != null) { + mBottomV.setVisibility(flag); + } + } + + public boolean isIconLeftVisible(){ + if (mTitleLeftLl != null) { + return mTitleLeftLl.getVisibility() == VISIBLE; + } + return false; + } + + /*-----------------------------------------setVisible END--------------------------------------*/ + public void setOnTitleClickListener(OnTitleClickListener listener) { + mListener = listener; + } + + public interface OnTitleClickListener { + public void onCommonTitleClick(int id); + } +} diff --git a/DeviceAddModule/src/main/java/com/mm/android/deviceaddmodule/mobilecommon/widget/CustomSearchView.java b/DeviceAddModule/src/main/java/com/mm/android/deviceaddmodule/mobilecommon/widget/CustomSearchView.java new file mode 100644 index 0000000..1fc5b4e --- /dev/null +++ b/DeviceAddModule/src/main/java/com/mm/android/deviceaddmodule/mobilecommon/widget/CustomSearchView.java @@ -0,0 +1,158 @@ +package com.mm.android.deviceaddmodule.mobilecommon.widget; + +import android.content.Context; +import android.support.annotation.Nullable; +import android.text.Editable; +import android.util.AttributeSet; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.InputMethodManager; +import android.widget.EditText; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.mm.android.deviceaddmodule.R; +import com.mm.android.deviceaddmodule.mobilecommon.utils.LogUtil; + +/** + * 通用搜索框 + */ + +public class CustomSearchView extends RelativeLayout implements View.OnClickListener, + ClearEditText.IFocusChangeListener, ClearEditText.ITextChangeListener, + TextView.OnEditorActionListener { + private ClearEditText mSearchInput; + private TextView mCancelTv; + private InputMethodManager mInputMethodManager; + private IOnTextChangeListener mTextChangeListener; + private IOnFocusChangeListener mFocusChangeListener; + + public CustomSearchView(Context context) { + this(context, null); + } + + public CustomSearchView(Context context, @Nullable AttributeSet attrs) { + this(context, attrs, 0); + } + + public interface IOnFocusChangeListener { + void onSearchFocusChange(View v, boolean hasFocus); + } + + public void setOnSearchFocusChangeListener(IOnFocusChangeListener listener) { + mFocusChangeListener = listener; + } + + public interface IOnTextChangeListener { + void onTextChange(View v, CharSequence ch); + } + + public void setOnTextChangedListener(IOnTextChangeListener listener) { + mTextChangeListener = listener; + } + + public CustomSearchView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + + LayoutInflater.from(context).inflate(R.layout.mobile_common_search_view, this); + initView(); + initData(); + } + + private void initView() { + mSearchInput = findViewById(R.id.common_search_input); + mCancelTv = findViewById(R.id.common_search_cancel); + + mCancelTv.setOnClickListener(this); + mSearchInput.setTextChangeListener(this); + mSearchInput.setOnClickListener(this); + mSearchInput.setClearTextFocusChange(this); + mSearchInput.setOnEditorActionListener(this); + } + + private void initData() { + mInputMethodManager = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE); + } + + @Override + public void onClick(View view) { + int id = view.getId(); + if (id == R.id.common_search_cancel) { + mSearchInput.clearFocus(); + } else if (id == R.id.common_search_input) { + mSearchInput.requestFocus(); + } + } + + @Override + public void onClearTextFocusChange(View v, boolean hasFocus) { + LogUtil.debugLog("33084", " onClearTextFocusChange hasFocus = " + hasFocus); + if (hasFocus) { + mCancelTv.setVisibility(View.VISIBLE); + } else { + mCancelTv.setVisibility(View.GONE); + mSearchInput.setText(""); + mInputMethodManager.hideSoftInputFromWindow(v.getWindowToken(), 0); + } + + if (mFocusChangeListener != null) { + mFocusChangeListener.onSearchFocusChange(v, hasFocus); + } + } + + @Override + public void afterChanged(EditText v, Editable s) { + + } + + @Override + public void beforeChanged(EditText v, CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(EditText v, CharSequence text, int start, int lengthBefore, int lengthAfter) { + LogUtil.debugLog("33084", " onTextChanged"); + if (mTextChangeListener != null) { + mTextChangeListener.onTextChange(v, text); + } + } + + @Override + public boolean onEditorAction(TextView tv, int actionId, KeyEvent keyEvent) { + if (actionId == EditorInfo.IME_ACTION_SEARCH) { + if (mInputMethodManager != null) { + mInputMethodManager.hideSoftInputFromWindow(tv.getWindowToken(), 0); + } + return true; + } + return false; + } + + /** + * 设置提示语 + * + * @param resId + */ + public void setSearchTextHint(int resId) { + mSearchInput.setHint(getResources().getString(resId)); + } + + /** + * 获取输入框内容 + */ + public String getEditText() { + return mSearchInput.getText().toString(); + } + + private void onDestroyView() { + if (mInputMethodManager != null) { + mInputMethodManager = null; + } + if (mTextChangeListener != null) { + mTextChangeListener = null; + } + } +} diff --git a/DeviceAddModule/src/main/java/com/mm/android/deviceaddmodule/mobilecommon/widget/DrawableTextView.java b/DeviceAddModule/src/main/java/com/mm/android/deviceaddmodule/mobilecommon/widget/DrawableTextView.java new file mode 100644 index 0000000..0f3d93c --- /dev/null +++ b/DeviceAddModule/src/main/java/com/mm/android/deviceaddmodule/mobilecommon/widget/DrawableTextView.java @@ -0,0 +1,42 @@ +package com.mm.android.deviceaddmodule.mobilecommon.widget; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.support.annotation.Nullable; +import android.util.AttributeSet; + +public class DrawableTextView extends android.support.v7.widget.AppCompatTextView { + Rect mRect = new Rect(); + public DrawableTextView(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + + @Override + protected void onDraw(Canvas canvas) { + + Drawable[] drawables = getCompoundDrawables(); + if(drawables != null){ + Drawable drawable = drawables[0]; + if(drawable != null){ + float textwidth = getPaint().measureText(getText().toString()); + int drawablePadding = getCompoundDrawablePadding(); + int drawableWidth = drawable.getIntrinsicWidth(); + float bodyWidth = textwidth + drawablePadding + drawableWidth; + canvas.translate((getWidth() - bodyWidth) / 2 , 0); + } else if((drawable = drawables[1]) != null){ + Rect rect = mRect; + getPaint().getTextBounds(getText().toString(), 0, getText().toString().length(), rect); + float textHeight = rect.height(); + int drawablePadding = getCompoundDrawablePadding(); + int drawableHeght = drawable.getIntrinsicHeight(); + float bodxinzaieight = textHeight + drawablePadding + drawableHeght; + canvas.translate(0, (getHeight() - bodxinzaieight) / 2); + } + } + + super.onDraw(canvas); + } +} diff --git a/DeviceAddModule/src/main/java/com/mm/android/deviceaddmodule/mobilecommon/widget/DrawerLayout.java b/DeviceAddModule/src/main/java/com/mm/android/deviceaddmodule/mobilecommon/widget/DrawerLayout.java new file mode 100644 index 0000000..ab5d4cd --- /dev/null +++ b/DeviceAddModule/src/main/java/com/mm/android/deviceaddmodule/mobilecommon/widget/DrawerLayout.java @@ -0,0 +1,2345 @@ +package com.mm.android.deviceaddmodule.mobilecommon.widget; + +import android.annotation.TargetApi; +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.PixelFormat; +import android.graphics.Rect; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.os.Parcel; +import android.os.Parcelable; +import android.os.SystemClock; +import android.support.annotation.ColorInt; +import android.support.annotation.DrawableRes; +import android.support.annotation.IntDef; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.annotation.RestrictTo; +import android.support.v4.content.ContextCompat; +import android.support.v4.graphics.drawable.DrawableCompat; +import android.support.v4.view.AbsSavedState; +import android.support.v4.view.AccessibilityDelegateCompat; +import android.support.v4.view.GravityCompat; +import android.support.v4.view.ViewCompat; +import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat; +import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat; +import android.support.v4.widget.ViewDragHelper; +import android.util.AttributeSet; +import android.view.Gravity; +import android.view.KeyEvent; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewParent; +import android.view.WindowInsets; +import android.view.accessibility.AccessibilityEvent; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.ArrayList; +import java.util.List; + +import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP; + +public class DrawerLayout extends ViewGroup { + private static final String TAG = "DrawerLayout"; + + private static final int[] THEME_ATTRS = { + android.R.attr.colorPrimaryDark + }; + + @IntDef({STATE_IDLE, STATE_DRAGGING, STATE_SETTLING}) + @Retention(RetentionPolicy.SOURCE) + private @interface State {} + + /** + * Indicates that any drawers are in an idle, settled state. No animation is in progress. + */ + public static final int STATE_IDLE = ViewDragHelper.STATE_IDLE; + + /** + * Indicates that a drawer is currently being dragged by the user. + */ + public static final int STATE_DRAGGING = ViewDragHelper.STATE_DRAGGING; + + /** + * Indicates that a drawer is in the process of settling to a final position. + */ + public static final int STATE_SETTLING = ViewDragHelper.STATE_SETTLING; + + @IntDef({LOCK_MODE_UNLOCKED, LOCK_MODE_LOCKED_CLOSED, LOCK_MODE_LOCKED_OPEN, + LOCK_MODE_UNDEFINED}) + @Retention(RetentionPolicy.SOURCE) + private @interface LockMode {} + + /** + * The drawer is unlocked. + */ + public static final int LOCK_MODE_UNLOCKED = 0; + + /** + * The drawer is locked closed. The user may not open it, though + * the app may open it programmatically. + */ + public static final int LOCK_MODE_LOCKED_CLOSED = 1; + + /** + * The drawer is locked open. The user may not close it, though the app + * may close it programmatically. + */ + public static final int LOCK_MODE_LOCKED_OPEN = 2; + + /** + * The drawer's lock state is reset to default. + */ + public static final int LOCK_MODE_UNDEFINED = 3; + + @IntDef(value = {Gravity.LEFT, Gravity.RIGHT, GravityCompat.START, GravityCompat.END}, + flag = true) + @Retention(RetentionPolicy.SOURCE) + private @interface EdgeGravity {} + + + private static final int MIN_DRAWER_MARGIN = 0; // dp + private static final int DRAWER_ELEVATION = 10; //dp + + private static final int DEFAULT_SCRIM_COLOR = 0x99000000; + + /** + * Length of time to delay before peeking the drawer. + */ + private static final int PEEK_DELAY = 160; // ms + + /** + * Minimum velocity that will be detected as a fling + */ + private static final int MIN_FLING_VELOCITY = 400; // dips per second + + /** + * Experimental feature. + */ + private static final boolean ALLOW_EDGE_LOCK = false; + + private static final boolean CHILDREN_DISALLOW_INTERCEPT = true; + + private static final float TOUCH_SLOP_SENSITIVITY = 1.f; + + static final int[] LAYOUT_ATTRS = new int[] { + android.R.attr.layout_gravity + }; + + /** Whether we can use NO_HIDE_DESCENDANTS accessibility importance. */ + static final boolean CAN_HIDE_DESCENDANTS = Build.VERSION.SDK_INT >= 19; + + /** Whether the drawer shadow comes from setting elevation on the drawer. */ + private static final boolean SET_DRAWER_SHADOW_FROM_ELEVATION = + Build.VERSION.SDK_INT >= 21; + + private final ChildAccessibilityDelegate mChildAccessibilityDelegate = + new ChildAccessibilityDelegate(); + private float mDrawerElevation; + + private int mMinDrawerMargin; + + private int mScrimColor = DEFAULT_SCRIM_COLOR; + private float mScrimOpacity; + private Paint mScrimPaint = new Paint(); + + private final ViewDragHelper mLeftDragger; + private final ViewDragHelper mRightDragger; + private final ViewDragCallback mLeftCallback; + private final ViewDragCallback mRightCallback; + private int mDrawerState; + private boolean mInLayout; + private boolean mFirstLayout = true; + + private @LockMode int mLockModeLeft = LOCK_MODE_UNDEFINED; + private @LockMode int mLockModeRight = LOCK_MODE_UNDEFINED; + private @LockMode int mLockModeStart = LOCK_MODE_UNDEFINED; + private @LockMode int mLockModeEnd = LOCK_MODE_UNDEFINED; + + private boolean mDisallowInterceptRequested; + private boolean mChildrenCanceledTouch; + + private @Nullable DrawerListener mListener; + private ListNote that for better support for both left-to-right and right-to-left layout + * directions, a drawable for RTL layout (in additional to the one in LTR layout) can be + * defined with a resource qualifier "ldrtl" for API 17 and above with the gravity + * {@link GravityCompat#START}. Alternatively, for API 23 and above, the drawable can + * auto-mirrored such that the drawable will be mirrored in RTL layout.
+ * + * @param shadowDrawable Shadow drawable to use at the edge of a drawer + * @param gravity Which drawer the shadow should apply to + */ + public void setDrawerShadow(Drawable shadowDrawable, @EdgeGravity int gravity) { + /* + * TODO Someone someday might want to set more complex drawables here. + * They're probably nuts, but we might want to consider registering callbacks, + * setting states, etc. properly. + */ + if (SET_DRAWER_SHADOW_FROM_ELEVATION) { + // No op. Drawer shadow will come from setting an elevation on the drawer. + return; + } + if ((gravity & GravityCompat.START) == GravityCompat.START) { + mShadowStart = shadowDrawable; + } else if ((gravity & GravityCompat.END) == GravityCompat.END) { + mShadowEnd = shadowDrawable; + } else if ((gravity & Gravity.LEFT) == Gravity.LEFT) { + mShadowLeft = shadowDrawable; + } else if ((gravity & Gravity.RIGHT) == Gravity.RIGHT) { + mShadowRight = shadowDrawable; + } else { + return; + } + resolveShadowDrawables(); + invalidate(); + } + + /** + * Set a simple drawable used for the left or right shadow. The drawable provided must have a + * nonzero intrinsic width. For API 21 and above, an elevation will be set on the drawer + * instead of using the provided shadow drawable. + * + *Note that for better support for both left-to-right and right-to-left layout + * directions, a drawable for RTL layout (in additional to the one in LTR layout) can be + * defined with a resource qualifier "ldrtl" for API 17 and above with the gravity + * {@link GravityCompat#START}. Alternatively, for API 23 and above, the drawable can + * auto-mirrored such that the drawable will be mirrored in RTL layout.
+ * + * @param resId Resource id of a shadow drawable to use at the edge of a drawer + * @param gravity Which drawer the shadow should apply to + */ + public void setDrawerShadow(@DrawableRes int resId, @EdgeGravity int gravity) { + setDrawerShadow(ContextCompat.getDrawable(getContext(), resId), gravity); + } + + /** + * Set a color to use for the scrim that obscures primary content while a drawer is open. + * + * @param color Color to use in 0xAARRGGBB format. + */ + public void setScrimColor(@ColorInt int color) { + mScrimColor = color; + invalidate(); + } + + /** + * Set a listener to be notified of drawer events. Note that this method is deprecated + * and you should use {@link #addDrawerListener(DrawerListener)} to add a listener and + * {@link #removeDrawerListener(DrawerListener)} to remove a registered listener. + * + * @param listener Listener to notify when drawer events occur + * @deprecated Use {@link #addDrawerListener(DrawerListener)} + * @see DrawerListener + * @see #addDrawerListener(DrawerListener) + * @see #removeDrawerListener(DrawerListener) + */ + @Deprecated + public void setDrawerListener(DrawerListener listener) { + // The logic in this method emulates what we had before support for multiple + // registered listeners. + if (mListener != null) { + removeDrawerListener(mListener); + } + if (listener != null) { + addDrawerListener(listener); + } + // Update the deprecated field so that we can remove the passed listener the next + // time we're called + mListener = listener; + } + + /** + * Adds the specified listener to the list of listeners that will be notified of drawer events. + * + * @param listener Listener to notify when drawer events occur. + * @see #removeDrawerListener(DrawerListener) + */ + public void addDrawerListener(@NonNull DrawerListener listener) { + if (listener == null) { + return; + } + if (mListeners == null) { + mListeners = new ArrayList<>(); + } + mListeners.add(listener); + } + + /** + * Removes the specified listener from the list of listeners that will be notified of drawer + * events. + * + * @param listener Listener to remove from being notified of drawer events + * @see #addDrawerListener(DrawerListener) + */ + public void removeDrawerListener(@NonNull DrawerListener listener) { + if (listener == null) { + return; + } + if (mListeners == null) { + // This can happen if this method is called before the first call to addDrawerListener + return; + } + mListeners.remove(listener); + } + + /** + * Enable or disable interaction with all drawers. + * + *This allows the application to restrict the user's ability to open or close + * any drawer within this layout. DrawerLayout will still respond to calls to + * {@link #openDrawer(int)}, {@link #closeDrawer(int)} and friends if a drawer is locked.
+ * + *Locking drawers open or closed will implicitly open or close + * any drawers as appropriate.
+ * + * @param lockMode The new lock mode for the given drawer. One of {@link #LOCK_MODE_UNLOCKED}, + * {@link #LOCK_MODE_LOCKED_CLOSED} or {@link #LOCK_MODE_LOCKED_OPEN}. + */ + public void setDrawerLockMode(@LockMode int lockMode) { + setDrawerLockMode(lockMode, Gravity.LEFT); + setDrawerLockMode(lockMode, Gravity.RIGHT); + } + + /** + * Enable or disable interaction with the given drawer. + * + *This allows the application to restrict the user's ability to open or close + * the given drawer. DrawerLayout will still respond to calls to {@link #openDrawer(int)}, + * {@link #closeDrawer(int)} and friends if a drawer is locked.
+ * + *Locking a drawer open or closed will implicitly open or close + * that drawer as appropriate.
+ * + * @param lockMode The new lock mode for the given drawer. One of {@link #LOCK_MODE_UNLOCKED}, + * {@link #LOCK_MODE_LOCKED_CLOSED} or {@link #LOCK_MODE_LOCKED_OPEN}. + * @param edgeGravity Gravity.LEFT, RIGHT, START or END. + * Expresses which drawer to change the mode for. + * + * @see #LOCK_MODE_UNLOCKED + * @see #LOCK_MODE_LOCKED_CLOSED + * @see #LOCK_MODE_LOCKED_OPEN + */ + public void setDrawerLockMode(@LockMode int lockMode, @EdgeGravity int edgeGravity) { + final int absGravity = GravityCompat.getAbsoluteGravity(edgeGravity, + ViewCompat.getLayoutDirection(this)); + + switch (edgeGravity) { + case Gravity.LEFT: + mLockModeLeft = lockMode; + break; + case Gravity.RIGHT: + mLockModeRight = lockMode; + break; + case GravityCompat.START: + mLockModeStart = lockMode; + break; + case GravityCompat.END: + mLockModeEnd = lockMode; + break; + } + + if (lockMode != LOCK_MODE_UNLOCKED) { + // Cancel interaction in progress + final ViewDragHelper helper = absGravity == Gravity.LEFT ? mLeftDragger : mRightDragger; + helper.cancel(); + } + switch (lockMode) { + case LOCK_MODE_LOCKED_OPEN: + final View toOpen = findDrawerWithGravity(absGravity); + if (toOpen != null) { + openDrawer(toOpen); + } + break; + case LOCK_MODE_LOCKED_CLOSED: + final View toClose = findDrawerWithGravity(absGravity); + if (toClose != null) { + closeDrawer(toClose); + } + break; + // default: do nothing + } + } + + /** + * Enable or disable interaction with the given drawer. + * + *This allows the application to restrict the user's ability to open or close + * the given drawer. DrawerLayout will still respond to calls to {@link #openDrawer(int)}, + * {@link #closeDrawer(int)} and friends if a drawer is locked.
+ * + *Locking a drawer open or closed will implicitly open or close + * that drawer as appropriate.
+ * + * @param lockMode The new lock mode for the given drawer. One of {@link #LOCK_MODE_UNLOCKED}, + * {@link #LOCK_MODE_LOCKED_CLOSED} or {@link #LOCK_MODE_LOCKED_OPEN}. + * @param drawerView The drawer view to change the lock mode for + * + * @see #LOCK_MODE_UNLOCKED + * @see #LOCK_MODE_LOCKED_CLOSED + * @see #LOCK_MODE_LOCKED_OPEN + */ + public void setDrawerLockMode(@LockMode int lockMode, @NonNull View drawerView) { + if (!isDrawerView(drawerView)) { + throw new IllegalArgumentException("View " + drawerView + " is not a " + + "drawer with appropriate layout_gravity"); + } + final int gravity = ((LayoutParams) drawerView.getLayoutParams()).gravity; + setDrawerLockMode(lockMode, gravity); + } + + /** + * Check the lock mode of the drawer with the given gravity. + * + * @param edgeGravity Gravity of the drawer to check + * @return one of {@link #LOCK_MODE_UNLOCKED}, {@link #LOCK_MODE_LOCKED_CLOSED} or + * {@link #LOCK_MODE_LOCKED_OPEN}. + */ + @LockMode + public int getDrawerLockMode(@EdgeGravity int edgeGravity) { + int layoutDirection = ViewCompat.getLayoutDirection(this); + + switch (edgeGravity) { + case Gravity.LEFT: + if (mLockModeLeft != LOCK_MODE_UNDEFINED) { + return mLockModeLeft; + } + int leftLockMode = (layoutDirection == ViewCompat.LAYOUT_DIRECTION_LTR) + ? mLockModeStart : mLockModeEnd; + if (leftLockMode != LOCK_MODE_UNDEFINED) { + return leftLockMode; + } + break; + case Gravity.RIGHT: + if (mLockModeRight != LOCK_MODE_UNDEFINED) { + return mLockModeRight; + } + int rightLockMode = (layoutDirection == ViewCompat.LAYOUT_DIRECTION_LTR) + ? mLockModeEnd : mLockModeStart; + if (rightLockMode != LOCK_MODE_UNDEFINED) { + return rightLockMode; + } + break; + case GravityCompat.START: + if (mLockModeStart != LOCK_MODE_UNDEFINED) { + return mLockModeStart; + } + int startLockMode = (layoutDirection == ViewCompat.LAYOUT_DIRECTION_LTR) + ? mLockModeLeft : mLockModeRight; + if (startLockMode != LOCK_MODE_UNDEFINED) { + return startLockMode; + } + break; + case GravityCompat.END: + if (mLockModeEnd != LOCK_MODE_UNDEFINED) { + return mLockModeEnd; + } + int endLockMode = (layoutDirection == ViewCompat.LAYOUT_DIRECTION_LTR) + ? mLockModeRight : mLockModeLeft; + if (endLockMode != LOCK_MODE_UNDEFINED) { + return endLockMode; + } + break; + } + + return LOCK_MODE_UNLOCKED; + } + + /** + * Check the lock mode of the given drawer view. + * + * @param drawerView Drawer view to check lock mode + * @return one of {@link #LOCK_MODE_UNLOCKED}, {@link #LOCK_MODE_LOCKED_CLOSED} or + * {@link #LOCK_MODE_LOCKED_OPEN}. + */ + @LockMode + public int getDrawerLockMode(@NonNull View drawerView) { + if (!isDrawerView(drawerView)) { + throw new IllegalArgumentException("View " + drawerView + " is not a drawer"); + } + final int drawerGravity = ((LayoutParams) drawerView.getLayoutParams()).gravity; + return getDrawerLockMode(drawerGravity); + } + + /** + * Sets the title of the drawer with the given gravity. + *
+ * When accessibility is turned on, this is the title that will be used to
+ * identify the drawer to the active accessibility service.
+ *
+ * @param edgeGravity Gravity.LEFT, RIGHT, START or END. Expresses which
+ * drawer to set the title for.
+ * @param title The title for the drawer.
+ */
+ public void setDrawerTitle(@EdgeGravity int edgeGravity, @Nullable CharSequence title) {
+ final int absGravity = GravityCompat.getAbsoluteGravity(
+ edgeGravity, ViewCompat.getLayoutDirection(this));
+ if (absGravity == Gravity.LEFT) {
+ mTitleLeft = title;
+ } else if (absGravity == Gravity.RIGHT) {
+ mTitleRight = title;
+ }
+ }
+
+ /**
+ * Returns the title of the drawer with the given gravity.
+ *
+ * @param edgeGravity Gravity.LEFT, RIGHT, START or END. Expresses which
+ * drawer to return the title for.
+ * @return The title of the drawer, or null if none set.
+ * @see #setDrawerTitle(int, CharSequence)
+ */
+ @Nullable
+ public CharSequence getDrawerTitle(@EdgeGravity int edgeGravity) {
+ final int absGravity = GravityCompat.getAbsoluteGravity(
+ edgeGravity, ViewCompat.getLayoutDirection(this));
+ if (absGravity == Gravity.LEFT) {
+ return mTitleLeft;
+ } else if (absGravity == Gravity.RIGHT) {
+ return mTitleRight;
+ }
+ return null;
+ }
+
+ /**
+ * Resolve the shared state of all drawers from the component ViewDragHelpers.
+ * Should be called whenever a ViewDragHelper's state changes.
+ */
+ void updateDrawerState(int forGravity, @State int activeState, View activeDrawer) {
+ final int leftState = mLeftDragger.getViewDragState();
+ final int rightState = mRightDragger.getViewDragState();
+
+ final int state;
+ if (leftState == STATE_DRAGGING || rightState == STATE_DRAGGING) {
+ state = STATE_DRAGGING;
+ } else if (leftState == STATE_SETTLING || rightState == STATE_SETTLING) {
+ state = STATE_SETTLING;
+ } else {
+ state = STATE_IDLE;
+ }
+
+ if (activeDrawer != null && activeState == STATE_IDLE) {
+ final LayoutParams lp = (LayoutParams) activeDrawer.getLayoutParams();
+ if (lp.onScreen == 0) {
+ dispatchOnDrawerClosed(activeDrawer);
+ } else if (lp.onScreen == 1) {
+ dispatchOnDrawerOpened(activeDrawer);
+ }
+ }
+
+ if (state != mDrawerState) {
+ mDrawerState = state;
+
+ if (mListeners != null) {
+ // Notify the listeners. Do that from the end of the list so that if a listener
+ // removes itself as the result of being called, it won't mess up with our iteration
+ int listenerCount = mListeners.size();
+ for (int i = listenerCount - 1; i >= 0; i--) {
+ mListeners.get(i).onDrawerStateChanged(state);
+ }
+ }
+ }
+ }
+
+ void dispatchOnDrawerClosed(View drawerView) {
+ final LayoutParams lp = (LayoutParams) drawerView.getLayoutParams();
+ if ((lp.openState & LayoutParams.FLAG_IS_OPENED) == 1) {
+ lp.openState = 0;
+
+ if (mListeners != null) {
+ // Notify the listeners. Do that from the end of the list so that if a listener
+ // removes itself as the result of being called, it won't mess up with our iteration
+ int listenerCount = mListeners.size();
+ for (int i = listenerCount - 1; i >= 0; i--) {
+ mListeners.get(i).onDrawerClosed(drawerView);
+ }
+ }
+
+ updateChildrenImportantForAccessibility(drawerView, false);
+
+ // Only send WINDOW_STATE_CHANGE if the host has window focus. This
+ // may change if support for multiple foreground windows (e.g. IME)
+ // improves.
+ if (hasWindowFocus()) {
+ final View rootView = getRootView();
+ if (rootView != null) {
+ rootView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
+ }
+ }
+ }
+ }
+
+ void dispatchOnDrawerOpened(View drawerView) {
+ final LayoutParams lp = (LayoutParams) drawerView.getLayoutParams();
+ if ((lp.openState & LayoutParams.FLAG_IS_OPENED) == 0) {
+ lp.openState = LayoutParams.FLAG_IS_OPENED;
+ if (mListeners != null) {
+ // Notify the listeners. Do that from the end of the list so that if a listener
+ // removes itself as the result of being called, it won't mess up with our iteration
+ int listenerCount = mListeners.size();
+ for (int i = listenerCount - 1; i >= 0; i--) {
+ mListeners.get(i).onDrawerOpened(drawerView);
+ }
+ }
+
+ updateChildrenImportantForAccessibility(drawerView, true);
+
+ // Only send WINDOW_STATE_CHANGE if the host has window focus.
+ if (hasWindowFocus()) {
+ sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
+ }
+ }
+ }
+
+ private void updateChildrenImportantForAccessibility(View drawerView, boolean isDrawerOpen) {
+ final int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ final View child = getChildAt(i);
+ if ((!isDrawerOpen && !isDrawerView(child)) || (isDrawerOpen && child == drawerView)) {
+ // Drawer is closed and this is a content view or this is an
+ // open drawer view, so it should be visible.
+ ViewCompat.setImportantForAccessibility(child,
+ ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_YES);
+ } else {
+ ViewCompat.setImportantForAccessibility(child,
+ ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
+ }
+ }
+ }
+
+ void dispatchOnDrawerSlide(View drawerView, float slideOffset) {
+ if (mListeners != null) {
+ // Notify the listeners. Do that from the end of the list so that if a listener
+ // removes itself as the result of being called, it won't mess up with our iteration
+ int listenerCount = mListeners.size();
+ for (int i = listenerCount - 1; i >= 0; i--) {
+ mListeners.get(i).onDrawerSlide(drawerView, slideOffset);
+ }
+ }
+ }
+
+ void setDrawerViewOffset(View drawerView, float slideOffset) {
+ final LayoutParams lp = (LayoutParams) drawerView.getLayoutParams();
+ if (slideOffset == lp.onScreen) {
+ return;
+ }
+
+ lp.onScreen = slideOffset;
+ dispatchOnDrawerSlide(drawerView, slideOffset);
+ }
+
+ float getDrawerViewOffset(View drawerView) {
+ return ((LayoutParams) drawerView.getLayoutParams()).onScreen;
+ }
+
+ /**
+ * @return the absolute gravity of the child drawerView, resolved according
+ * to the current layout direction
+ */
+ int getDrawerViewAbsoluteGravity(View drawerView) {
+ final int gravity = ((LayoutParams) drawerView.getLayoutParams()).gravity;
+ return GravityCompat.getAbsoluteGravity(gravity, ViewCompat.getLayoutDirection(this));
+ }
+
+ boolean checkDrawerViewAbsoluteGravity(View drawerView, int checkFor) {
+ final int absGravity = getDrawerViewAbsoluteGravity(drawerView);
+ return (absGravity & checkFor) == checkFor;
+ }
+
+ View findOpenDrawer() {
+ final int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ final View child = getChildAt(i);
+ final LayoutParams childLp = (LayoutParams) child.getLayoutParams();
+ if ((childLp.openState & LayoutParams.FLAG_IS_OPENED) == 1) {
+ return child;
+ }
+ }
+ return null;
+ }
+
+ void moveDrawerToOffset(View drawerView, float slideOffset) {
+ final float oldOffset = getDrawerViewOffset(drawerView);
+ final int width = drawerView.getWidth();
+ final int oldPos = (int) (width * oldOffset);
+ final int newPos = (int) (width * slideOffset);
+ final int dx = newPos - oldPos;
+
+ drawerView.offsetLeftAndRight(
+ checkDrawerViewAbsoluteGravity(drawerView, Gravity.LEFT) ? dx : -dx);
+ setDrawerViewOffset(drawerView, slideOffset);
+ }
+
+ /**
+ * @param gravity the gravity of the child to return. If specified as a
+ * relative value, it will be resolved according to the current
+ * layout direction.
+ * @return the drawer with the specified gravity
+ */
+ View findDrawerWithGravity(int gravity) {
+ final int absHorizGravity = GravityCompat.getAbsoluteGravity(
+ gravity, ViewCompat.getLayoutDirection(this)) & Gravity.HORIZONTAL_GRAVITY_MASK;
+ final int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ final View child = getChildAt(i);
+ final int childAbsGravity = getDrawerViewAbsoluteGravity(child);
+ if ((childAbsGravity & Gravity.HORIZONTAL_GRAVITY_MASK) == absHorizGravity) {
+ return child;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Simple gravity to string - only supports LEFT and RIGHT for debugging output.
+ *
+ * @param gravity Absolute gravity value
+ * @return LEFT or RIGHT as appropriate, or a hex string
+ */
+ static String gravityToString(@EdgeGravity int gravity) {
+ if ((gravity & Gravity.LEFT) == Gravity.LEFT) {
+ return "LEFT";
+ }
+ if ((gravity & Gravity.RIGHT) == Gravity.RIGHT) {
+ return "RIGHT";
+ }
+ return Integer.toHexString(gravity);
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ mFirstLayout = true;
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ mFirstLayout = true;
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ int widthMode = MeasureSpec.getMode(widthMeasureSpec);
+ int heightMode = MeasureSpec.getMode(heightMeasureSpec);
+ int widthSize = MeasureSpec.getSize(widthMeasureSpec);
+ int heightSize = MeasureSpec.getSize(heightMeasureSpec);
+
+ if (widthMode != MeasureSpec.EXACTLY || heightMode != MeasureSpec.EXACTLY) {
+ if (isInEditMode()) {
+ // Don't crash the layout editor. Consume all of the space if specified
+ // or pick a magic number from thin air otherwise.
+ // TODO Better communication with tools of this bogus state.
+ // It will crash on a real device.
+ if (widthMode == MeasureSpec.AT_MOST) {
+ widthMode = MeasureSpec.EXACTLY;
+ } else if (widthMode == MeasureSpec.UNSPECIFIED) {
+ widthMode = MeasureSpec.EXACTLY;
+ widthSize = 300;
+ }
+ if (heightMode == MeasureSpec.AT_MOST) {
+ heightMode = MeasureSpec.EXACTLY;
+ } else if (heightMode == MeasureSpec.UNSPECIFIED) {
+ heightMode = MeasureSpec.EXACTLY;
+ heightSize = 300;
+ }
+ } else {
+ throw new IllegalArgumentException(
+ "DrawerLayout must be measured with MeasureSpec.EXACTLY.");
+ }
+ }
+
+ setMeasuredDimension(widthSize, heightSize);
+
+ final boolean applyInsets = mLastInsets != null && ViewCompat.getFitsSystemWindows(this);
+ final int layoutDirection = ViewCompat.getLayoutDirection(this);
+
+ // Only one drawer is permitted along each vertical edge (left / right). These two booleans
+ // are tracking the presence of the edge drawers.
+ boolean hasDrawerOnLeftEdge = false;
+ boolean hasDrawerOnRightEdge = false;
+ final int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ final View child = getChildAt(i);
+
+ if (child.getVisibility() == GONE) {
+ continue;
+ }
+
+ final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+
+ if (applyInsets) {
+ final int cgrav = GravityCompat.getAbsoluteGravity(lp.gravity, layoutDirection);
+ if (ViewCompat.getFitsSystemWindows(child)) {
+ if (Build.VERSION.SDK_INT >= 21) {
+ WindowInsets wi = (WindowInsets) mLastInsets;
+ if (cgrav == Gravity.LEFT) {
+ wi = wi.replaceSystemWindowInsets(wi.getSystemWindowInsetLeft(),
+ wi.getSystemWindowInsetTop(), 0,
+ wi.getSystemWindowInsetBottom());
+ } else if (cgrav == Gravity.RIGHT) {
+ wi = wi.replaceSystemWindowInsets(0, wi.getSystemWindowInsetTop(),
+ wi.getSystemWindowInsetRight(),
+ wi.getSystemWindowInsetBottom());
+ }
+ child.dispatchApplyWindowInsets(wi);
+ }
+ } else {
+ if (Build.VERSION.SDK_INT >= 21) {
+ WindowInsets wi = (WindowInsets) mLastInsets;
+ if (cgrav == Gravity.LEFT) {
+ wi = wi.replaceSystemWindowInsets(wi.getSystemWindowInsetLeft(),
+ wi.getSystemWindowInsetTop(), 0,
+ wi.getSystemWindowInsetBottom());
+ } else if (cgrav == Gravity.RIGHT) {
+ wi = wi.replaceSystemWindowInsets(0, wi.getSystemWindowInsetTop(),
+ wi.getSystemWindowInsetRight(),
+ wi.getSystemWindowInsetBottom());
+ }
+ lp.leftMargin = wi.getSystemWindowInsetLeft();
+ lp.topMargin = wi.getSystemWindowInsetTop();
+ lp.rightMargin = wi.getSystemWindowInsetRight();
+ lp.bottomMargin = wi.getSystemWindowInsetBottom();
+ }
+ }
+ }
+
+ if (isContentView(child)) {
+ // Content views get measured at exactly the layout's size.
+ final int contentWidthSpec = MeasureSpec.makeMeasureSpec(
+ widthSize - lp.leftMargin - lp.rightMargin, MeasureSpec.EXACTLY);
+ final int contentHeightSpec = MeasureSpec.makeMeasureSpec(
+ heightSize - lp.topMargin - lp.bottomMargin, MeasureSpec.EXACTLY);
+ child.measure(contentWidthSpec, contentHeightSpec);
+ } else if (isDrawerView(child)) {
+ if (SET_DRAWER_SHADOW_FROM_ELEVATION) {
+ if (ViewCompat.getElevation(child) != mDrawerElevation) {
+ ViewCompat.setElevation(child, mDrawerElevation);
+ }
+ }
+ final @EdgeGravity int childGravity =
+ getDrawerViewAbsoluteGravity(child) & Gravity.HORIZONTAL_GRAVITY_MASK;
+ // Note that the isDrawerView check guarantees that childGravity here is either
+ // LEFT or RIGHT
+ boolean isLeftEdgeDrawer = (childGravity == Gravity.LEFT);
+ if ((isLeftEdgeDrawer && hasDrawerOnLeftEdge)
+ || (!isLeftEdgeDrawer && hasDrawerOnRightEdge)) {
+ throw new IllegalStateException("Child drawer has absolute gravity "
+ + gravityToString(childGravity) + " but this " + TAG + " already has a "
+ + "drawer view along that edge");
+ }
+ if (isLeftEdgeDrawer) {
+ hasDrawerOnLeftEdge = true;
+ } else {
+ hasDrawerOnRightEdge = true;
+ }
+ final int drawerWidthSpec = getChildMeasureSpec(widthMeasureSpec,
+ mMinDrawerMargin + lp.leftMargin + lp.rightMargin,
+ lp.width);
+ final int drawerHeightSpec = getChildMeasureSpec(heightMeasureSpec,
+ lp.topMargin + lp.bottomMargin,
+ lp.height);
+ child.measure(drawerWidthSpec, drawerHeightSpec);
+ } else {
+ throw new IllegalStateException("Child " + child + " at index " + i
+ + " does not have a valid layout_gravity - must be Gravity.LEFT, "
+ + "Gravity.RIGHT or Gravity.NO_GRAVITY");
+ }
+ }
+ }
+
+ private void resolveShadowDrawables() {
+ if (SET_DRAWER_SHADOW_FROM_ELEVATION) {
+ return;
+ }
+ mShadowLeftResolved = resolveLeftShadow();
+ mShadowRightResolved = resolveRightShadow();
+ }
+
+ private Drawable resolveLeftShadow() {
+ int layoutDirection = ViewCompat.getLayoutDirection(this);
+ // Prefer shadows defined with start/end gravity over left and right.
+ if (layoutDirection == ViewCompat.LAYOUT_DIRECTION_LTR) {
+ if (mShadowStart != null) {
+ // Correct drawable layout direction, if needed.
+ mirror(mShadowStart, layoutDirection);
+ return mShadowStart;
+ }
+ } else {
+ if (mShadowEnd != null) {
+ // Correct drawable layout direction, if needed.
+ mirror(mShadowEnd, layoutDirection);
+ return mShadowEnd;
+ }
+ }
+ return mShadowLeft;
+ }
+
+ private Drawable resolveRightShadow() {
+ int layoutDirection = ViewCompat.getLayoutDirection(this);
+ if (layoutDirection == ViewCompat.LAYOUT_DIRECTION_LTR) {
+ if (mShadowEnd != null) {
+ // Correct drawable layout direction, if needed.
+ mirror(mShadowEnd, layoutDirection);
+ return mShadowEnd;
+ }
+ } else {
+ if (mShadowStart != null) {
+ // Correct drawable layout direction, if needed.
+ mirror(mShadowStart, layoutDirection);
+ return mShadowStart;
+ }
+ }
+ return mShadowRight;
+ }
+
+ /**
+ * Change the layout direction of the given drawable.
+ * Return true if auto-mirror is supported and drawable's layout direction can be changed.
+ * Otherwise, return false.
+ */
+ private boolean mirror(Drawable drawable, int layoutDirection) {
+ if (drawable == null || !DrawableCompat.isAutoMirrored(drawable)) {
+ return false;
+ }
+
+ DrawableCompat.setLayoutDirection(drawable, layoutDirection);
+ return true;
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int l, int t, int r, int b) {
+ mInLayout = true;
+ final int width = r - l;
+ final int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ final View child = getChildAt(i);
+
+ if (child.getVisibility() == GONE) {
+ continue;
+ }
+
+ final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+
+ if (isContentView(child)) {
+ child.layout(lp.leftMargin, lp.topMargin,
+ lp.leftMargin + child.getMeasuredWidth(),
+ lp.topMargin + child.getMeasuredHeight());
+ } else { // Drawer, if it wasn't onMeasure would have thrown an exception.
+ final int childWidth = child.getMeasuredWidth();
+ final int childHeight = child.getMeasuredHeight();
+ int childLeft;
+
+ final float newOffset;
+ if (checkDrawerViewAbsoluteGravity(child, Gravity.LEFT)) {
+ childLeft = -childWidth + (int) (childWidth * lp.onScreen);
+ newOffset = (float) (childWidth + childLeft) / childWidth;
+ } else { // Right; onMeasure checked for us.
+ childLeft = width - (int) (childWidth * lp.onScreen);
+ newOffset = (float) (width - childLeft) / childWidth;
+ }
+
+ final boolean changeOffset = newOffset != lp.onScreen;
+
+ final int vgrav = lp.gravity & Gravity.VERTICAL_GRAVITY_MASK;
+
+ switch (vgrav) {
+ default:
+ case Gravity.TOP: {
+ child.layout(childLeft, lp.topMargin, childLeft + childWidth,
+ lp.topMargin + childHeight);
+ break;
+ }
+
+ case Gravity.BOTTOM: {
+ final int height = b - t;
+ child.layout(childLeft,
+ height - lp.bottomMargin - child.getMeasuredHeight(),
+ childLeft + childWidth,
+ height - lp.bottomMargin);
+ break;
+ }
+
+ case Gravity.CENTER_VERTICAL: {
+ final int height = b - t;
+ int childTop = (height - childHeight) / 2;
+
+ // Offset for margins. If things don't fit right because of
+ // bad measurement before, oh well.
+ if (childTop < lp.topMargin) {
+ childTop = lp.topMargin;
+ } else if (childTop + childHeight > height - lp.bottomMargin) {
+ childTop = height - lp.bottomMargin - childHeight;
+ }
+ child.layout(childLeft, childTop, childLeft + childWidth,
+ childTop + childHeight);
+ break;
+ }
+ }
+
+ if (changeOffset) {
+ setDrawerViewOffset(child, newOffset);
+ }
+
+ final int newVisibility = lp.onScreen > 0 ? VISIBLE : INVISIBLE;
+ if (child.getVisibility() != newVisibility) {
+ child.setVisibility(newVisibility);
+ }
+ }
+ }
+ mInLayout = false;
+ mFirstLayout = false;
+ }
+
+ @Override
+ public void requestLayout() {
+ if (!mInLayout) {
+ super.requestLayout();
+ }
+ }
+
+ @Override
+ public void computeScroll() {
+ final int childCount = getChildCount();
+ float scrimOpacity = 0;
+ for (int i = 0; i < childCount; i++) {
+ final float onscreen = ((LayoutParams) getChildAt(i).getLayoutParams()).onScreen;
+ scrimOpacity = Math.max(scrimOpacity, onscreen);
+ }
+ mScrimOpacity = scrimOpacity;
+
+ boolean leftDraggerSettling = mLeftDragger.continueSettling(true);
+ boolean rightDraggerSettling = mRightDragger.continueSettling(true);
+ if (leftDraggerSettling || rightDraggerSettling) {
+ ViewCompat.postInvalidateOnAnimation(this);
+ }
+ }
+
+ private static boolean hasOpaqueBackground(View v) {
+ final Drawable bg = v.getBackground();
+ if (bg != null) {
+ return bg.getOpacity() == PixelFormat.OPAQUE;
+ }
+ return false;
+ }
+
+ /**
+ * Set a drawable to draw in the insets area for the status bar.
+ * Note that this will only be activated if this DrawerLayout fitsSystemWindows.
+ *
+ * @param bg Background drawable to draw behind the status bar
+ */
+ public void setStatusBarBackground(@Nullable Drawable bg) {
+ mStatusBarBackground = bg;
+ invalidate();
+ }
+
+ /**
+ * Gets the drawable used to draw in the insets area for the status bar.
+ *
+ * @return The status bar background drawable, or null if none set
+ */
+ @Nullable
+ public Drawable getStatusBarBackgroundDrawable() {
+ return mStatusBarBackground;
+ }
+
+ /**
+ * Set a drawable to draw in the insets area for the status bar.
+ * Note that this will only be activated if this DrawerLayout fitsSystemWindows.
+ *
+ * @param resId Resource id of a background drawable to draw behind the status bar
+ */
+ public void setStatusBarBackground(int resId) {
+ mStatusBarBackground = resId != 0 ? ContextCompat.getDrawable(getContext(), resId) : null;
+ invalidate();
+ }
+
+ /**
+ * Set a drawable to draw in the insets area for the status bar.
+ * Note that this will only be activated if this DrawerLayout fitsSystemWindows.
+ *
+ * @param color Color to use as a background drawable to draw behind the status bar
+ * in 0xAARRGGBB format.
+ */
+ public void setStatusBarBackgroundColor(@ColorInt int color) {
+ mStatusBarBackground = new ColorDrawable(color);
+ invalidate();
+ }
+
+ @Override
+ public void onRtlPropertiesChanged(int layoutDirection) {
+ resolveShadowDrawables();
+ }
+
+ @Override
+ public void onDraw(Canvas c) {
+ super.onDraw(c);
+ if (mDrawStatusBarBackground && mStatusBarBackground != null) {
+ final int inset;
+ if (Build.VERSION.SDK_INT >= 21) {
+ inset = mLastInsets != null
+ ? ((WindowInsets) mLastInsets).getSystemWindowInsetTop() : 0;
+ } else {
+ inset = 0;
+ }
+ if (inset > 0) {
+ mStatusBarBackground.setBounds(0, 0, getWidth(), inset);
+ mStatusBarBackground.draw(c);
+ }
+ }
+ }
+
+ @Override
+ protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
+ final int height = getHeight();
+ final boolean drawingContent = isContentView(child);
+ int clipLeft = 0, clipRight = getWidth();
+
+ final int restoreCount = canvas.save();
+ if (drawingContent) {
+ final int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ final View v = getChildAt(i);
+ if (v == child || v.getVisibility() != VISIBLE
+ || !hasOpaqueBackground(v) || !isDrawerView(v)
+ || v.getHeight() < height) {
+ continue;
+ }
+
+ if (checkDrawerViewAbsoluteGravity(v, Gravity.LEFT)) {
+ final int vright = v.getRight();
+ if (vright > clipLeft) clipLeft = vright;
+ } else {
+ final int vleft = v.getLeft();
+ if (vleft < clipRight) clipRight = vleft;
+ }
+ }
+ canvas.clipRect(clipLeft, 0, clipRight, getHeight());
+ }
+ final boolean result = super.drawChild(canvas, child, drawingTime);
+ canvas.restoreToCount(restoreCount);
+
+ if (mScrimOpacity > 0 && drawingContent) {
+ final int baseAlpha = (mScrimColor & 0xff000000) >>> 24;
+ final int imag = (int) (baseAlpha * mScrimOpacity);
+ final int color = imag << 24 | (mScrimColor & 0xffffff);
+ mScrimPaint.setColor(color);
+
+ canvas.drawRect(clipLeft, 0, clipRight, getHeight(), mScrimPaint);
+ } else if (mShadowLeftResolved != null
+ && checkDrawerViewAbsoluteGravity(child, Gravity.LEFT)) {
+ final int shadowWidth = mShadowLeftResolved.getIntrinsicWidth();
+ final int childRight = child.getRight();
+ final int drawerPeekDistance = mLeftDragger.getEdgeSize();
+ final float alpha =
+ Math.max(0, Math.min((float) childRight / drawerPeekDistance, 1.f));
+ mShadowLeftResolved.setBounds(childRight, child.getTop(),
+ childRight + shadowWidth, child.getBottom());
+ mShadowLeftResolved.setAlpha((int) (0xff * alpha));
+ mShadowLeftResolved.draw(canvas);
+ } else if (mShadowRightResolved != null
+ && checkDrawerViewAbsoluteGravity(child, Gravity.RIGHT)) {
+ final int shadowWidth = mShadowRightResolved.getIntrinsicWidth();
+ final int childLeft = child.getLeft();
+ final int showing = getWidth() - childLeft;
+ final int drawerPeekDistance = mRightDragger.getEdgeSize();
+ final float alpha =
+ Math.max(0, Math.min((float) showing / drawerPeekDistance, 1.f));
+ mShadowRightResolved.setBounds(childLeft - shadowWidth, child.getTop(),
+ childLeft, child.getBottom());
+ mShadowRightResolved.setAlpha((int) (0xff * alpha));
+ mShadowRightResolved.draw(canvas);
+ }
+ return result;
+ }
+
+ boolean isContentView(View child) {
+ return ((LayoutParams) child.getLayoutParams()).gravity == Gravity.NO_GRAVITY;
+ }
+
+ boolean isDrawerView(View child) {
+ final int gravity = ((LayoutParams) child.getLayoutParams()).gravity;
+ final int absGravity = GravityCompat.getAbsoluteGravity(gravity,
+ ViewCompat.getLayoutDirection(child));
+ if ((absGravity & Gravity.LEFT) != 0) {
+ // This child is a left-edge drawer
+ return true;
+ }
+ if ((absGravity & Gravity.RIGHT) != 0) {
+ // This child is a right-edge drawer
+ return true;
+ }
+ return false;
+ }
+
+ @SuppressWarnings("ShortCircuitBoolean")
+ @Override
+ public boolean onInterceptTouchEvent(MotionEvent ev) {
+ try {
+ final int action = ev.getActionMasked();
+
+ // "|" used deliberately here; both methods should be invoked.
+ final boolean interceptForDrag = mLeftDragger.shouldInterceptTouchEvent(ev)
+ | mRightDragger.shouldInterceptTouchEvent(ev);
+
+ boolean interceptForTap = false;
+
+ switch (action) {
+ case MotionEvent.ACTION_DOWN: {
+ final float x = ev.getX();
+ final float y = ev.getY();
+ mInitialMotionX = x;
+ mInitialMotionY = y;
+ if (mScrimOpacity > 0) {
+ final View child = mLeftDragger.findTopChildUnder((int) x, (int) y);
+ if (child != null && isContentView(child)) {
+ interceptForTap = true;
+ }
+ }
+ mDisallowInterceptRequested = false;
+ mChildrenCanceledTouch = false;
+ break;
+ }
+
+ case MotionEvent.ACTION_MOVE: {
+ // If we cross the touch slop, don't perform the delayed peek for an edge touch.
+ if (mLeftDragger.checkTouchSlop(ViewDragHelper.DIRECTION_ALL)) {
+ mLeftCallback.removeCallbacks();
+ mRightCallback.removeCallbacks();
+ }
+ break;
+ }
+
+ case MotionEvent.ACTION_CANCEL:
+ case MotionEvent.ACTION_UP: {
+ closeDrawers(true);
+ mDisallowInterceptRequested = false;
+ mChildrenCanceledTouch = false;
+ }
+ }
+
+ return interceptForDrag || interceptForTap || hasPeekingDrawer() || mChildrenCanceledTouch;
+ }catch (IllegalArgumentException e){
+ e.printStackTrace();
+ }
+ return false;
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent ev) {
+ try {
+ mLeftDragger.processTouchEvent(ev);
+ mRightDragger.processTouchEvent(ev);
+
+ final int action = ev.getAction();
+ boolean wantTouchEvents = true;
+
+ switch (action & MotionEvent.ACTION_MASK) {
+ case MotionEvent.ACTION_DOWN: {
+ final float x = ev.getX();
+ final float y = ev.getY();
+ mInitialMotionX = x;
+ mInitialMotionY = y;
+ mDisallowInterceptRequested = false;
+ mChildrenCanceledTouch = false;
+ break;
+ }
+
+ case MotionEvent.ACTION_UP: {
+ final float x = ev.getX();
+ final float y = ev.getY();
+ boolean peekingOnly = true;
+ final View touchedView = mLeftDragger.findTopChildUnder((int) x, (int) y);
+ if (touchedView != null && isContentView(touchedView)) {
+ final float dx = x - mInitialMotionX;
+ final float dy = y - mInitialMotionY;
+ final int slop = mLeftDragger.getTouchSlop();
+ if (dx * dx + dy * dy < slop * slop) {
+ // Taps close a dimmed open drawer but only if it isn't locked open.
+ final View openDrawer = findOpenDrawer();
+ if (openDrawer != null) {
+ peekingOnly = getDrawerLockMode(openDrawer) == LOCK_MODE_LOCKED_OPEN;
+ }
+ }
+ }
+ closeDrawers(peekingOnly);
+ mDisallowInterceptRequested = false;
+ break;
+ }
+
+ case MotionEvent.ACTION_CANCEL: {
+ closeDrawers(true);
+ mDisallowInterceptRequested = false;
+ mChildrenCanceledTouch = false;
+ break;
+ }
+ }
+
+ return wantTouchEvents;
+ }catch (IllegalArgumentException e){
+ e.printStackTrace();
+ }
+ return false;
+ }
+
+ @Override
+ public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
+ if (CHILDREN_DISALLOW_INTERCEPT
+ || (!mLeftDragger.isEdgeTouched(ViewDragHelper.EDGE_LEFT)
+ && !mRightDragger.isEdgeTouched(ViewDragHelper.EDGE_RIGHT))) {
+ // If we have an edge touch we want to skip this and track it for later instead.
+ super.requestDisallowInterceptTouchEvent(disallowIntercept);
+ }
+ mDisallowInterceptRequested = disallowIntercept;
+ if (disallowIntercept) {
+ closeDrawers(true);
+ }
+ }
+
+ /**
+ * Close all currently open drawer views by animating them out of view.
+ */
+ public void closeDrawers() {
+ closeDrawers(false);
+ }
+
+ void closeDrawers(boolean peekingOnly) {
+ boolean needsInvalidate = false;
+ final int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ final View child = getChildAt(i);
+ final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+
+ if (!isDrawerView(child) || (peekingOnly && !lp.isPeeking)) {
+ continue;
+ }
+
+ final int childWidth = child.getWidth();
+
+ if (checkDrawerViewAbsoluteGravity(child, Gravity.LEFT)) {
+ needsInvalidate |= mLeftDragger.smoothSlideViewTo(child,
+ -childWidth, child.getTop());
+ } else {
+ needsInvalidate |= mRightDragger.smoothSlideViewTo(child,
+ getWidth(), child.getTop());
+ }
+
+ lp.isPeeking = false;
+ }
+
+ mLeftCallback.removeCallbacks();
+ mRightCallback.removeCallbacks();
+
+ if (needsInvalidate) {
+ invalidate();
+ }
+ }
+
+ /**
+ * Open the specified drawer view by animating it into view.
+ *
+ * @param drawerView Drawer view to open
+ */
+ public void openDrawer(@NonNull View drawerView) {
+ openDrawer(drawerView, true);
+ }
+
+ /**
+ * Open the specified drawer view.
+ *
+ * @param drawerView Drawer view to open
+ * @param animate Whether opening of the drawer should be animated.
+ */
+ public void openDrawer(@NonNull View drawerView, boolean animate) {
+ if (!isDrawerView(drawerView)) {
+ throw new IllegalArgumentException("View " + drawerView + " is not a sliding drawer");
+ }
+
+ final LayoutParams lp = (LayoutParams) drawerView.getLayoutParams();
+ if (mFirstLayout) {
+ lp.onScreen = 1.f;
+ lp.openState = LayoutParams.FLAG_IS_OPENED;
+
+ updateChildrenImportantForAccessibility(drawerView, true);
+ } else if (animate) {
+ lp.openState |= LayoutParams.FLAG_IS_OPENING;
+
+ if (checkDrawerViewAbsoluteGravity(drawerView, Gravity.LEFT)) {
+ mLeftDragger.smoothSlideViewTo(drawerView, 0, drawerView.getTop());
+ } else {
+ mRightDragger.smoothSlideViewTo(drawerView, getWidth() - drawerView.getWidth(),
+ drawerView.getTop());
+ }
+ } else {
+ moveDrawerToOffset(drawerView, 1.f);
+ updateDrawerState(lp.gravity, STATE_IDLE, drawerView);
+ drawerView.setVisibility(VISIBLE);
+ }
+ invalidate();
+ }
+
+ /**
+ * Open the specified drawer by animating it out of view.
+ *
+ * @param gravity Gravity.LEFT to move the left drawer or Gravity.RIGHT for the right.
+ * GravityCompat.START or GravityCompat.END may also be used.
+ */
+ public void openDrawer(@EdgeGravity int gravity) {
+ openDrawer(gravity, true);
+ }
+
+ /**
+ * Open the specified drawer.
+ *
+ * @param gravity Gravity.LEFT to move the left drawer or Gravity.RIGHT for the right.
+ * GravityCompat.START or GravityCompat.END may also be used.
+ * @param animate Whether opening of the drawer should be animated.
+ */
+ public void openDrawer(@EdgeGravity int gravity, boolean animate) {
+ final View drawerView = findDrawerWithGravity(gravity);
+ if (drawerView == null) {
+ throw new IllegalArgumentException("No drawer view found with gravity "
+ + gravityToString(gravity));
+ }
+ openDrawer(drawerView, animate);
+ }
+
+ /**
+ * Close the specified drawer view by animating it into view.
+ *
+ * @param drawerView Drawer view to close
+ */
+ public void closeDrawer(@NonNull View drawerView) {
+ closeDrawer(drawerView, true);
+ }
+
+ /**
+ * Close the specified drawer view.
+ *
+ * @param drawerView Drawer view to close
+ * @param animate Whether closing of the drawer should be animated.
+ */
+ public void closeDrawer(@NonNull View drawerView, boolean animate) {
+ if (!isDrawerView(drawerView)) {
+ throw new IllegalArgumentException("View " + drawerView + " is not a sliding drawer");
+ }
+
+ final LayoutParams lp = (LayoutParams) drawerView.getLayoutParams();
+ if (mFirstLayout) {
+ lp.onScreen = 0.f;
+ lp.openState = 0;
+ } else if (animate) {
+ lp.openState |= LayoutParams.FLAG_IS_CLOSING;
+
+ if (checkDrawerViewAbsoluteGravity(drawerView, Gravity.LEFT)) {
+ mLeftDragger.smoothSlideViewTo(drawerView, -drawerView.getWidth(),
+ drawerView.getTop());
+ } else {
+ mRightDragger.smoothSlideViewTo(drawerView, getWidth(), drawerView.getTop());
+ }
+ } else {
+ moveDrawerToOffset(drawerView, 0.f);
+ updateDrawerState(lp.gravity, STATE_IDLE, drawerView);
+ drawerView.setVisibility(INVISIBLE);
+ }
+ invalidate();
+ }
+
+ /**
+ * Close the specified drawer by animating it out of view.
+ *
+ * @param gravity Gravity.LEFT to move the left drawer or Gravity.RIGHT for the right.
+ * GravityCompat.START or GravityCompat.END may also be used.
+ */
+ public void closeDrawer(@EdgeGravity int gravity) {
+ closeDrawer(gravity, true);
+ }
+
+ /**
+ * Close the specified drawer.
+ *
+ * @param gravity Gravity.LEFT to move the left drawer or Gravity.RIGHT for the right.
+ * GravityCompat.START or GravityCompat.END may also be used.
+ * @param animate Whether closing of the drawer should be animated.
+ */
+ public void closeDrawer(@EdgeGravity int gravity, boolean animate) {
+ final View drawerView = findDrawerWithGravity(gravity);
+ if (drawerView == null) {
+ throw new IllegalArgumentException("No drawer view found with gravity "
+ + gravityToString(gravity));
+ }
+ closeDrawer(drawerView, animate);
+ }
+
+ /**
+ * Check if the given drawer view is currently in an open state.
+ * To be considered "open" the drawer must have settled into its fully
+ * visible state. To check for partial visibility use
+ * {@link #isDrawerVisible(android.view.View)}.
+ *
+ * @param drawer Drawer view to check
+ * @return true if the given drawer view is in an open state
+ * @see #isDrawerVisible(android.view.View)
+ */
+ public boolean isDrawerOpen(@NonNull View drawer) {
+ if (!isDrawerView(drawer)) {
+ throw new IllegalArgumentException("View " + drawer + " is not a drawer");
+ }
+ LayoutParams drawerLp = (LayoutParams) drawer.getLayoutParams();
+ return (drawerLp.openState & LayoutParams.FLAG_IS_OPENED) == 1;
+ }
+
+ /**
+ * Check if the given drawer view is currently in an open state.
+ * To be considered "open" the drawer must have settled into its fully
+ * visible state. If there is no drawer with the given gravity this method
+ * will return false.
+ *
+ * @param drawerGravity Gravity of the drawer to check
+ * @return true if the given drawer view is in an open state
+ */
+ public boolean isDrawerOpen(@EdgeGravity int drawerGravity) {
+ final View drawerView = findDrawerWithGravity(drawerGravity);
+ if (drawerView != null) {
+ return isDrawerOpen(drawerView);
+ }
+ return false;
+ }
+
+ /**
+ * Check if a given drawer view is currently visible on-screen. The drawer
+ * may be only peeking onto the screen, fully extended, or anywhere inbetween.
+ *
+ * @param drawer Drawer view to check
+ * @return true if the given drawer is visible on-screen
+ * @see #isDrawerOpen(android.view.View)
+ */
+ public boolean isDrawerVisible(@NonNull View drawer) {
+ if (!isDrawerView(drawer)) {
+ throw new IllegalArgumentException("View " + drawer + " is not a drawer");
+ }
+ return ((LayoutParams) drawer.getLayoutParams()).onScreen > 0;
+ }
+
+ /**
+ * Check if a given drawer view is currently visible on-screen. The drawer
+ * may be only peeking onto the screen, fully extended, or anywhere in between.
+ * If there is no drawer with the given gravity this method will return false.
+ *
+ * @param drawerGravity Gravity of the drawer to check
+ * @return true if the given drawer is visible on-screen
+ */
+ public boolean isDrawerVisible(@EdgeGravity int drawerGravity) {
+ final View drawerView = findDrawerWithGravity(drawerGravity);
+ if (drawerView != null) {
+ return isDrawerVisible(drawerView);
+ }
+ return false;
+ }
+
+ private boolean hasPeekingDrawer() {
+ final int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ final LayoutParams lp = (LayoutParams) getChildAt(i).getLayoutParams();
+ if (lp.isPeeking) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
+ return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
+ }
+
+ @Override
+ protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
+ return p instanceof LayoutParams
+ ? new LayoutParams((LayoutParams) p)
+ : p instanceof ViewGroup.MarginLayoutParams
+ ? new LayoutParams((MarginLayoutParams) p)
+ : new LayoutParams(p);
+ }
+
+ @Override
+ protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
+ return p instanceof LayoutParams && super.checkLayoutParams(p);
+ }
+
+ @Override
+ public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
+ return new LayoutParams(getContext(), attrs);
+ }
+
+ @Override
+ public void addFocusables(ArrayList The onChanged() method is called whenever current spinnerwheel positions is changed:
+ * The onItemClicked() method is called whenever a spinnerwheel item is clicked
+ * alpha
of the {@link Paint} for drawing separators
+ * spinnerwheel.
+ * @param alpha alpha value from 0 to 255
+ */
+ @SuppressWarnings("unused") // Called via reflection
+ @Keep
+ public void setSeparatorsPaintAlpha(int alpha) {
+ mSeparatorsPaint.setAlpha(alpha);
+ invalidate();
+ }
+
+ @Override
+ public void removeBitmap(){
+ if(mSpinBitmap != null && !mSpinBitmap.isRecycled()){
+ mSpinBitmap.recycle();
+ mSpinBitmap = null;
+ }
+//
+// if(mSeparatorsBitmap != null && !mSeparatorsBitmap.isRecycled()){
+// mSeparatorsBitmap.recycle();
+// mSeparatorsBitmap = null;
+// }
+ }
+
+ /**
+ * Sets the coeff
of the {@link Paint} for drawing
+ * the selector spinnerwheel.
+ *
+ * @param coeff Coefficient from 0 (selector is passive) to 1 (selector is active)
+ */
+ @Keep
+ abstract public void setSelectorPaintCoeff(float coeff);
+
+
+ //--------------------------------------------------------------------------
+ //
+ // Processing scroller events
+ //
+ //--------------------------------------------------------------------------
+
+ @Override
+ protected void onScrollTouched() {
+ mDimSelectorWheelAnimator.cancel();
+ mDimSeparatorsAnimator.cancel();
+ setSelectorPaintCoeff(1);
+ setSeparatorsPaintAlpha(mSelectionDividerActiveAlpha);
+ }
+
+ @Override
+ protected void onScrollTouchedUp() {
+ super.onScrollTouchedUp();
+ fadeSelectorWheel(750);
+ lightSeparators(750);
+ }
+
+ @Override
+ protected void onScrollFinished() {
+ fadeSelectorWheel(500);
+ lightSeparators(500);
+ }
+
+ //----------------------------------
+ // Animating components
+ //----------------------------------
+
+ /**
+ * Fade the selector spinnerwheel via an animation.
+ *
+ * @param animationDuration The duration of the animation.
+ */
+ private void fadeSelectorWheel(long animationDuration) {
+ mDimSelectorWheelAnimator.setDuration(animationDuration);
+ mDimSelectorWheelAnimator.start();
+ }
+
+ /**
+ * Fade the selector spinnerwheel via an animation.
+ *
+ * @param animationDuration The duration of the animation.
+ */
+ private void lightSeparators(long animationDuration) {
+ mDimSeparatorsAnimator.setDuration(animationDuration);
+ mDimSeparatorsAnimator.start();
+ }
+
+
+ //--------------------------------------------------------------------------
+ //
+ // Layout measuring
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Perform layout measurements
+ */
+ abstract protected void measureLayout();
+
+
+ //--------------------------------------------------------------------------
+ //
+ // Drawing stuff
+ //
+ //--------------------------------------------------------------------------
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+
+ if (mViewAdapter != null && mViewAdapter.getItemsCount() > 0) {
+ if (rebuildItems()) {
+ measureLayout();
+ }
+ doItemsLayout();
+ drawItems(canvas);
+ }
+ }
+
+ /**
+ * Draws items on specified canvas
+ *
+ * @param canvas the canvas for drawing
+ */
+ abstract protected void drawItems(Canvas canvas);
+}
diff --git a/DeviceAddModule/src/main/java/com/mm/android/deviceaddmodule/mobilecommon/widget/antistatic/spinnerwheel/ItemsRange.java b/DeviceAddModule/src/main/java/com/mm/android/deviceaddmodule/mobilecommon/widget/antistatic/spinnerwheel/ItemsRange.java
new file mode 100644
index 0000000..2e3125c
--- /dev/null
+++ b/DeviceAddModule/src/main/java/com/mm/android/deviceaddmodule/mobilecommon/widget/antistatic/spinnerwheel/ItemsRange.java
@@ -0,0 +1,62 @@
+package com.mm.android.deviceaddmodule.mobilecommon.widget.antistatic.spinnerwheel;
+
+ /**
+ * Range for visible items.
+ */
+ public class ItemsRange {
+ // First item number
+ private int first;
+
+ // Items count
+ private int count;
+
+ /**
+ * Default constructor. Creates an empty range
+ */
+ public ItemsRange() {
+ this(0, 0);
+ }
+
+ /**
+ * Constructor
+ * @param first the number of first item
+ * @param count the count of items
+ */
+ public ItemsRange(int first, int count) {
+ this.first = first;
+ this.count = count;
+ }
+
+ /**
+ * Gets number of first item
+ * @return the number of the first item
+ */
+ public int getFirst() {
+ return first;
+ }
+
+ /**
+ * Gets number of last item
+ * @return the number of last item
+ */
+ public int getLast() {
+ return getFirst() + getCount() - 1;
+ }
+
+ /**
+ * Get items count
+ * @return the count of items
+ */
+ public int getCount() {
+ return count;
+ }
+
+ /**
+ * Tests whether item is contained by range
+ * @param index the item number
+ * @return true if item is contained
+ */
+ public boolean contains(int index) {
+ return index >= getFirst() && index <= getLast();
+ }
+}
\ No newline at end of file
diff --git a/DeviceAddModule/src/main/java/com/mm/android/deviceaddmodule/mobilecommon/widget/antistatic/spinnerwheel/OnWheelChangedListener.java b/DeviceAddModule/src/main/java/com/mm/android/deviceaddmodule/mobilecommon/widget/antistatic/spinnerwheel/OnWheelChangedListener.java
new file mode 100644
index 0000000..2208d80
--- /dev/null
+++ b/DeviceAddModule/src/main/java/com/mm/android/deviceaddmodule/mobilecommon/widget/antistatic/spinnerwheel/OnWheelChangedListener.java
@@ -0,0 +1,17 @@
+package com.mm.android.deviceaddmodule.mobilecommon.widget.antistatic.spinnerwheel;
+
+/**
+ * Wheel changed listener interface.
+ *