From 301458f6dcaabf12b710196cf5491690ef5857b9 Mon Sep 17 00:00:00 2001 From: wutq Date: Wed, 28 Nov 2018 18:28:34 +0800 Subject: [PATCH 01/23] =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=B4=AD=E7=89=A9?= =?UTF-8?q?=E8=BD=A6=EF=BC=8C=E4=BC=98=E5=8C=96=E7=BD=91=E7=BB=9C=E8=A7=A3?= =?UTF-8?q?=E6=9E=90=E5=8E=BB=E9=99=A4=E5=A4=9A=E4=BD=99=E9=83=A8=E5=88=86?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/wss/common/constants/EventAction.java | 14 ++- .../common/net/callback/OnResultCallBack.java | 49 +++++++++- .../net/callback/OnResultListCallBack.java | 47 --------- .../net/callback/OnResultObjectCallBack.java | 42 -------- .../net/callback/OnResultStringCallBack.java | 38 -------- ...nt.xml => bg_of_green_gradient_radius.xml} | 0 .../res/drawable/bg_of_orange_gradient.xml | 1 - ...t.xml => bg_of_orange_gradient_radius.xml} | 1 + .../main/res/drawable/bg_of_red_gradient.xml | 7 ++ .../main/ui/loading/LoadingActivity.java | 2 +- .../wss/module/main/ui/main/MainActivity.java | 4 +- .../main/ui/main/mvp/MainPresenter.java | 4 +- .../ui/selector/mvp/SelectorPresenter.java | 4 +- .../res/layout/main_activity_flow_layout.xml | 24 ++--- .../src/main/res/layout/main_activity_im.xml | 2 +- .../main/res/layout/main_activity_loading.xml | 2 +- .../main_activity_multifunctional_item.xml | 2 +- .../layout/main_activity_observer_button.xml | 2 +- .../com/wss/module/market/bean/GoodsInfo.java | 4 +- .../ui/goods/cart/ShoppingCartActivity.java | 52 +++++++--- .../cart/adapter/ShoppingCartAdapter.java | 3 +- .../ui/goods/detail/GoodsDetailActivity.java | 92 +++++++++++++++++- .../fragment/GoodsInfoMainFragment.java | 16 +++ .../market/ui/main/MarketMainActivity.java | 10 +- .../ui/main/adapter/MarketMainAdapter.java | 5 +- .../market/utils/ShoppingCartUtils.java | 12 ++- .../market_icon_shopping_cart.png | Bin 1814 -> 5866 bytes .../market_shopping_cart_next_btn.xml | 2 +- .../market_shopping_cart_next_btn_red.xml | 7 ++ .../layout/market_activity_goods_details.xml | 75 +++++++++++++- .../layout/market_activity_shopping_cart.xml | 6 +- .../market_fragment_goods_info_main.xml | 17 +++- module_market/src/main/res/values/strings.xml | 8 +- .../user/ui/account/mvp/LoginPresenter.java | 4 +- .../ui/account/mvp/RegisterPresenter.java | 7 +- .../user/ui/main/mvp/UserPresenter.java | 4 +- .../main/res/layout/user_activity_login.xml | 4 +- .../res/layout/user_activity_register.xml | 2 +- .../com/wss/module/wan/bean/BannerInfo.java | 69 +------------ .../collection/mvp/CollectionPresenter.java | 4 +- .../wan/ui/main/fragment/HomeFragment.java | 4 +- .../module/wan/ui/main/mvp/HomePresenter.java | 65 ++++++------- .../wan/ui/project/mvp/ProjectPresenter.java | 7 +- .../wan/ui/search/mvp/SearchPresenter.java | 4 +- .../ui/setup/mvp/SystemArticlePresenter.java | 4 +- .../wan/ui/setup/mvp/SystemPresenter.java | 4 +- .../ui/wxnumber/mvp/WXArticlePresenter.java | 4 +- .../res/layout/wan_action_bar_of_search.xml | 2 +- .../res/layout/wan_item_of_article_list.xml | 4 +- 49 files changed, 414 insertions(+), 332 deletions(-) delete mode 100644 common_base/src/main/java/com/wss/common/net/callback/OnResultListCallBack.java delete mode 100644 common_base/src/main/java/com/wss/common/net/callback/OnResultObjectCallBack.java delete mode 100644 common_base/src/main/java/com/wss/common/net/callback/OnResultStringCallBack.java rename common_base/src/main/res/drawable/{bg_of_green_gradient.xml => bg_of_green_gradient_radius.xml} (100%) rename common_base/src/main/res/drawable/{bg_of_gradient.xml => bg_of_orange_gradient_radius.xml} (85%) create mode 100644 common_base/src/main/res/drawable/bg_of_red_gradient.xml create mode 100644 module_market/src/main/res/drawable/market_shopping_cart_next_btn_red.xml diff --git a/common_base/src/main/java/com/wss/common/constants/EventAction.java b/common_base/src/main/java/com/wss/common/constants/EventAction.java index 8192797..b6c2fe9 100644 --- a/common_base/src/main/java/com/wss/common/constants/EventAction.java +++ b/common_base/src/main/java/com/wss/common/constants/EventAction.java @@ -7,20 +7,18 @@ public interface EventAction { - /** - * 商城商品被点击 - */ - String EVENT_MARKET_CLICK = "event_market_click"; + //************************************Market模块*****************************************/ /** - * 刷新购物车 + * 购物车有变化 */ - String EVENT_SHOPPING_CART_REFRESH = "event_shopping_cart_refresh"; + String EVENT_SHOPPING_CART_CHANGED = "event_shopping_cart_changed"; /** - * 清空购物车 + * 刷新购物车 重新获取数据 */ - String EVENT_SHOPPING_CART_CLEAN = "event_shopping_cart_clean"; + String EVENT_SHOPPING_CART_REFRESH = "event_shopping_cart_refresh"; + //************************************User模块*****************************************/ /** * 登录成功 */ diff --git a/common_base/src/main/java/com/wss/common/net/callback/OnResultCallBack.java b/common_base/src/main/java/com/wss/common/net/callback/OnResultCallBack.java index 627e4d4..622644a 100644 --- a/common_base/src/main/java/com/wss/common/net/callback/OnResultCallBack.java +++ b/common_base/src/main/java/com/wss/common/net/callback/OnResultCallBack.java @@ -1,22 +1,66 @@ package com.wss.common.net.callback; +import com.alibaba.fastjson.JSON; +import com.google.gson.Gson; +import com.orhanobut.logger.Logger; import com.tamic.novate.Throwable; import com.tamic.novate.callback.RxGenericsCallback; +import com.wss.common.net.NetConfig; + +import org.json.JSONObject; import java.io.IOException; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; import okhttp3.Call; import okhttp3.ResponseBody; /** - * Describe:网络返回基类 + * Describe:网络返回基类 泛型为必传项 默认 传入String即可 * Created by 吴天强 on 2017/9/26. */ - +@SuppressWarnings("unchecked") public abstract class OnResultCallBack extends RxGenericsCallback { protected boolean success; + + @Override + public T onHandleResponse(ResponseBody response) throws Exception { + return transform(new String(response.bytes())); + } + + private T transform(String response) { + Logger.e(JSON.toJSONString(response)); + try { + JSONObject jsonObject = new JSONObject(response); + code = jsonObject.optInt(NetConfig.Code.CODE); + msg = jsonObject.optString(NetConfig.Code.MSG); + success = jsonObject.optBoolean(NetConfig.Code.SUCCESS); + dataStr = jsonObject.opt(NetConfig.Code.MODEL).toString(); + + if (dataStr.charAt(0) == 123) { + //获取泛型类型 + Class classOfT = (Class) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]; + if (classOfT == String.class) { + dataResponse = (T) dataStr; + } else { + //对象 + dataResponse = (new Gson()).fromJson(dataStr, classOfT); + } + } else if (dataStr.charAt(0) == 91) { + //数组 + Type collectionType = ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]; + dataResponse = new Gson().fromJson(dataStr, collectionType); + } + } catch (Exception e) { + e.printStackTrace(); + } + return dataResponse; + + } + @Override public void onError(Object tag, Throwable e) { e.printStackTrace(); @@ -44,6 +88,7 @@ public void onCompleted(Object tag) { onCompleted(); } + public abstract void onSuccess(boolean success, int code, String msg, Object tag, T response); public abstract void onFailure(Object tag, Exception e); diff --git a/common_base/src/main/java/com/wss/common/net/callback/OnResultListCallBack.java b/common_base/src/main/java/com/wss/common/net/callback/OnResultListCallBack.java deleted file mode 100644 index a113abb..0000000 --- a/common_base/src/main/java/com/wss/common/net/callback/OnResultListCallBack.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.wss.common.net.callback; - -import com.alibaba.fastjson.JSON; -import com.google.gson.Gson; -import com.orhanobut.logger.Logger; -import com.wss.common.net.NetConfig; - -import org.json.JSONObject; - -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; - -import okhttp3.ResponseBody; - -/** - * Describe:返回数组类型数据 - * Created by 吴天强 on 2017/9/28. - */ - -public abstract class OnResultListCallBack extends OnResultCallBack { - - private Type collectionType; - - @Override - public T onHandleResponse(ResponseBody response) throws Exception { - if (collectionType == null) { - collectionType = ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]; - } - return transform(new String(response.bytes()), null); - } - - public T transform(String response, final Class classOfT) throws ClassCastException { - Logger.e(JSON.toJSONString(response)); - try { - JSONObject jsonObject = new JSONObject(response); - code = jsonObject.optInt(NetConfig.Code.CODE); - msg = jsonObject.optString(NetConfig.Code.MSG); - success = jsonObject.optBoolean(NetConfig.Code.SUCCESS); - dataStr = jsonObject.opt(NetConfig.Code.MODEL).toString(); - dataResponse = new Gson().fromJson(dataStr, collectionType); - } catch (Exception e) { - e.printStackTrace(); - } - - return dataResponse; - } -} \ No newline at end of file diff --git a/common_base/src/main/java/com/wss/common/net/callback/OnResultObjectCallBack.java b/common_base/src/main/java/com/wss/common/net/callback/OnResultObjectCallBack.java deleted file mode 100644 index 151c250..0000000 --- a/common_base/src/main/java/com/wss/common/net/callback/OnResultObjectCallBack.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.wss.common.net.callback; - -import com.google.gson.Gson; -import com.orhanobut.logger.Logger; -import com.wss.common.net.NetConfig; - -import org.json.JSONObject; - -import java.lang.reflect.ParameterizedType; - -import okhttp3.ResponseBody; - -/** - * Describe:返回对象类型数据 - * Created by 吴天强 on 2017/9/28. - */ - -public abstract class OnResultObjectCallBack extends OnResultCallBack { - - @Override - public T onHandleResponse(ResponseBody response) throws Exception { - Class entityClass = (Class) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]; - return transform(new String(response.bytes()), entityClass); - } - - public T transform(String response, final Class classOfT) throws ClassCastException { - Logger.e(response); - try { - JSONObject jsonObject = new JSONObject(response); - - code = jsonObject.optInt(NetConfig.Code.CODE); - msg = jsonObject.optString(NetConfig.Code.MSG); - success = jsonObject.optBoolean(NetConfig.Code.SUCCESS); - dataStr = jsonObject.opt(NetConfig.Code.MODEL).toString(); - dataResponse = (T) new Gson().fromJson(dataStr, classOfT); - } catch (Exception e) { - e.printStackTrace(); - } - return dataResponse; - } -} - diff --git a/common_base/src/main/java/com/wss/common/net/callback/OnResultStringCallBack.java b/common_base/src/main/java/com/wss/common/net/callback/OnResultStringCallBack.java deleted file mode 100644 index eec4ce6..0000000 --- a/common_base/src/main/java/com/wss/common/net/callback/OnResultStringCallBack.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.wss.common.net.callback; - -import com.alibaba.fastjson.JSON; -import com.orhanobut.logger.Logger; -import com.wss.common.net.NetConfig; - -import org.json.JSONObject; - -import okhttp3.ResponseBody; - -/** - * Describe:String类型数据解析 - * Created by 吴天强 on 2017/9/28. - */ - -public abstract class OnResultStringCallBack extends OnResultCallBack { - - @Override - public String onHandleResponse(ResponseBody response) throws Exception { - return transform(new String(response.bytes())); - } - - private String transform(String response) { - Logger.e(JSON.toJSONString(response)); - try { - JSONObject jsonObject = new JSONObject(response); - code = jsonObject.optInt(NetConfig.Code.CODE); - msg = jsonObject.optString(NetConfig.Code.MSG); - success = jsonObject.optBoolean(NetConfig.Code.SUCCESS); - dataStr = jsonObject.opt(NetConfig.Code.MODEL).toString(); - dataResponse = dataStr; - } catch (Exception e) { - e.printStackTrace(); - } - return dataResponse; - } - -} diff --git a/common_base/src/main/res/drawable/bg_of_green_gradient.xml b/common_base/src/main/res/drawable/bg_of_green_gradient_radius.xml similarity index 100% rename from common_base/src/main/res/drawable/bg_of_green_gradient.xml rename to common_base/src/main/res/drawable/bg_of_green_gradient_radius.xml diff --git a/common_base/src/main/res/drawable/bg_of_orange_gradient.xml b/common_base/src/main/res/drawable/bg_of_orange_gradient.xml index 26a204d..8cc2733 100644 --- a/common_base/src/main/res/drawable/bg_of_orange_gradient.xml +++ b/common_base/src/main/res/drawable/bg_of_orange_gradient.xml @@ -4,5 +4,4 @@ android:endColor="#FF8000" android:startColor="#FFA82E" android:type="linear" /> - \ No newline at end of file diff --git a/common_base/src/main/res/drawable/bg_of_gradient.xml b/common_base/src/main/res/drawable/bg_of_orange_gradient_radius.xml similarity index 85% rename from common_base/src/main/res/drawable/bg_of_gradient.xml rename to common_base/src/main/res/drawable/bg_of_orange_gradient_radius.xml index 8cc2733..26a204d 100644 --- a/common_base/src/main/res/drawable/bg_of_gradient.xml +++ b/common_base/src/main/res/drawable/bg_of_orange_gradient_radius.xml @@ -4,4 +4,5 @@ android:endColor="#FF8000" android:startColor="#FFA82E" android:type="linear" /> + \ No newline at end of file diff --git a/common_base/src/main/res/drawable/bg_of_red_gradient.xml b/common_base/src/main/res/drawable/bg_of_red_gradient.xml new file mode 100644 index 0000000..43fdb81 --- /dev/null +++ b/common_base/src/main/res/drawable/bg_of_red_gradient.xml @@ -0,0 +1,7 @@ + + + \ No newline at end of file diff --git a/module_main/src/main/java/com/wss/module/main/ui/loading/LoadingActivity.java b/module_main/src/main/java/com/wss/module/main/ui/loading/LoadingActivity.java index 12e500e..2b3e9e1 100644 --- a/module_main/src/main/java/com/wss/module/main/ui/loading/LoadingActivity.java +++ b/module_main/src/main/java/com/wss/module/main/ui/loading/LoadingActivity.java @@ -19,7 +19,7 @@ public class LoadingActivity extends BaseActivity { - private long loadingTime = 500; + private long loadingTime = 1500; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { diff --git a/module_main/src/main/java/com/wss/module/main/ui/main/MainActivity.java b/module_main/src/main/java/com/wss/module/main/ui/main/MainActivity.java index 436f52f..d16b3a0 100644 --- a/module_main/src/main/java/com/wss/module/main/ui/main/MainActivity.java +++ b/module_main/src/main/java/com/wss/module/main/ui/main/MainActivity.java @@ -23,8 +23,8 @@ import com.wss.module.main.R; import com.wss.module.main.R2; import com.wss.module.main.ui.main.fragment.CenterFragment; -import com.wss.module.main.ui.main.mvp.contract.MainContract; import com.wss.module.main.ui.main.mvp.MainPresenter; +import com.wss.module.main.ui.main.mvp.contract.MainContract; import java.util.ArrayList; import java.util.List; @@ -85,7 +85,7 @@ public void onCheckedChanged(RadioGroup group, @IdRes int checkedId) { } }); //检查文件权限 if (PermissionsUtils.checkPermissions(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) { - presenter.checkUpdate(); +// presenter.checkUpdate(); } presenter.getTabList(); } diff --git a/module_main/src/main/java/com/wss/module/main/ui/main/mvp/MainPresenter.java b/module_main/src/main/java/com/wss/module/main/ui/main/mvp/MainPresenter.java index 5c73fe5..bb0607b 100644 --- a/module_main/src/main/java/com/wss/module/main/ui/main/mvp/MainPresenter.java +++ b/module_main/src/main/java/com/wss/module/main/ui/main/mvp/MainPresenter.java @@ -5,7 +5,7 @@ import com.wss.common.bean.AppInfo; import com.wss.common.bean.Template; import com.wss.common.constants.ARouterConfig; -import com.wss.common.net.callback.OnResultObjectCallBack; +import com.wss.common.net.callback.OnResultCallBack; import com.wss.module.main.R; import com.wss.module.main.ui.hortab.OrderListActivity; import com.wss.module.main.ui.im.IMActivity; @@ -43,7 +43,7 @@ public void start() { @Override public void checkUpdate() { if (isViewAttached()) { - getModule().checkUpdate(new OnResultObjectCallBack() { + getModule().checkUpdate(new OnResultCallBack() { @Override public void onSuccess(boolean success, int code, String msg, Object tag, AppInfo response) { if (code == 1000 || response != null) { diff --git a/module_main/src/main/java/com/wss/module/main/ui/selector/mvp/SelectorPresenter.java b/module_main/src/main/java/com/wss/module/main/ui/selector/mvp/SelectorPresenter.java index 3c16d15..1cf7798 100644 --- a/module_main/src/main/java/com/wss/module/main/ui/selector/mvp/SelectorPresenter.java +++ b/module_main/src/main/java/com/wss/module/main/ui/selector/mvp/SelectorPresenter.java @@ -3,7 +3,7 @@ import com.alibaba.fastjson.JSON; import com.wss.common.base.mvp.BasePresenter; import com.wss.common.constants.Constants; -import com.wss.common.net.callback.OnResultStringCallBack; +import com.wss.common.net.callback.OnResultCallBack; import com.wss.module.main.bean.Province; import com.wss.module.main.ui.selector.mvp.contract.SelectContract; @@ -22,7 +22,7 @@ public class SelectorPresenter extends BasePresenter() { @Override public void onSuccess(boolean success, int code, String msg, Object tag, String response) { List provinceList = JSON.parseArray(response, Province.class); diff --git a/module_main/src/main/res/layout/main_activity_flow_layout.xml b/module_main/src/main/res/layout/main_activity_flow_layout.xml index 6b8a256..c9a1f29 100644 --- a/module_main/src/main/res/layout/main_activity_flow_layout.xml +++ b/module_main/src/main/res/layout/main_activity_flow_layout.xml @@ -9,7 +9,7 @@ android:layout_height="wrap_content" android:layout_marginEnd="10dp" android:layout_marginTop="10dp" - android:background="@drawable/bg_of_orange_gradient" + android:background="@drawable/bg_of_orange_gradient_radius" android:padding="4dp" android:text="哇哈哈哈哈" android:textColor="@color/white" @@ -20,7 +20,7 @@ android:layout_height="wrap_content" android:layout_marginEnd="10dp" android:layout_marginTop="10dp" - android:background="@drawable/bg_of_green_gradient" + android:background="@drawable/bg_of_green_gradient_radius" android:padding="4dp" android:text="x" android:textColor="@color/white" @@ -32,7 +32,7 @@ android:layout_height="wrap_content" android:layout_marginEnd="10dp" android:layout_marginTop="10dp" - android:background="@drawable/bg_of_orange_gradient" + android:background="@drawable/bg_of_orange_gradient_radius" android:padding="4dp" android:text="新疆维吾尔自治区" android:textColor="@color/white" @@ -43,7 +43,7 @@ android:layout_height="wrap_content" android:layout_marginEnd="10dp" android:layout_marginTop="10dp" - android:background="@drawable/bg_of_green_gradient" + android:background="@drawable/bg_of_green_gradient_radius" android:padding="4dp" android:text="长河落日圆" android:textColor="@color/white" @@ -55,7 +55,7 @@ android:layout_height="wrap_content" android:layout_marginEnd="10dp" android:layout_marginTop="10dp" - android:background="@drawable/bg_of_orange_gradient" + android:background="@drawable/bg_of_orange_gradient_radius" android:padding="4dp" android:text="哦。是吗" android:textColor="@color/white" @@ -66,7 +66,7 @@ android:layout_height="wrap_content" android:layout_marginEnd="10dp" android:layout_marginTop="10dp" - android:background="@drawable/bg_of_green_gradient" + android:background="@drawable/bg_of_green_gradient_radius" android:padding="4dp" android:text="像水一样流动" android:textColor="@color/white" @@ -77,7 +77,7 @@ android:layout_height="wrap_content" android:layout_marginEnd="10dp" android:layout_marginTop="10dp" - android:background="@drawable/bg_of_orange_gradient" + android:background="@drawable/bg_of_orange_gradient_radius" android:padding="4dp" android:text="1233333333" android:textColor="@color/white" @@ -88,7 +88,7 @@ android:layout_height="wrap_content" android:layout_marginEnd="10dp" android:layout_marginTop="10dp" - android:background="@drawable/bg_of_green_gradient" + android:background="@drawable/bg_of_green_gradient_radius" android:padding="4dp" android:text="必须先吃是程序下啊啊大厦实打实" android:textColor="@color/white" @@ -99,7 +99,7 @@ android:layout_height="wrap_content" android:layout_marginEnd="10dp" android:layout_marginTop="10dp" - android:background="@drawable/bg_of_green_gradient" + android:background="@drawable/bg_of_green_gradient_radius" android:padding="4dp" android:text="必须先吃是程序下啊大厦打" android:textColor="@color/white" @@ -110,7 +110,7 @@ android:layout_height="wrap_content" android:layout_marginEnd="10dp" android:layout_marginTop="10dp" - android:background="@drawable/bg_of_orange_gradient" + android:background="@drawable/bg_of_orange_gradient_radius" android:padding="4dp" android:text="1233333333" android:textColor="@color/white" @@ -121,7 +121,7 @@ android:layout_height="wrap_content" android:layout_marginEnd="10dp" android:layout_marginTop="10dp" - android:background="@drawable/bg_of_orange_gradient" + android:background="@drawable/bg_of_orange_gradient_radius" android:padding="4dp" android:text="我鲁科" android:textColor="@color/white" @@ -132,7 +132,7 @@ android:layout_height="wrap_content" android:layout_marginEnd="10dp" android:layout_marginTop="10dp" - android:background="@drawable/bg_of_green_gradient" + android:background="@drawable/bg_of_green_gradient_radius" android:padding="4dp" android:text="必须先吃是程序下啊啊大厦实打实" android:textColor="@color/white" diff --git a/module_main/src/main/res/layout/main_activity_im.xml b/module_main/src/main/res/layout/main_activity_im.xml index 0f1d30a..6dcbcbf 100644 --- a/module_main/src/main/res/layout/main_activity_im.xml +++ b/module_main/src/main/res/layout/main_activity_im.xml @@ -51,7 +51,7 @@ android:text="发送" android:textColor="@color/black" app:defaultBgResource="@drawable/corner_gray_shape" - app:pressBgResource="@drawable/bg_of_orange_gradient" /> + app:pressBgResource="@drawable/bg_of_orange_gradient_radius" /> diff --git a/module_main/src/main/res/layout/main_activity_loading.xml b/module_main/src/main/res/layout/main_activity_loading.xml index ae0502e..627936c 100644 --- a/module_main/src/main/res/layout/main_activity_loading.xml +++ b/module_main/src/main/res/layout/main_activity_loading.xml @@ -2,7 +2,7 @@ + android:background="@drawable/bg_of_orange_gradient_radius"> diff --git a/module_main/src/main/res/layout/main_activity_multifunctional_item.xml b/module_main/src/main/res/layout/main_activity_multifunctional_item.xml index 0b99a99..55cce1f 100644 --- a/module_main/src/main/res/layout/main_activity_multifunctional_item.xml +++ b/module_main/src/main/res/layout/main_activity_multifunctional_item.xml @@ -21,7 +21,7 @@ android:layout_width="match_parent" android:layout_height="50dp" android:layout_marginTop="10dp" - android:background="@drawable/bg_of_gradient" + android:background="@drawable/bg_of_orange_gradient" app:leftText="我的订单" app:leftTextColor="@color/red" app:showLeftIcon="false" /> diff --git a/module_main/src/main/res/layout/main_activity_observer_button.xml b/module_main/src/main/res/layout/main_activity_observer_button.xml index 167cf17..757d80e 100644 --- a/module_main/src/main/res/layout/main_activity_observer_button.xml +++ b/module_main/src/main/res/layout/main_activity_observer_button.xml @@ -68,6 +68,6 @@ android:text="注册" android:textColor="@color/black" app:defaultBgResource="@drawable/corner_gray_shape" - app:pressBgResource="@drawable/bg_of_orange_gradient" /> + app:pressBgResource="@drawable/bg_of_orange_gradient_radius" /> diff --git a/module_market/src/main/java/com/wss/module/market/bean/GoodsInfo.java b/module_market/src/main/java/com/wss/module/market/bean/GoodsInfo.java index 8690c91..fa59b3e 100644 --- a/module_market/src/main/java/com/wss/module/market/bean/GoodsInfo.java +++ b/module_market/src/main/java/com/wss/module/market/bean/GoodsInfo.java @@ -26,8 +26,8 @@ public class GoodsInfo extends BaseBean { private String praiseRate;//好评率 private String commentCount;//用户点评数 private int num;//数量 - @Transient - private boolean checked;// + @Transient//该字段不入库 + private boolean checked;//是否选择 @Transient//该字段不入库 private List goodsHeadImg;//商品头图 private String vendorId;//供应商ID diff --git a/module_market/src/main/java/com/wss/module/market/ui/goods/cart/ShoppingCartActivity.java b/module_market/src/main/java/com/wss/module/market/ui/goods/cart/ShoppingCartActivity.java index afddbf7..5f3af53 100644 --- a/module_market/src/main/java/com/wss/module/market/ui/goods/cart/ShoppingCartActivity.java +++ b/module_market/src/main/java/com/wss/module/market/ui/goods/cart/ShoppingCartActivity.java @@ -14,6 +14,7 @@ import com.wss.common.utils.ToastUtils; import com.wss.module.market.R; import com.wss.module.market.R2; +import com.wss.module.market.bean.GoodsInfo; import com.wss.module.market.bean.Vendor; import com.wss.module.market.ui.goods.cart.adapter.ShoppingCartAdapter; import com.wss.module.market.ui.goods.cart.mvp.CartPresenter; @@ -44,6 +45,9 @@ public class ShoppingCartActivity extends ActionBarActivity imple @BindView(R2.id.btn_buy) TextView btnBuy; + private TextView tvRight;//右上角文字 + private boolean isEdit;//是否属于编辑状态 + @Override protected CartPresenter createPresenter() { return new CartPresenter(); @@ -55,7 +59,6 @@ protected CartPresenter createPresenter() { @Override protected int getLayoutId() { - return R.layout.market_activity_shopping_cart; } @@ -65,15 +68,36 @@ protected void initView() { adapter = new ShoppingCartAdapter(mContext, mData, R.layout.market_item_of_shopping_cart_list, this); recycleView.setLayoutManager(new LinearLayoutManager(mContext)); recycleView.setAdapter(adapter); - actionBar.setRightText("清空", new View.OnClickListener() { + tvRight = actionBar.getTextView(); + tvRight.setText("编辑"); + tvRight.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - ShoppingCartUtils.cleanLocal(); + onRightChange(); } }); + actionBar.setRightView(tvRight); presenter.start(); } + + private void onRightChange() { + isEdit = !isEdit; + if (isEdit) { + tvRight.setText("完成"); + tvTotal.setVisibility(View.GONE); + btnBuy.setText("删除"); + btnBuy.setBackgroundResource(R.drawable.market_shopping_cart_next_btn_red); + } else { + tvTotal.setVisibility(View.VISIBLE); + tvRight.setText("编辑"); + btnBuy.setText("下一步"); + btnBuy.setBackgroundResource(R.drawable.market_shopping_cart_next_btn); + } + adapter.setEdit(isEdit); + } + + @Override protected boolean regEvent() { return true; @@ -82,19 +106,20 @@ protected boolean regEvent() { @Override public void onEventBus(Event event) { super.onEventBus(event); - if (TextUtils.equals(EventAction.EVENT_SHOPPING_CART_REFRESH, event.getAction())) { + if (TextUtils.equals(EventAction.EVENT_SHOPPING_CART_CHANGED, event.getAction())) { //购物车有变化 adapter.notifyDataSetChanged(); ivCheckAll.setSelected(ShoppingCartUtils.isAllVendorChecked(mData)); displayResult(); - } else if (TextUtils.equals(EventAction.EVENT_SHOPPING_CART_CLEAN, event.getAction())) { - showEmptyView("车里空空如也"); + } else if (TextUtils.equals(EventAction.EVENT_SHOPPING_CART_REFRESH, event.getAction())) { + //重新获取购物车数据 + presenter.getCartData(); } } private void displayResult() { btnBuy.setSelected(ShoppingCartUtils.isCheckedLeastOne(mData)); - tvTotal.setText(String.format("%s%s", getString(R.string.total), ShoppingCartUtils.getCartCountPrice(mData))); + tvTotal.setText(String.format("%s%s", getString(R.string.market_total), ShoppingCartUtils.getCartCountPrice(mData))); } @@ -103,9 +128,6 @@ public void cartData(List dataList) { this.mData.clear(); this.mData.addAll(dataList); adapter.notifyDataSetChanged(); - //默认全部选中 - ShoppingCartUtils.checkAll(mData, true); - ivCheckAll.setSelected(true); displayResult(); } @@ -120,7 +142,15 @@ public void onViewClicked(View view) { adapter.notifyDataSetChanged(); displayResult(); } else if (i == R.id.btn_buy) { - ToastUtils.showToast(mContext, "可点击"); + List checkedGoods = ShoppingCartUtils.getAllCheckedGoods(mData); + if (checkedGoods.size() > 0) { + if (isEdit) { + //删除 + ShoppingCartUtils.delete(checkedGoods); + } else { + ToastUtils.showToast(mContext, "去结算"); + } + } } } diff --git a/module_market/src/main/java/com/wss/module/market/ui/goods/cart/adapter/ShoppingCartAdapter.java b/module_market/src/main/java/com/wss/module/market/ui/goods/cart/adapter/ShoppingCartAdapter.java index 80177c1..11febbd 100644 --- a/module_market/src/main/java/com/wss/module/market/ui/goods/cart/adapter/ShoppingCartAdapter.java +++ b/module_market/src/main/java/com/wss/module/market/ui/goods/cart/adapter/ShoppingCartAdapter.java @@ -38,6 +38,7 @@ public class ShoppingCartAdapter extends BaseListAdapter implements OnCl public void setEdit(boolean edit) { isEdit = edit; + notifyDataSetChanged(); } public ShoppingCartAdapter(Context context, List items, int layoutResId, OnListItemClickListener listener) { @@ -138,6 +139,6 @@ public void onMin() { private void updateCart() { //刷新购物车 - EventBusUtils.sendEvent(new Event(EventAction.EVENT_SHOPPING_CART_REFRESH)); + EventBusUtils.sendEvent(new Event(EventAction.EVENT_SHOPPING_CART_CHANGED)); } } diff --git a/module_market/src/main/java/com/wss/module/market/ui/goods/detail/GoodsDetailActivity.java b/module_market/src/main/java/com/wss/module/market/ui/goods/detail/GoodsDetailActivity.java index 1c62503..5d816eb 100644 --- a/module_market/src/main/java/com/wss/module/market/ui/goods/detail/GoodsDetailActivity.java +++ b/module_market/src/main/java/com/wss/module/market/ui/goods/detail/GoodsDetailActivity.java @@ -1,19 +1,28 @@ package com.wss.module.market.ui.goods.detail; +import android.text.TextUtils; import android.view.View; import android.widget.TextView; import com.wss.common.adapter.FragmentPagerAdapter; import com.wss.common.base.BaseActivity; import com.wss.common.base.BaseFragment; +import com.wss.common.bean.Event; import com.wss.common.bean.HorizontalTabTitle; +import com.wss.common.constants.EventAction; +import com.wss.common.utils.ActivityToActivity; +import com.wss.common.utils.EventBusUtils; +import com.wss.common.utils.ToastUtils; import com.wss.common.widget.NoScrollViewPager; import com.wss.common.widget.PagerSlidingTabStrip; import com.wss.module.market.R; import com.wss.module.market.R2; +import com.wss.module.market.bean.GoodsInfo; +import com.wss.module.market.ui.goods.cart.ShoppingCartActivity; import com.wss.module.market.ui.goods.detail.fragment.GoodsInfoDetailMainFragment; import com.wss.module.market.ui.goods.detail.fragment.GoodsInfoMainFragment; import com.wss.module.market.ui.goods.detail.fragment.child.GoodsCommentFragment; +import com.wss.module.market.utils.ShoppingCartUtils; import java.util.ArrayList; import java.util.List; @@ -36,6 +45,14 @@ public class GoodsDetailActivity extends BaseActivity { @BindView(R2.id.vp_content) public NoScrollViewPager vpContent; + @BindView(R2.id.tv_count) + TextView tvCount;//购物车数量 + + //TODO 测试使用列表造的伪数据表示不同商品做加入购物车操作 + private GoodsInfo goodsInfo; + + private GoodsInfoMainFragment goodsInfoMainFragment; + @Override protected int getLayoutId() { return R.layout.market_activity_goods_details; @@ -43,6 +60,10 @@ protected int getLayoutId() { @Override protected void initView() { + if (getIntent() != null) { + goodsInfo = (GoodsInfo) getIntent().getSerializableExtra("GoodsInfo"); + } + List title = new ArrayList<>(); title.add(new HorizontalTabTitle("商品")); title.add(new HorizontalTabTitle("详情")); @@ -50,19 +71,19 @@ protected void initView() { List fragmentList = new ArrayList<>(); - fragmentList.add(new GoodsInfoMainFragment()); + fragmentList.add(goodsInfoMainFragment = new GoodsInfoMainFragment()); fragmentList.add(new GoodsInfoDetailMainFragment()); fragmentList.add(new GoodsCommentFragment()); vpContent.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager(), title, fragmentList)); vpContent.setOffscreenPageLimit(3); pstsTabs.setViewPager(vpContent); - } - @OnClick(R2.id.ll_back) - public void onClick(View v) { - finish(); + setCartNumber(); } + /** + * 设置内容 + */ public void setViewContent(boolean scrollToBottom) { if (scrollToBottom) { // 图文详情 @@ -77,7 +98,68 @@ public void setViewContent(boolean scrollToBottom) { } } + @Override + protected boolean regEvent() { + return true; + } + + @Override + public void onEventBus(Event event) { + super.onEventBus(event); + if (TextUtils.equals(EventAction.EVENT_SHOPPING_CART_REFRESH, event.getAction())) { + setCartNumber(); + } + } + + @Override + protected void onResume() { + super.onResume(); + setCartNumber(); + } + + @OnClick({R2.id.ll_back, R2.id.rl_cart, R2.id.tv_add_cart, R2.id.tv_buy_now}) + public void onViewClicked(View view) { + int i = view.getId(); + if (i == R.id.ll_back) { + finish(); + } else if (i == R.id.rl_cart) { + //去购物车 + ActivityToActivity.toActivity(mContext, ShoppingCartActivity.class); + } else if (i == R.id.tv_add_cart) { + //加入购物车 + if (goodsInfo != null) { + goodsInfo.setNum(goodsInfoMainFragment.getGoodsCount()); + ShoppingCartUtils.addCartGoods(goodsInfo); + EventBusUtils.sendEvent(new Event(EventAction.EVENT_SHOPPING_CART_REFRESH)); + }else { + ToastUtils.showToast(mContext,"没有正经的商品信息~"); + } + } else if (i == R.id.tv_buy_now) { + //立即购买 + ToastUtils.showToast(mContext, "立即购买"); + } + } + + /** + * 设置购物车数量 + */ + private void setCartNumber() { + int count = ShoppingCartUtils.getCartCount(); + if (count < 1) { + tvCount.setVisibility(View.GONE); + } else { + tvCount.setVisibility(View.VISIBLE); + tvCount.setText(String.valueOf(count)); + } + } + + /** + * 切换Fragment + * + * @param position position + */ public void setCurrentFragment(int position) { vpContent.setCurrentItem(position); } + } diff --git a/module_market/src/main/java/com/wss/module/market/ui/goods/detail/fragment/GoodsInfoMainFragment.java b/module_market/src/main/java/com/wss/module/market/ui/goods/detail/fragment/GoodsInfoMainFragment.java index bdc634b..3210eff 100644 --- a/module_market/src/main/java/com/wss/module/market/ui/goods/detail/fragment/GoodsInfoMainFragment.java +++ b/module_market/src/main/java/com/wss/module/market/ui/goods/detail/fragment/GoodsInfoMainFragment.java @@ -13,6 +13,7 @@ import com.bigkoo.convenientbanner.ConvenientBanner; import com.wss.common.adapter.BannerImgAdapter; import com.wss.common.base.BaseMvpFragment; +import com.wss.common.widget.CountClickView; import com.wss.common.widget.SlideLayout; import com.wss.module.market.R; import com.wss.module.market.R2; @@ -66,6 +67,9 @@ public class GoodsInfoMainFragment extends BaseMvpFragment @BindView(R2.id.sv_switch) SlideLayout svSwitch; + @BindView(R2.id.ccv_click) + CountClickView ccvClick;//商品数量加减控件 + /** * 当前商品详情数据页的索引分别是图文详情、规格参数 @@ -86,6 +90,9 @@ protected int getLayoutId() { @Override protected void initView() { + + ccvClick.setMinCount(1); + ccvClick.setCurrCount(1); svSwitch.setOnSlideDetailsListener(this); //设置文字中间一条横线 tvOldPrice.getPaint().setFlags(Paint.STRIKE_THRU_TEXT_FLAG); @@ -182,4 +189,13 @@ public void commentList(List commentList) { protected GoodsDetailPresenter createPresenter() { return new GoodsDetailPresenter(); } + + /** + * 得到当前商品增减数量 + * + * @return int + */ + public int getGoodsCount() { + return ccvClick.getCount(); + } } diff --git a/module_market/src/main/java/com/wss/module/market/ui/main/MarketMainActivity.java b/module_market/src/main/java/com/wss/module/market/ui/main/MarketMainActivity.java index 2fc502f..103e8af 100644 --- a/module_market/src/main/java/com/wss/module/market/ui/main/MarketMainActivity.java +++ b/module_market/src/main/java/com/wss/module/market/ui/main/MarketMainActivity.java @@ -23,7 +23,9 @@ import com.wss.module.market.ui.main.mvp.MarketMainPresenter; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import butterknife.BindView; @@ -97,14 +99,16 @@ public void cartCount(long count) { @Override public void onItemClick(View view, int position) { - ActivityToActivity.toActivity(mContext, GoodsDetailActivity.class); + Map param = new HashMap<>(); + param.put("GoodsInfo", marketInfoList.get(position)); + ActivityToActivity.toActivity(mContext, GoodsDetailActivity.class, param); } @Override public void onEventBus(Event event) { super.onEventBus(event); - if (TextUtils.equals(EventAction.EVENT_SHOPPING_CART_REFRESH, event.getAction()) || - TextUtils.equals(EventAction.EVENT_SHOPPING_CART_CLEAN, event.getAction())) { + if (TextUtils.equals(EventAction.EVENT_SHOPPING_CART_CHANGED, event.getAction()) || + TextUtils.equals(EventAction.EVENT_SHOPPING_CART_REFRESH, event.getAction())) { //刷新购物车 presenter.getCartCount(); } diff --git a/module_market/src/main/java/com/wss/module/market/ui/main/adapter/MarketMainAdapter.java b/module_market/src/main/java/com/wss/module/market/ui/main/adapter/MarketMainAdapter.java index 5fce483..cf1431c 100644 --- a/module_market/src/main/java/com/wss/module/market/ui/main/adapter/MarketMainAdapter.java +++ b/module_market/src/main/java/com/wss/module/market/ui/main/adapter/MarketMainAdapter.java @@ -38,15 +38,16 @@ public void onBindData(SuperViewHolder holder, int viewType, int layoutPosition, holder.setText(R.id.tv_price, data.getGoodsPrice()); TextView tvOldPrice = holder.findViewById(R.id.tv_old_price); tvOldPrice.setText(data.getGoodsOldPrice()); - //设置文字中间一条横线, + final GoodsInfo goodsInfo = data; + //设置文字中间一条横线, tvOldPrice.getPaint().setFlags(Paint.STRIKE_THRU_TEXT_FLAG); holder.findViewById(R.id.iv_add_cart).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //加入购物车 ShoppingCartUtils.addCartGoods(goodsInfo); - EventBusUtils.sendEvent(new Event(EventAction.EVENT_SHOPPING_CART_REFRESH)); + EventBusUtils.sendEvent(new Event(EventAction.EVENT_SHOPPING_CART_CHANGED)); } }); } diff --git a/module_market/src/main/java/com/wss/module/market/utils/ShoppingCartUtils.java b/module_market/src/main/java/com/wss/module/market/utils/ShoppingCartUtils.java index f9e96c1..6277bf8 100644 --- a/module_market/src/main/java/com/wss/module/market/utils/ShoppingCartUtils.java +++ b/module_market/src/main/java/com/wss/module/market/utils/ShoppingCartUtils.java @@ -121,12 +121,16 @@ public static double getCartCountPrice(List vendors) { return price; } - public static void cleanLocal() { - + /** + * 删除购物车数据 + * + * @param goodsList goodsList + */ + public static void delete(List goodsList) { MarketDBFactory.getInstance() .getGoodsInfoManage() - .deleteAll(); - EventBusUtils.sendEvent(new Event(EventAction.EVENT_SHOPPING_CART_CLEAN)); + .delete(goodsList); + EventBusUtils.sendEvent(new Event(EventAction.EVENT_SHOPPING_CART_REFRESH)); } //**********************************购物车点击逻辑操作******************************************* diff --git a/module_market/src/main/res/drawable-xxhdpi/market_icon_shopping_cart.png b/module_market/src/main/res/drawable-xxhdpi/market_icon_shopping_cart.png index c9bdb3c9c3034a21cdff24b2aa79cce7741882d1..96addd3bb52ae7e405080b90e6bbf32142342697 100644 GIT binary patch literal 5866 zcmeHL`8yQQ*B?u^j5XV6m|+TKH^@E=8Ea)rQ@y0Pq(Sy=Bq?PgONl{g ztb>HIWXWzwLgLl?{tMsV-tT#yd(XY+x#!%^J@<3Z5BKh6Yf~T>hzkG!0L@UwHUI$g z@sJt7!E&sqWZ1`J#S&sJro0iz4F#|LC0|bmo4o~j*gCw*Z)`kn}PqI88|83FmrtJ zqfi@bTL2R?3+o9sb`DOiliWZaUOs*S!BaxQBBEj-@zY=lNeEO*8g}NajI7+b^YRLc zO3Es#YH)Q8%?n!EI=XuL1_(nVq_N3GQrU%%nx?Ba^K z>E`a?>4n94`}q3#2LuKMhlJh=3y-)R85JFKCpIoVAu%Z#Pe{3YFEuUweg^SD=EJN< zr0ksB$9ee$g+;|BrDf$6Lz>b$!E|#-`?$x9?itx3yC{I=eo6 z?EXaS>Fw(u7^Dvkk9;2eGB!T(_1oms^vw6!x%q`3i%ZKZt842UjLof|+rM^x@9ypY zIrw|H!ZD@}00>+$Gd8pn6`_cQ`7sB-8z-=d z3OOrv(HKec^;mNty$Zk)q3NeQ#O|RgV)QDtX@B0TjTXFY>EDQ*oS)l?E!_CQ!vCL> zy^3LjXa-H`Yv?EcWFp{Jp>yYkpJ)_{S%8!P6*_pJ^c>5^iTd+dqB+Z0YM>cvvJEEel(kXKbJAAD|cREl3I|}#+UjqlPkpeJuQab~ebH_g>rD)w9 z{n_A+Qio}Ps#BekVtj;`+)zW%DwH$Dg{&g&a$}JD`$PVo%bgu=KcSPm3Th3mD4!G= zw5qth(r@{sh#8=#S9k9kR03Ofe=M>tKn1qb=dt6EzRGd8IXfqH>Bnb62bwzA)4k9B zJGory)?50)qbiM*Z zR7Nqos-6L!DzNo?k*$y2>-`fWihF-esp?duL-jvy>{yRy!LG#||AcKk9Lae2c@xhHkA=rXH-Q1nMfPS7lq06@6vs)H;0(cZR5y2K9 zpc^cy5cPh^hAlu@H<&{~lUj8?F~x6A<4nB5xyi ze+Zzhk;Mx`3{~CXmV5Xg{A4|>mWcjiBjjyqR-7!*-fFrmp*5t4;ZuU@2vCRM5{Bu-avQdZ-pxyvh9qDKly z)qMF?@M!LU5wsQcbP^dS1RSNhxM9bD@md)qYsTmU%GZ?lEk@L<497zO&^u#C5NRmz zd~}$M!XJoi3{DH6uM&G-Q zMMzX)JfOP2#enBe@~4%m!*#i*oRG9ljxH5SKF8FWF>RKk>o5G768^X6KdMx3ZWk!k2Iot0lPP z4KLK+2OHH|odLd(vXY55m9*Em$mdKhc_l}G@TTa_{`vNS3=$K{G&XYiHwX2YR=eW# z+P~WSa${Wa5s&fiK6d9-k_#hwOLi3$vdhpigIBYqPj#+fbMAV7L%O_1Doa#Uusr=4 z9_g*o9&}m(c{#n*YI~S3=^wp{%0N+rSHb+mDBPIf;Qivt1u2*lPV7E5eX%N!KeHtn zE{}qYXKxR^psSuKlH#=mA9 ziM`FlTz67|w+xg)Hz?!J&%ip`iVxNwKAzN)XcIHG;I%7rm)EPS7fu+$lVmQ}6k04j z3gQ@mgEWRsUq8O_x5sF|Op`fOMIq(^Y2n*`Cv6J*7sna9mDuTsnDv zlwpwy119p%lvVa3_|x*4v#e_Xv_IieUwMUE z0%`X#zH^W9@h3d`A>s>uFj(~9N~|=nK{~K`XbW%gm99a=$5uUaTHlk;gHx&`H1crG5&ax_>#!%{G1Fc~`#d~4-urZS zP7~Kw;uXqjG79((W4Xq?XLuFuZ&J=KYFlJ<2NnPYPMzh$Tba z#LFb?(M+wL+~SJxO{LsJF3CBysm8vR!47Ax@4 z1cG}OizB?*OTueHNP@UM!JA|j1rbAelWOcPtBP6*$q!0q$1SBq+%Cc|@lDK7z9u>1 ztY|`f*AK(tJ(nQXZ1h)xuyz!B$28xv0>cCQbVx}vPJ`E!&S;~uI-)`EXr|HmrnGe; zN^>yy!uMGr(1Kypma>+E*05rP zoF~^WQoj+s-(EuEoH~$7XdZ&y3NK~bP&cgtW5QI9uE~V!raH=^kyIoR{*Q1q{Olj- zbYLd_Cr(Q|hyehucq8cpZxZmM{49GktSGM;%>r(xP9?oKuOMSc57t%?!O+6lf#NGj zI^C58xN$Qz+YvzxA;R@cEW~}6w1Qe3FTEgXpp|%ZHwQ>l@Uqb z;rJT@h53CL(CH=-DMIp<0h7t@uBT!`#9%SNu0c&51pTv@O3Y6v%&GV6kijT|Zl_xy zF%HZmH!qbaL2%wq*1W*P@+F>qtRyOuD|-kzbr!Ou6|WECG#g^wU*tnYf_#e!qCY zrY=}`&al1K>I4{X$gC2l*nHfl^VC7&v8LG;(0EZJ!c$=)qNjrDLqx2aW~)Ks-=y+X z{DNX+Z&(vv5)t``Y&U3p4uWvz1W_6O1woiN4xOqPg=AJq<|#5{9z178sD{SB$>-_T zIF3W6+MyuY^m$zr#J}YD3Za;f*HMJZW1lodJxIJLlJMv?1S9KgL5TWai0p>{Aigt4 z{2xT4e-PcCr#Jibtvdp$CgG9Qs|AA45v=J8y?S*Rop0aoiYY3qar^74REnQLOK_wmB-JZxLqFzgud=Lhotg_B%+#dNNfCBL}&3EJK4i&n6 z<#X-pKINuAsylRBI5~Q2N;vc7$(%>Y6UAqLxjQ&CB+rqDE_(i`VD+}n8|mqrN`*8& zInt`TrR8lo6YA;13KMb5eSPom6HvxLyMkdSPoJcA#DpCT>N;I>vZ#-l_e4l9G0@Z&|UTWVMUD z+xC1m6W+qn-Nn&#W&@j6w5yfaZ#uXTQ>$36pWk?0t~O z6k4Ur?01@sW=VG_HeI%XUcw%{DGJ^(%%Uv@GQp4`Io`rjU=-mbF}2(B^@Vs@9r|%e!#gOC z+)Bx6NUFj^L?qQlVp25ns@9X;$tgVF_}A>opyV6RT%R7M>~PpxCAfR)Xop^;5OTex zf-f5r1o`|#ZLJdB$!cJ<)VMM^Qbg;^eV!<(aRhmvD>GLy6q|w_RUNUME7k*RL(s8g zG!r1|^=Y|}3)epa)0F&6K%Q!-MekgE2j z$K}aQOpUwwRnJW**}2PxD7?PgQ?r!ebKQ0<#8k~3Z;;f;xA%5Ps90n{m3b<^2LK!? zC6b|L|4OWMyOf$tX6v)58d?{EL=Jss~t|+Mpb{Lo!pToLnTRjJ6lcokd zocvH-%UOdt-&9vdf zpV=SQN@WvOMEUKKlC3tE#b$Nu9&tIt8uc_Bi z^^!rC+y`4fYsH3R9*dbdpQwT+m*vFIJH5OH!>h8aG$XzHl7%cs^XtFduvT&*983w-&N16@qh*^ah?Bx5b$E>FZH8@3@j}|O{KQf(l xk&O8~5^nHwA*uCXlY-P4CZzl)rDOOAz-_Px*&`Cr=RCodHTU~4vRTMsFcG|L#f>nVRH4#ZvC_fKIULd3iCPWe+Shs*>3q^tn zY79|$@xdl)LP8W@cxeO|m&mq5@h3`zXpF&xsL@0VHX;7SKY~Ai)c);u=6G(~>E3&1 zT6T76JJamE+-55x{3P zX8ir*$J_pv`_8nw0>q<@Tc2|X4tR~kJ_I^s!2B01>tMh4e)J`VYyuIkmD`0n&1TQo z>%d>1CzH*0734FgrT~FRpH5^NgR#s3=S(vB_^lK5i{d>M2zun8fv}h3*vGT9TG7jl^06#BrWr2X;v`Pg6ATrx= zLgQoCXtyN8zR#@(0)mqi4G4-15LG^_9&f0fl7L{6QE~~+HX{QBKrHSW?UuZh_POQ6xA*7&}C^=b<@-S4#qd=~4@gD0zh80YVO!Kpp{LXh2ZSu3fu435$zzxJt(Z zM0Ir`)Pn(mq;P~Vw71tgLAU@I)rP#$;CAiAsV5<(u=eT zQy5yj{pM^M>J(kH?Lr`r7#;{w;R&6Dl*vNUXlZGg$J=i0RIf~r(3c&4?G^ewq9^BF z;`Mhc!97A_+eqv{oxH{m!aY>tF98V9Rt}wnLJ|*>8t9Ys+2!OB!()@W-{AGwgSMnY zD60G(#S^}Ia#(^#s4gX5=7xU<>RsXuqek)U5`fT`&+zX+{k*oeR(+s>fiN_(6uzI! zSBSAQjgc_`LnqtPiS$+7d zb3X4aR&hwI=P}h|O@uEy+cT?B>^`JR?Ihi}Q8kfFy~LjI{EhmB>puQj9Wx)uX5Uaw z^@WZl10i;FiA~LEj=$z`8SAeN8=AwIx$ZV6t=v5w3NzBeRXaQF@l~96K>` z?}w^Hyl5Kc>hVAjx@ud~;OcjO_szMLD;_-TI5vO5k8>G$kd#J6FLqi>=&=Mij)U^ASe11S7(n62PuhrF6^^UwvoBX*dGgJ_m z;RxImj@Yy*Rc`|}I1XKlLG=fgby(TrPBn&tr;?kuttSWWM+3U8?9mVP1WMPbY#_w{ z!1%?-eooUyRtkj6F^X-ltfM0Hobqe?_U*HJ`s`B-MuR&!gYZf1?AXKUbb7#*>1D}z zgcwM8f&zjN5-haQNsH=qTs^(^J{bg|gJ=u+MEaBkgb0T*PmpIJs^79@=QO>epmnk; zh5C5%ksf6MAvmEhQK821W}D{Ve+9`D))0Ml;{UPw%STl!3kX4syj!{KH51!2nM|)& zJ{1x=;y=rH@{!(U0U=fgL5z&{@Sog-CvckmmI3kI{>n_gw6o*bJ4}vGji%VF8eA7` zA)ox&c?Q7=Vfsf8e}`>s-rRDhD5nH~$|My8W+npv1IDN#d_&?}KL7v#07*qoM6N<$ Ef?z9i5&!@I diff --git a/module_market/src/main/res/drawable/market_shopping_cart_next_btn.xml b/module_market/src/main/res/drawable/market_shopping_cart_next_btn.xml index 58e9161..f08d346 100644 --- a/module_market/src/main/res/drawable/market_shopping_cart_next_btn.xml +++ b/module_market/src/main/res/drawable/market_shopping_cart_next_btn.xml @@ -1,7 +1,7 @@ - + \ No newline at end of file diff --git a/module_market/src/main/res/drawable/market_shopping_cart_next_btn_red.xml b/module_market/src/main/res/drawable/market_shopping_cart_next_btn_red.xml new file mode 100644 index 0000000..9b3afd2 --- /dev/null +++ b/module_market/src/main/res/drawable/market_shopping_cart_next_btn_red.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/module_market/src/main/res/layout/market_activity_goods_details.xml b/module_market/src/main/res/layout/market_activity_goods_details.xml index ae0026b..d37d6a1 100644 --- a/module_market/src/main/res/layout/market_activity_goods_details.xml +++ b/module_market/src/main/res/layout/market_activity_goods_details.xml @@ -1,5 +1,5 @@ - - + android:layout_height="wrap_content" + android:layout_above="@+id/rl_bottom" + android:layout_below="@+id/rl_top" /> + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_market/src/main/res/layout/market_activity_shopping_cart.xml b/module_market/src/main/res/layout/market_activity_shopping_cart.xml index 8df735f..f1ce104 100644 --- a/module_market/src/main/res/layout/market_activity_shopping_cart.xml +++ b/module_market/src/main/res/layout/market_activity_shopping_cart.xml @@ -36,7 +36,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="8dp" - android:text="@string/check_all" + android:text="@string/market_check_all" android:textSize="12sp" /> @@ -48,7 +48,7 @@ android:layout_centerVertical="true" android:layout_marginStart="8dp" android:layout_toEndOf="@+id/ll_checked_view" - android:text="@string/total" /> + android:text="@string/market_total" /> diff --git a/module_market/src/main/res/layout/market_fragment_goods_info_main.xml b/module_market/src/main/res/layout/market_fragment_goods_info_main.xml index 1a919ff..f466608 100644 --- a/module_market/src/main/res/layout/market_fragment_goods_info_main.xml +++ b/module_market/src/main/res/layout/market_fragment_goods_info_main.xml @@ -45,32 +45,39 @@ - - + + diff --git a/module_market/src/main/res/values/strings.xml b/module_market/src/main/res/values/strings.xml index f06d7d5..01df41a 100644 --- a/module_market/src/main/res/values/strings.xml +++ b/module_market/src/main/res/values/strings.xml @@ -1,6 +1,8 @@ module_market - 全选 - 合计: - 下一步 + 全选 + 合计: + 下一步 + 加入购物车 + 立即购买 diff --git a/module_user/src/main/java/com/wss/module/user/ui/account/mvp/LoginPresenter.java b/module_user/src/main/java/com/wss/module/user/ui/account/mvp/LoginPresenter.java index a2b44d6..209fafa 100644 --- a/module_user/src/main/java/com/wss/module/user/ui/account/mvp/LoginPresenter.java +++ b/module_user/src/main/java/com/wss/module/user/ui/account/mvp/LoginPresenter.java @@ -4,7 +4,7 @@ import com.wss.common.base.mvp.BasePresenter; import com.wss.common.bean.User; -import com.wss.common.net.callback.OnResultObjectCallBack; +import com.wss.common.net.callback.OnResultCallBack; import com.wss.module.user.ui.account.mvp.contract.LoginContract; /** @@ -20,7 +20,7 @@ public class LoginPresenter extends BasePresenter() { + getModule().login(getView().getUserInfo(), new OnResultCallBack() { @Override public void onSuccess(boolean success, int code, String msg, Object tag, User response) { if (code == 0 && response != null && !TextUtils.isEmpty(String.valueOf(response.getId()))) { diff --git a/module_user/src/main/java/com/wss/module/user/ui/account/mvp/RegisterPresenter.java b/module_user/src/main/java/com/wss/module/user/ui/account/mvp/RegisterPresenter.java index 2ca9777..3657a3a 100644 --- a/module_user/src/main/java/com/wss/module/user/ui/account/mvp/RegisterPresenter.java +++ b/module_user/src/main/java/com/wss/module/user/ui/account/mvp/RegisterPresenter.java @@ -1,11 +1,8 @@ package com.wss.module.user.ui.account.mvp; -import android.text.TextUtils; - import com.wss.common.base.mvp.BasePresenter; import com.wss.common.bean.User; -import com.wss.common.constants.Constants; -import com.wss.common.net.callback.OnResultObjectCallBack; +import com.wss.common.net.callback.OnResultCallBack; import com.wss.module.user.ui.account.mvp.contract.RegisterContract; /** @@ -20,7 +17,7 @@ public class RegisterPresenter extends BasePresenter() { + getModule().register(getView().getUserInfo(), new OnResultCallBack() { @Override public void onSuccess(boolean success, int code, String msg, Object tag, User response) { diff --git a/module_user/src/main/java/com/wss/module/user/ui/main/mvp/UserPresenter.java b/module_user/src/main/java/com/wss/module/user/ui/main/mvp/UserPresenter.java index 2649156..16944f5 100644 --- a/module_user/src/main/java/com/wss/module/user/ui/main/mvp/UserPresenter.java +++ b/module_user/src/main/java/com/wss/module/user/ui/main/mvp/UserPresenter.java @@ -3,7 +3,7 @@ import com.wss.common.base.mvp.BasePresenter; import com.wss.common.bean.AppInfo; import com.wss.common.constants.Constants; -import com.wss.common.net.callback.OnResultObjectCallBack; +import com.wss.common.net.callback.OnResultCallBack; import com.wss.common.utils.ToastUtils; import com.wss.module.user.ui.main.mvp.contract.UserContract; @@ -19,7 +19,7 @@ public class UserPresenter extends BasePresenter() { + getModule().checkUpdate(new OnResultCallBack() { @Override public void onSuccess(boolean success, int code, String msg, Object tag, AppInfo response) { if (code == 1000 || response != null) { diff --git a/module_user/src/main/res/layout/user_activity_login.xml b/module_user/src/main/res/layout/user_activity_login.xml index 578b236..b63bbc4 100644 --- a/module_user/src/main/res/layout/user_activity_login.xml +++ b/module_user/src/main/res/layout/user_activity_login.xml @@ -78,14 +78,14 @@ android:text="登录" android:textColor="@color/black" app:defaultBgResource="@drawable/corner_gray_shape" - app:pressBgResource="@drawable/bg_of_orange_gradient" /> + app:pressBgResource="@drawable/bg_of_orange_gradient_radius" /> diff --git a/module_user/src/main/res/layout/user_activity_register.xml b/module_user/src/main/res/layout/user_activity_register.xml index d51d90b..b429ec7 100644 --- a/module_user/src/main/res/layout/user_activity_register.xml +++ b/module_user/src/main/res/layout/user_activity_register.xml @@ -101,6 +101,6 @@ android:text="注册" android:textColor="@color/black" app:defaultBgResource="@drawable/corner_gray_shape" - app:pressBgResource="@drawable/bg_of_orange_gradient" /> + app:pressBgResource="@drawable/bg_of_orange_gradient_radius" /> diff --git a/module_wan_android/src/main/java/com/wss/module/wan/bean/BannerInfo.java b/module_wan_android/src/main/java/com/wss/module/wan/bean/BannerInfo.java index 5abb321..683da83 100644 --- a/module_wan_android/src/main/java/com/wss/module/wan/bean/BannerInfo.java +++ b/module_wan_android/src/main/java/com/wss/module/wan/bean/BannerInfo.java @@ -2,11 +2,15 @@ import com.wss.common.base.bean.BaseBean; +import lombok.Getter; +import lombok.Setter; + /** * Describe:Banner实体类 * Created by 吴天强 on 2018/10/17. */ - +@Getter +@Setter public class BannerInfo extends BaseBean { @@ -30,67 +34,4 @@ public class BannerInfo extends BaseBean { private int type; private String url; - public void setDesc(String desc) { - this.desc = desc; - } - - public void setId(int id) { - this.id = id; - } - - public void setImagePath(String imagePath) { - this.imagePath = imagePath; - } - - public void setIsVisible(int isVisible) { - this.isVisible = isVisible; - } - - public void setOrder(int order) { - this.order = order; - } - - public void setTitle(String title) { - this.title = title; - } - - public void setType(int type) { - this.type = type; - } - - public void setUrl(String url) { - this.url = url; - } - - public String getDesc() { - return desc; - } - - public int getId() { - return id; - } - - public String getImagePath() { - return imagePath; - } - - public int getIsVisible() { - return isVisible; - } - - public int getOrder() { - return order; - } - - public String getTitle() { - return title; - } - - public int getType() { - return type; - } - - public String getUrl() { - return url; - } } diff --git a/module_wan_android/src/main/java/com/wss/module/wan/ui/collection/mvp/CollectionPresenter.java b/module_wan_android/src/main/java/com/wss/module/wan/ui/collection/mvp/CollectionPresenter.java index ec24c89..092abd0 100644 --- a/module_wan_android/src/main/java/com/wss/module/wan/ui/collection/mvp/CollectionPresenter.java +++ b/module_wan_android/src/main/java/com/wss/module/wan/ui/collection/mvp/CollectionPresenter.java @@ -3,7 +3,7 @@ import com.alibaba.fastjson.JSON; import com.wss.common.base.mvp.BasePresenter; import com.wss.common.constants.Constants; -import com.wss.common.net.callback.OnResultStringCallBack; +import com.wss.common.net.callback.OnResultCallBack; import com.wss.module.wan.bean.Article; import com.wss.module.wan.ui.collection.mvp.contract.CollectionContract; @@ -22,7 +22,7 @@ public class CollectionPresenter extends BasePresenter() { @Override public void onSuccess(boolean success, int code, String msg, Object tag, String response) { if (code == Constants.SUCCESS_CODE) { diff --git a/module_wan_android/src/main/java/com/wss/module/wan/ui/main/fragment/HomeFragment.java b/module_wan_android/src/main/java/com/wss/module/wan/ui/main/fragment/HomeFragment.java index b6126ef..48f7caa 100644 --- a/module_wan_android/src/main/java/com/wss/module/wan/ui/main/fragment/HomeFragment.java +++ b/module_wan_android/src/main/java/com/wss/module/wan/ui/main/fragment/HomeFragment.java @@ -16,6 +16,7 @@ import com.wss.common.utils.ActivityToActivity; import com.wss.common.utils.ImageUtils; import com.wss.common.utils.PxUtils; +import com.wss.common.utils.ToastUtils; import com.wss.common.widget.pulltorefresh.OnPullRefreshListener; import com.wss.common.widget.pulltorefresh.PullToRefreshLayout; import com.wss.module.wan.R; @@ -25,8 +26,8 @@ import com.wss.module.wan.bean.WXNumber; import com.wss.module.wan.ui.main.adapter.ArticleAdapter; import com.wss.module.wan.ui.main.adapter.HomeRcyAdapter; -import com.wss.module.wan.ui.main.mvp.contract.HomeContract; import com.wss.module.wan.ui.main.mvp.HomePresenter; +import com.wss.module.wan.ui.main.mvp.contract.HomeContract; import java.util.ArrayList; import java.util.HashMap; @@ -123,6 +124,7 @@ public void onItemClick(int position) { ActivityToActivity.toWebView(mContext, bannerList.get(position).getUrl()); } }); + ToastUtils.showToast(mContext, "收到消息"); } @Override diff --git a/module_wan_android/src/main/java/com/wss/module/wan/ui/main/mvp/HomePresenter.java b/module_wan_android/src/main/java/com/wss/module/wan/ui/main/mvp/HomePresenter.java index 4ff7555..9ae5316 100644 --- a/module_wan_android/src/main/java/com/wss/module/wan/ui/main/mvp/HomePresenter.java +++ b/module_wan_android/src/main/java/com/wss/module/wan/ui/main/mvp/HomePresenter.java @@ -4,8 +4,7 @@ import com.wss.common.base.mvp.BasePresenter; import com.wss.common.bean.Template; import com.wss.common.constants.Constants; -import com.wss.common.net.callback.OnResultListCallBack; -import com.wss.common.net.callback.OnResultStringCallBack; +import com.wss.common.net.callback.OnResultCallBack; import com.wss.module.wan.R; import com.wss.module.wan.bean.Article; import com.wss.module.wan.bean.BannerInfo; @@ -31,32 +30,31 @@ public class HomePresenter extends BasePresenter>() { - - @Override - public void onSuccess(boolean success, int code, String msg, Object tag, List response) { - if (code == 0) { - if (response != null && response.size() > 0) { - getView().bannerList(response); - } else { - getView().onEmpty(tag); - } - } else { - getView().onError(tag, msg); - } + showLoading(); + getModule().getBanner(new OnResultCallBack>() { + @Override + public void onSuccess(boolean success, int code, String msg, Object tag, List response) { + if (code == 0) { + if (response != null && response.size() > 0) { + getView().bannerList(response); + } else { + getView().onEmpty(tag); } + } else { + getView().onError(tag, msg); + } + } - @Override - public void onFailure(Object tag, Exception e) { - getView().onError(tag, Constants.ERROR_MESSAGE); - } + @Override + public void onFailure(Object tag, Exception e) { + getView().onError(tag, Constants.ERROR_MESSAGE); + } + + @Override + public void onCompleted() { + } + }); - @Override - public void onCompleted() { - } - }); } } @@ -78,7 +76,7 @@ public void getBlockList() { @Override public void getWXNumber() { if (isViewAttached()) { - getModule().getWXNumber(new OnResultListCallBack>() { + getModule().getWXNumber(new OnResultCallBack>() { @Override public void onSuccess(boolean success, int code, String msg, Object tag, List response) { if (code == Constants.SUCCESS_CODE && response != null && response.size() > 0) { @@ -88,7 +86,6 @@ public void onSuccess(boolean success, int code, String msg, Object tag, List() { + + @Override - public void onSuccess(boolean success, int code, String msg, Object tag, String - response) { + public void onSuccess(boolean success, int code, String msg, Object tag, String response) { if (code == Constants.SUCCESS_CODE) { - final List
articleList = JSON.parseArray(JSON.parseObject(response).getString("datas"), Article.class); + final List
articleList = JSON.parseArray( + JSON.parseObject(response).getString("datas"), Article.class); if (articleList == null || articleList.size() < 1) { getView().onEmpty(tag); } else { @@ -122,12 +121,11 @@ public void onSuccess(boolean success, int code, String msg, Object tag, String @Override public void onFailure(Object tag, Exception e) { - getView().onError(tag, Constants.ERROR_MESSAGE); } @Override public void onCompleted() { - getView().dismissLoading(); + dismissLoading(); } }); } @@ -143,7 +141,6 @@ protected HomeModel createModule() { public void start() { getBanner(); getBlockList(); - getBanner(); getWXNumber(); getArticleList(); } diff --git a/module_wan_android/src/main/java/com/wss/module/wan/ui/project/mvp/ProjectPresenter.java b/module_wan_android/src/main/java/com/wss/module/wan/ui/project/mvp/ProjectPresenter.java index a89b856..8d29b37 100644 --- a/module_wan_android/src/main/java/com/wss/module/wan/ui/project/mvp/ProjectPresenter.java +++ b/module_wan_android/src/main/java/com/wss/module/wan/ui/project/mvp/ProjectPresenter.java @@ -3,8 +3,7 @@ import com.alibaba.fastjson.JSON; import com.wss.common.base.mvp.BasePresenter; import com.wss.common.constants.Constants; -import com.wss.common.net.callback.OnResultListCallBack; -import com.wss.common.net.callback.OnResultStringCallBack; +import com.wss.common.net.callback.OnResultCallBack; import com.wss.module.wan.bean.Article; import com.wss.module.wan.bean.Classification; import com.wss.module.wan.ui.project.mvp.contract.ProjectContract; @@ -33,7 +32,7 @@ public void start() { public void getProjectType() { if (isViewAttached()) { getView().showLoading(); - getModule().getProjectType(new OnResultListCallBack>() { + getModule().getProjectType(new OnResultCallBack>() { @Override public void onSuccess(boolean success, int code, String msg, Object tag, List response) { if (code == Constants.SUCCESS_CODE) { @@ -65,7 +64,7 @@ public void onCompleted() { public void getProject() { if (isViewAttached()) { getView().showLoading(); - getModule().getProject(getView().getPage(), getView().getTypeId(), new OnResultStringCallBack() { + getModule().getProject(getView().getPage(), getView().getTypeId(), new OnResultCallBack() { @Override public void onSuccess(boolean success, int code, String msg, Object tag, String response) { if (code == Constants.SUCCESS_CODE) { diff --git a/module_wan_android/src/main/java/com/wss/module/wan/ui/search/mvp/SearchPresenter.java b/module_wan_android/src/main/java/com/wss/module/wan/ui/search/mvp/SearchPresenter.java index 78ec6b6..d2d4516 100644 --- a/module_wan_android/src/main/java/com/wss/module/wan/ui/search/mvp/SearchPresenter.java +++ b/module_wan_android/src/main/java/com/wss/module/wan/ui/search/mvp/SearchPresenter.java @@ -3,7 +3,7 @@ import com.alibaba.fastjson.JSON; import com.wss.common.base.mvp.BasePresenter; import com.wss.common.constants.Constants; -import com.wss.common.net.callback.OnResultStringCallBack; +import com.wss.common.net.callback.OnResultCallBack; import com.wss.module.wan.bean.Article; import com.wss.module.wan.ui.search.mvp.contract.SearchContract; @@ -20,7 +20,7 @@ public class SearchPresenter extends BasePresenter() { @Override public void onSuccess(boolean success, int code, String msg, Object tag, String response) { if (code == Constants.SUCCESS_CODE) { diff --git a/module_wan_android/src/main/java/com/wss/module/wan/ui/setup/mvp/SystemArticlePresenter.java b/module_wan_android/src/main/java/com/wss/module/wan/ui/setup/mvp/SystemArticlePresenter.java index de4c245..96340c2 100644 --- a/module_wan_android/src/main/java/com/wss/module/wan/ui/setup/mvp/SystemArticlePresenter.java +++ b/module_wan_android/src/main/java/com/wss/module/wan/ui/setup/mvp/SystemArticlePresenter.java @@ -3,7 +3,7 @@ import com.alibaba.fastjson.JSON; import com.wss.common.base.mvp.BasePresenter; import com.wss.common.constants.Constants; -import com.wss.common.net.callback.OnResultStringCallBack; +import com.wss.common.net.callback.OnResultCallBack; import com.wss.module.wan.bean.Article; import com.wss.module.wan.ui.setup.mvp.contract.SystemArticleContract; @@ -22,7 +22,7 @@ public class SystemArticlePresenter extends BasePresenter() { @Override public void onSuccess(boolean success, int code, String msg, Object tag, String response) { if (code == Constants.SUCCESS_CODE) { diff --git a/module_wan_android/src/main/java/com/wss/module/wan/ui/setup/mvp/SystemPresenter.java b/module_wan_android/src/main/java/com/wss/module/wan/ui/setup/mvp/SystemPresenter.java index 42d02b5..beee629 100644 --- a/module_wan_android/src/main/java/com/wss/module/wan/ui/setup/mvp/SystemPresenter.java +++ b/module_wan_android/src/main/java/com/wss/module/wan/ui/setup/mvp/SystemPresenter.java @@ -2,7 +2,7 @@ import com.wss.common.base.mvp.BasePresenter; import com.wss.common.constants.Constants; -import com.wss.common.net.callback.OnResultListCallBack; +import com.wss.common.net.callback.OnResultCallBack; import com.wss.module.wan.bean.Classification; import com.wss.module.wan.ui.setup.mvp.contract.SystemContract; @@ -19,7 +19,7 @@ public class SystemPresenter extends BasePresenter>() { + getModule().getSystem(new OnResultCallBack>() { @Override public void onSuccess(boolean success, int code, String msg, Object tag, List response) { if (code == 0) { diff --git a/module_wan_android/src/main/java/com/wss/module/wan/ui/wxnumber/mvp/WXArticlePresenter.java b/module_wan_android/src/main/java/com/wss/module/wan/ui/wxnumber/mvp/WXArticlePresenter.java index 1d689f2..12714e8 100644 --- a/module_wan_android/src/main/java/com/wss/module/wan/ui/wxnumber/mvp/WXArticlePresenter.java +++ b/module_wan_android/src/main/java/com/wss/module/wan/ui/wxnumber/mvp/WXArticlePresenter.java @@ -3,7 +3,7 @@ import com.alibaba.fastjson.JSON; import com.wss.common.base.mvp.BasePresenter; import com.wss.common.constants.Constants; -import com.wss.common.net.callback.OnResultStringCallBack; +import com.wss.common.net.callback.OnResultCallBack; import com.wss.module.wan.bean.Article; import com.wss.module.wan.ui.wxnumber.mvp.contract.WXNumberContract; @@ -22,7 +22,7 @@ public class WXArticlePresenter extends BasePresenter() { @Override public void onSuccess(boolean success, int code, String msg, Object tag, String response) { diff --git a/module_wan_android/src/main/res/layout/wan_action_bar_of_search.xml b/module_wan_android/src/main/res/layout/wan_action_bar_of_search.xml index e6048b6..a1be658 100644 --- a/module_wan_android/src/main/res/layout/wan_action_bar_of_search.xml +++ b/module_wan_android/src/main/res/layout/wan_action_bar_of_search.xml @@ -55,7 +55,7 @@ android:textColor="@color/black" android:textSize="14sp" app:defaultBgResource="@drawable/corner_gray_shape" - app:pressBgResource="@drawable/bg_of_orange_gradient" /> + app:pressBgResource="@drawable/bg_of_orange_gradient_radius" /> diff --git a/module_wan_android/src/main/res/layout/wan_item_of_article_list.xml b/module_wan_android/src/main/res/layout/wan_item_of_article_list.xml index 1800b88..599e788 100644 --- a/module_wan_android/src/main/res/layout/wan_item_of_article_list.xml +++ b/module_wan_android/src/main/res/layout/wan_item_of_article_list.xml @@ -36,7 +36,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="10dp" - android:background="@drawable/bg_of_orange_gradient" + android:background="@drawable/bg_of_orange_gradient_radius" android:padding="4dp" android:textColor="@color/white" android:textSize="12sp" /> @@ -46,7 +46,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="10dp" - android:background="@drawable/bg_of_green_gradient" + android:background="@drawable/bg_of_green_gradient_radius" android:padding="4dp" android:textColor="@color/white" android:textSize="12sp" /> From 43dc0650dd48bccb6760a227037cf91decfe68a5 Mon Sep 17 00:00:00 2001 From: wutq Date: Wed, 28 Nov 2018 18:52:43 +0800 Subject: [PATCH 02/23] fix bug --- .../src/main/java/com/wss/module/main/ui/main/MainActivity.java | 2 +- .../java/com/wss/module/wan/ui/main/fragment/HomeFragment.java | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/module_main/src/main/java/com/wss/module/main/ui/main/MainActivity.java b/module_main/src/main/java/com/wss/module/main/ui/main/MainActivity.java index d16b3a0..c5ad7bb 100644 --- a/module_main/src/main/java/com/wss/module/main/ui/main/MainActivity.java +++ b/module_main/src/main/java/com/wss/module/main/ui/main/MainActivity.java @@ -85,7 +85,7 @@ public void onCheckedChanged(RadioGroup group, @IdRes int checkedId) { } }); //检查文件权限 if (PermissionsUtils.checkPermissions(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) { -// presenter.checkUpdate(); + presenter.checkUpdate(); } presenter.getTabList(); } diff --git a/module_wan_android/src/main/java/com/wss/module/wan/ui/main/fragment/HomeFragment.java b/module_wan_android/src/main/java/com/wss/module/wan/ui/main/fragment/HomeFragment.java index 48f7caa..5a8dcf7 100644 --- a/module_wan_android/src/main/java/com/wss/module/wan/ui/main/fragment/HomeFragment.java +++ b/module_wan_android/src/main/java/com/wss/module/wan/ui/main/fragment/HomeFragment.java @@ -16,7 +16,6 @@ import com.wss.common.utils.ActivityToActivity; import com.wss.common.utils.ImageUtils; import com.wss.common.utils.PxUtils; -import com.wss.common.utils.ToastUtils; import com.wss.common.widget.pulltorefresh.OnPullRefreshListener; import com.wss.common.widget.pulltorefresh.PullToRefreshLayout; import com.wss.module.wan.R; @@ -124,7 +123,6 @@ public void onItemClick(int position) { ActivityToActivity.toWebView(mContext, bannerList.get(position).getUrl()); } }); - ToastUtils.showToast(mContext, "收到消息"); } @Override From f5e8a60dcfd1e005ea3642bf7de11b81b528a2fb Mon Sep 17 00:00:00 2001 From: wutq Date: Wed, 5 Dec 2018 15:10:19 +0800 Subject: [PATCH 03/23] =?UTF-8?q?fix=20=20=E7=A9=BA=E9=A1=B5=E9=9D=A2?= =?UTF-8?q?=E5=8A=A0=E8=BD=BDBUG?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- common_base/build.gradle | 1 + .../common/adapter/FragmentPagerAdapter.java | 4 ++-- .../com/wss/common/base/BaseActivity.java | 22 +++++++++--------- .../com/wss/common/base/BaseFragment.java | 23 +++++++++---------- .../com/wss/common/base/BaseMvpActivity.java | 3 +-- .../wss/common/base/mvp/BasePresenter.java | 2 +- .../wss/common/widget/NumberProgressBar.java | 5 +++- .../src/main/AndroidManifest.xml | 1 - 8 files changed, 31 insertions(+), 30 deletions(-) diff --git a/common_base/build.gradle b/common_base/build.gradle index 33a99e0..8fda9e6 100644 --- a/common_base/build.gradle +++ b/common_base/build.gradle @@ -48,6 +48,7 @@ dependencies { api rootProject.ext.dependencies["support-v4"] api rootProject.ext.dependencies["design"] api rootProject.ext.dependencies["support_annotations"] + api rootProject.ext.dependencies["junit"] //MultiDex分包方法 api rootProject.ext.dependencies["multidex"] //黄油刀 diff --git a/common_base/src/main/java/com/wss/common/adapter/FragmentPagerAdapter.java b/common_base/src/main/java/com/wss/common/adapter/FragmentPagerAdapter.java index 499cb62..8c9f0d4 100644 --- a/common_base/src/main/java/com/wss/common/adapter/FragmentPagerAdapter.java +++ b/common_base/src/main/java/com/wss/common/adapter/FragmentPagerAdapter.java @@ -13,8 +13,8 @@ /** * Describe:滑动Fragment适配器 - * 如果滑动Fragment是同一个 使用双参构造方法 则覆写 getTabFragment 返回Fragment - * 如果滑动Fragment是不同的Fragment 使用第三参个构造方法 传入对应的Fragment + * 如果滑动Fragment是同一个 使用双参构造方法 覆写 getTabFragment 返回Fragment + * 如果滑动Fragment是不同的Fragment 使用第三参构造方法 传入对应的Fragment集合 *

* Created by 吴天强 on 2018/10/22. */ diff --git a/common_base/src/main/java/com/wss/common/base/BaseActivity.java b/common_base/src/main/java/com/wss/common/base/BaseActivity.java index ae77bd4..8cd0568 100644 --- a/common_base/src/main/java/com/wss/common/base/BaseActivity.java +++ b/common_base/src/main/java/com/wss/common/base/BaseActivity.java @@ -122,19 +122,19 @@ protected void showErrorView() { } public void showEmptyOrErrorView(String text, int img) { - emptyView = findViewById(R.id.vs_empty); - if (emptyView != null) { - emptyView.setVisibility(View.VISIBLE); - findViewById(R.id.iv_empty).setBackgroundResource(img); - ((TextView) findViewById(R.id.tv_empty)).setText(text); - findViewById(R.id.ll_empty).setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - onPageClick(); - } - }); + if (emptyView == null) { + emptyView = findViewById(R.id.vs_empty); } + emptyView.setVisibility(View.VISIBLE); + findViewById(R.id.iv_empty).setBackgroundResource(img); + ((TextView) findViewById(R.id.tv_empty)).setText(text); + findViewById(R.id.ll_empty).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + onPageClick(); + } + }); } protected void hideEmptyView() { diff --git a/common_base/src/main/java/com/wss/common/base/BaseFragment.java b/common_base/src/main/java/com/wss/common/base/BaseFragment.java index edc3de2..745f750 100644 --- a/common_base/src/main/java/com/wss/common/base/BaseFragment.java +++ b/common_base/src/main/java/com/wss/common/base/BaseFragment.java @@ -84,19 +84,18 @@ protected void showErrorView() { } public void showEmptyOrErrorView(String text, int img) { - emptyView = rootView.findViewById(R.id.vs_empty); - - if (emptyView != null) { - emptyView.setVisibility(View.VISIBLE); - rootView.findViewById(R.id.iv_empty).setBackgroundResource(img); - ((TextView) rootView.findViewById(R.id.tv_empty)).setText(text); - rootView.findViewById(R.id.ll_empty).setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - onPageClick(); - } - }); + if (emptyView == null) { + emptyView = rootView.findViewById(R.id.vs_empty); } + emptyView.setVisibility(View.VISIBLE); + rootView.findViewById(R.id.iv_empty).setBackgroundResource(img); + ((TextView) rootView.findViewById(R.id.tv_empty)).setText(text); + rootView.findViewById(R.id.ll_empty).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + onPageClick(); + } + }); } protected void hideEmptyView() { diff --git a/common_base/src/main/java/com/wss/common/base/BaseMvpActivity.java b/common_base/src/main/java/com/wss/common/base/BaseMvpActivity.java index 826b881..e5aedff 100644 --- a/common_base/src/main/java/com/wss/common/base/BaseMvpActivity.java +++ b/common_base/src/main/java/com/wss/common/base/BaseMvpActivity.java @@ -11,13 +11,12 @@ * Describe:所有需要Mvp开发的Activity的基类 * Created by 吴天强 on 2018/10/15. */ - +@SuppressWarnings("unchecked") public abstract class BaseMvpActivity

extends BaseActivity implements IBaseView { protected P presenter; - @SuppressWarnings("unchecked") @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); diff --git a/common_base/src/main/java/com/wss/common/base/mvp/BasePresenter.java b/common_base/src/main/java/com/wss/common/base/mvp/BasePresenter.java index bb3c05d..58f4358 100644 --- a/common_base/src/main/java/com/wss/common/base/mvp/BasePresenter.java +++ b/common_base/src/main/java/com/wss/common/base/mvp/BasePresenter.java @@ -12,6 +12,7 @@ * Created by 吴天强 on 2018/10/17. */ +@SuppressWarnings("unchecked") public abstract class BasePresenter { private V mProxyView; @@ -21,7 +22,6 @@ public abstract class BasePresenter { /** * 绑定View */ - @SuppressWarnings("unchecked") public void attachView(V view) { weakReference = new WeakReference<>(view); mProxyView = (V) Proxy.newProxyInstance( diff --git a/common_base/src/main/java/com/wss/common/widget/NumberProgressBar.java b/common_base/src/main/java/com/wss/common/widget/NumberProgressBar.java index 89a56f3..f114fff 100644 --- a/common_base/src/main/java/com/wss/common/widget/NumberProgressBar.java +++ b/common_base/src/main/java/com/wss/common/widget/NumberProgressBar.java @@ -15,7 +15,10 @@ import com.wss.common.base.R; - +/** + * Describe:数字进度条 + * Created by 吴天强 on 2018/11/1. + */ public class NumberProgressBar extends View { diff --git a/module_wan_android/src/main/AndroidManifest.xml b/module_wan_android/src/main/AndroidManifest.xml index e3b480a..ae4412c 100644 --- a/module_wan_android/src/main/AndroidManifest.xml +++ b/module_wan_android/src/main/AndroidManifest.xml @@ -9,6 +9,5 @@ - From fb92625ea4342421546adab4c6772ae35a69d5ba Mon Sep 17 00:00:00 2001 From: wutq Date: Tue, 19 Mar 2019 14:26:02 +0800 Subject: [PATCH 04/23] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=BA=86=E4=BA=8E?= =?UTF-8?q?=E6=85=A2=E6=85=A2=E7=89=8C=E8=AE=A1=E7=AE=97=E5=99=A8=EF=BC=8C?= =?UTF-8?q?=E8=87=AA=E5=AE=9A=E4=B9=89RadioGroup?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- common_base/src/main/AndroidManifest.xml | 3 +- .../com/wss/common/base/BaseMvpActivity.java | 8 + .../java/com/wss/common/utils/MoneyUtils.java | 6 +- .../java/com/wss/common/utils/PxUtils.java | 7 + .../wss/common/widget/NumberProgressBar.java | 2 +- .../wss/common/widget/StrongRadioGroup.java | 381 ++++++++++++++++++ .../res/drawable-xhdpi/popup_icon_close.png | Bin 0 -> 498 bytes .../src/main/res/drawable-xxhdpi/ic_back.png | Bin 612 -> 916 bytes .../res/drawable-xxhdpi/input_add_default.png | Bin 266 -> 429 bytes .../drawable-xxhdpi/input_add_disabled.png | Bin 266 -> 388 bytes .../drawable-xxhdpi/input_minus_default.png | Bin 138 -> 181 bytes .../drawable-xxhdpi/input_minus_disabled.png | Bin 155 -> 204 bytes .../res/drawable-xxhdpi/popup_icon_close.png | Bin 0 -> 747 bytes .../src/main/res/drawable-xxxhdpi/ic_back.png | Bin 916 -> 0 bytes .../main/res/drawable-xxxhdpi/ic_launcher.png | Bin 4851 -> 0 bytes .../drawable-xxxhdpi/input_add_default.png | Bin 429 -> 0 bytes .../drawable-xxxhdpi/input_add_disabled.png | Bin 388 -> 0 bytes .../drawable-xxxhdpi/input_minus_default.png | Bin 181 -> 0 bytes .../drawable-xxxhdpi/input_minus_disabled.png | Bin 204 -> 0 bytes .../res/drawable/market_shape_round_red.xml | 0 common_base/src/main/res/values/colors.xml | 2 +- module_main/src/main/AndroidManifest.xml | 3 + .../wss/module/main/ui/main/MainActivity.java | 1 + .../main/ui/main/mvp/MainPresenter.java | 4 + .../module/main/ui/page/DialogActivity.java | 22 +- .../main/ui/page/RadioGroupActivity.java | 48 +++ .../module/main/ui/page/YumanmanActivity.java | 196 +++++++++ .../res/layout/main_activity_radio_group.xml | 59 +++ .../res/layout/main_activity_scale_image.xml | 4 + .../res/layout/main_activity_yumanman.xml | 148 +++++++ .../src/main/assets/html/goods_detail.html | 83 ++++ .../ui/goods/detail/GoodsDetailActivity.java | 32 +- .../fragment/GoodsInfoMainFragment.java | 9 +- .../fragment/child/GoodsConfigFragment.java | 16 +- .../fragment/child/GoodsInfoWebFragment.java | 4 +- .../detail/helper/GoodsSpecificationPop.java | 106 +++++ .../color/market_goods_button_text_color.xml | 5 + .../market_bg_of_ellipse_button_black.xml | 12 + .../market_bg_of_ellipse_button_red.xml | 12 + .../market_bg_of_ellipse_button_select.xml | 5 + .../layout/market_activity_goods_details.xml | 1 + .../market_fragment_goods_info_main.xml | 6 +- .../market_item_of_goods_config_list.xml | 19 +- .../layout/market_pop_goods_specification.xml | 99 +++++ 44 files changed, 1260 insertions(+), 43 deletions(-) create mode 100644 common_base/src/main/java/com/wss/common/widget/StrongRadioGroup.java create mode 100644 common_base/src/main/res/drawable-xhdpi/popup_icon_close.png create mode 100644 common_base/src/main/res/drawable-xxhdpi/popup_icon_close.png delete mode 100644 common_base/src/main/res/drawable-xxxhdpi/ic_back.png delete mode 100644 common_base/src/main/res/drawable-xxxhdpi/ic_launcher.png delete mode 100644 common_base/src/main/res/drawable-xxxhdpi/input_add_default.png delete mode 100644 common_base/src/main/res/drawable-xxxhdpi/input_add_disabled.png delete mode 100644 common_base/src/main/res/drawable-xxxhdpi/input_minus_default.png delete mode 100644 common_base/src/main/res/drawable-xxxhdpi/input_minus_disabled.png rename {module_market => common_base}/src/main/res/drawable/market_shape_round_red.xml (100%) create mode 100644 module_main/src/main/java/com/wss/module/main/ui/page/RadioGroupActivity.java create mode 100644 module_main/src/main/java/com/wss/module/main/ui/page/YumanmanActivity.java create mode 100644 module_main/src/main/res/layout/main_activity_radio_group.xml create mode 100644 module_main/src/main/res/layout/main_activity_yumanman.xml create mode 100644 module_market/src/main/assets/html/goods_detail.html create mode 100644 module_market/src/main/java/com/wss/module/market/ui/goods/detail/helper/GoodsSpecificationPop.java create mode 100644 module_market/src/main/res/color/market_goods_button_text_color.xml create mode 100644 module_market/src/main/res/drawable/market_bg_of_ellipse_button_black.xml create mode 100644 module_market/src/main/res/drawable/market_bg_of_ellipse_button_red.xml create mode 100644 module_market/src/main/res/drawable/market_bg_of_ellipse_button_select.xml create mode 100644 module_market/src/main/res/layout/market_pop_goods_specification.xml diff --git a/common_base/src/main/AndroidManifest.xml b/common_base/src/main/AndroidManifest.xml index a4ea8b7..f0f9a56 100644 --- a/common_base/src/main/AndroidManifest.xml +++ b/common_base/src/main/AndroidManifest.xml @@ -9,7 +9,8 @@ - + + diff --git a/common_base/src/main/java/com/wss/common/base/BaseMvpActivity.java b/common_base/src/main/java/com/wss/common/base/BaseMvpActivity.java index e5aedff..30e6ab6 100644 --- a/common_base/src/main/java/com/wss/common/base/BaseMvpActivity.java +++ b/common_base/src/main/java/com/wss/common/base/BaseMvpActivity.java @@ -3,6 +3,7 @@ import android.content.Context; import android.os.Bundle; import android.support.annotation.Nullable; +import android.text.TextUtils; import com.wss.common.base.mvp.BasePresenter; import com.wss.common.base.mvp.IBaseView; @@ -41,7 +42,14 @@ protected void onDestroy() { //***************************************IBaseView方法实现************************************* @Override public void showLoading() { + showLoading(""); + } + + public void showLoading(String msg) { if (loadingDialog != null && !loadingDialog.isShowing()) { + if (!TextUtils.isEmpty(msg)) { + loadingDialog.setTitleText(msg); + } loadingDialog.show(); } } diff --git a/common_base/src/main/java/com/wss/common/utils/MoneyUtils.java b/common_base/src/main/java/com/wss/common/utils/MoneyUtils.java index 15d12d4..ebc2363 100644 --- a/common_base/src/main/java/com/wss/common/utils/MoneyUtils.java +++ b/common_base/src/main/java/com/wss/common/utils/MoneyUtils.java @@ -24,9 +24,9 @@ public static class Algorithm { * @param v2 * @return */ - public static String add(String v1, String v2) { - BigDecimal b1 = new BigDecimal(v1); - BigDecimal b2 = new BigDecimal(v2); + public static String add(Object v1, Object v2) { + BigDecimal b1 = new BigDecimal(String.valueOf(v1)); + BigDecimal b2 = new BigDecimal(String.valueOf(v2)); return b1.add(b2).toString(); } diff --git a/common_base/src/main/java/com/wss/common/utils/PxUtils.java b/common_base/src/main/java/com/wss/common/utils/PxUtils.java index 005da2a..83a205e 100644 --- a/common_base/src/main/java/com/wss/common/utils/PxUtils.java +++ b/common_base/src/main/java/com/wss/common/utils/PxUtils.java @@ -2,6 +2,8 @@ import android.content.Context; +import com.wss.common.base.BaseApplication; + /** * Describe:尺寸工具类 * Created by 吴天强 on 2017/9/19. @@ -37,6 +39,11 @@ public static int dp2px(Context context, float dipValue) { return (int) (dipValue * scale + 0.5); } + public static int dp2px(float dipValue) { + final float scale = getScreenDensity(BaseApplication.getApplication()); + return (int) (dipValue * scale + 0.5); + } + /** * 将像素转换成dp * diff --git a/common_base/src/main/java/com/wss/common/widget/NumberProgressBar.java b/common_base/src/main/java/com/wss/common/widget/NumberProgressBar.java index f114fff..b129306 100644 --- a/common_base/src/main/java/com/wss/common/widget/NumberProgressBar.java +++ b/common_base/src/main/java/com/wss/common/widget/NumberProgressBar.java @@ -32,7 +32,7 @@ public class NumberProgressBar extends View { */ private Context context; - /** + /**l * 主线程传过来进程 0 - 100 */ private int progress; diff --git a/common_base/src/main/java/com/wss/common/widget/StrongRadioGroup.java b/common_base/src/main/java/com/wss/common/widget/StrongRadioGroup.java new file mode 100644 index 0000000..66889fb --- /dev/null +++ b/common_base/src/main/java/com/wss/common/widget/StrongRadioGroup.java @@ -0,0 +1,381 @@ +package com.wss.common.widget; + +import android.content.Context; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; +import android.widget.CompoundButton; +import android.widget.LinearLayout; +import android.widget.RadioButton; + + +/** + * Describe:可添加任意ViewGroup的RadioGroup + * Created by 吴天强 on 2019/3/18. + */ + +public class StrongRadioGroup extends LinearLayout { + // holds the checked id; the selection is empty by default + private int mCheckedId = -1; + // tracks children radio buttons checked state + private CompoundButton.OnCheckedChangeListener mChildOnCheckedChangeListener; + // when true, mOnCheckedChangeListener discards events + private boolean mProtectFromCheckedChange = false; + private OnCheckedChangeListener mOnCheckedChangeListener; + private PassThroughHierarchyChangeListener mPassThroughListener; + + public StrongRadioGroup(Context context) { + super(context); + setOrientation(VERTICAL); + init(); + } + + public StrongRadioGroup(Context context, AttributeSet attrs) { + super(context, attrs); + init(); + } + + private void init() { + mChildOnCheckedChangeListener = new CheckedStateTracker(); + mPassThroughListener = new PassThroughHierarchyChangeListener(); + super.setOnHierarchyChangeListener(mPassThroughListener); + } + + @Override + public void setOnHierarchyChangeListener(OnHierarchyChangeListener listener) { + // the user listener is delegated to our pass-through listener + mPassThroughListener.mOnHierarchyChangeListener = listener; + } + + @Override + protected void onFinishInflate() { + super.onFinishInflate(); + + // checks the appropriate radio button as requested in the XML file + if (mCheckedId != -1) { + mProtectFromCheckedChange = true; + setCheckedStateForView(mCheckedId, true); + mProtectFromCheckedChange = false; + setCheckedId(mCheckedId); + } + } + + @Override + public void addView(View child, int index, ViewGroup.LayoutParams params) { + if (child instanceof RadioButton) { + final RadioButton button = (RadioButton) child; + if (button.isChecked()) { + mProtectFromCheckedChange = true; + if (mCheckedId != -1) { + setCheckedStateForView(mCheckedId, false); + } + mProtectFromCheckedChange = false; + setCheckedId(button.getId()); + } + } else if (child instanceof ViewGroup) { + //添加部分 + final RadioButton button = findRadioButton((ViewGroup) child); + if (button.isChecked()) { + mProtectFromCheckedChange = true; + if (mCheckedId != -1) { + setCheckedStateForView(mCheckedId, false); + } + mProtectFromCheckedChange = false; + setCheckedId(button.getId()); + } + } + + super.addView(child, index, params); + } + + /** + * 查找radioButton控件 + */ + public RadioButton findRadioButton(ViewGroup group) { + RadioButton resBtn = null; + int len = group.getChildCount(); + for (int i = 0; i < len; i++) { + if (group.getChildAt(i) instanceof RadioButton) { + resBtn = (RadioButton) group.getChildAt(i); + } else if (group.getChildAt(i) instanceof ViewGroup) { + findRadioButton((ViewGroup) group.getChildAt(i)); + } + } + return resBtn; + } + + /** + *

+ * Sets the selection to the radio button whose identifier is passed in + * parameter. Using -1 as the selection identifier clears the selection; + * such an operation is equivalent to invoking {@link #clearCheck()}. + *

+ * + * @param id the unique id of the radio button to select in this group + * @see #getCheckedRadioButtonId() + * @see #clearCheck() + */ + public void check(int id) { + // don't even bother + if (id != -1 && (id == mCheckedId)) { + return; + } + + if (mCheckedId != -1) { + setCheckedStateForView(mCheckedId, false); + } + + if (id != -1) { + setCheckedStateForView(id, true); + } + + setCheckedId(id); + } + + private void setCheckedId(int id) { + mCheckedId = id; + if (mOnCheckedChangeListener != null) { + mOnCheckedChangeListener.onCheckedChanged(this, mCheckedId); + } + } + + private void setCheckedStateForView(int viewId, boolean checked) { + View checkedView = findViewById(viewId); + if (checkedView != null && checkedView instanceof RadioButton) { + ((RadioButton) checkedView).setChecked(checked); + } + } + + /** + *

+ * Returns the identifier of the selected radio button in this group. Upon + * empty selection, the returned value is -1. + *

+ * + * @return the unique id of the selected radio button in this group + * @see #check(int) + * @see #clearCheck() + */ + public int getCheckedRadioButtonId() { + return mCheckedId; + } + + /** + *

+ * Clears the selection. When the selection is cleared, no radio button in + * this group is selected and {@link #getCheckedRadioButtonId()} returns + * null. + *

+ * + * @see #check(int) + * @see #getCheckedRadioButtonId() + */ + public void clearCheck() { + check(-1); + } + + /** + *

+ * Register a callback to be invoked when the checked radio button changes + * in this group. + *

+ * + * @param listener the callback to call on checked state change + */ + public void setOnCheckedChangeListener(OnCheckedChangeListener listener) { + mOnCheckedChangeListener = listener; + } + + /** + * {@inheritDoc} + */ + @Override + public LayoutParams generateLayoutParams(AttributeSet attrs) { + return new StrongRadioGroup.LayoutParams(getContext(), attrs); + } + + /** + * {@inheritDoc} + */ + @Override + protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { + return p instanceof StrongRadioGroup.LayoutParams; + } + + @Override + protected LinearLayout.LayoutParams generateDefaultLayoutParams() { + return new LayoutParams(LayoutParams.WRAP_CONTENT, + LayoutParams.WRAP_CONTENT); + } + + /** + *

+ * This set of layout parameters defaults the width and the height of the + * children to {@link #WRAP_CONTENT} when they are not specified in the XML + * file. Otherwise, this class ussed the value read from the XML file. + *

+ *

+ *

+ * Attributes} for a list of all child view attributes that this class + * supports. + *

+ */ + public static class LayoutParams extends LinearLayout.LayoutParams { + /** + * {@inheritDoc} + */ + public LayoutParams(Context c, AttributeSet attrs) { + super(c, attrs); + } + + /** + * {@inheritDoc} + */ + public LayoutParams(int w, int h) { + super(w, h); + } + + /** + * {@inheritDoc} + */ + public LayoutParams(int w, int h, float initWeight) { + super(w, h, initWeight); + } + + /** + * {@inheritDoc} + */ + public LayoutParams(ViewGroup.LayoutParams p) { + super(p); + } + + /** + * {@inheritDoc} + */ + public LayoutParams(MarginLayoutParams source) { + super(source); + } + + /** + *

+ * Fixes the child's width to + * {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT} and the + * child's height to + * {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT} when not + * specified in the XML file. + *

+ * + * @param a the styled attributes set + * @param widthAttr the width attribute to fetch + * @param heightAttr the height attribute to fetch + */ + @Override + protected void setBaseAttributes(TypedArray a, int widthAttr, + int heightAttr) { + + if (a.hasValue(widthAttr)) { + width = a.getLayoutDimension(widthAttr, "layout_width"); + } else { + width = WRAP_CONTENT; + } + + if (a.hasValue(heightAttr)) { + height = a.getLayoutDimension(heightAttr, "layout_height"); + } else { + height = WRAP_CONTENT; + } + } + } + + /** + *

+ * Interface definition for a callback to be invoked when the checked radio + * button changed in this group. + *

+ */ + public interface OnCheckedChangeListener { + /** + *

+ * Called when the checked radio button has changed. When the selection + * is cleared, checkedId is -1. + *

+ * + * @param group the group in which the checked radio button has changed + * @param checkedId the unique identifier of the newly checked radio button + */ + public void onCheckedChanged(StrongRadioGroup group, int checkedId); + } + + private class CheckedStateTracker implements + CompoundButton.OnCheckedChangeListener { + public void onCheckedChanged(CompoundButton buttonView, + boolean isChecked) { + // prevents from infinite recursion + if (mProtectFromCheckedChange) { + return; + } + + mProtectFromCheckedChange = true; + if (mCheckedId != -1) { + setCheckedStateForView(mCheckedId, false); + } + mProtectFromCheckedChange = false; + + int id = buttonView.getId(); + setCheckedId(id); + } + } + + /** + *

+ * A pass-through listener acts upon the events and dispatches them to + * another listener. This allows the table layout to set its own internal + * hierarchy change listener without preventing the user to setup his. + *

+ */ + private class PassThroughHierarchyChangeListener implements + ViewGroup.OnHierarchyChangeListener { + private ViewGroup.OnHierarchyChangeListener mOnHierarchyChangeListener; + + public void onChildViewAdded(View parent, View child) { + if (parent == StrongRadioGroup.this && child instanceof RadioButton) { + int id = child.getId(); + // generates an id if it's missing + if (id == View.NO_ID) { + id = child.hashCode(); + child.setId(id); + } + ((RadioButton) child) + .setOnCheckedChangeListener(mChildOnCheckedChangeListener); + } else if (parent == StrongRadioGroup.this && child instanceof ViewGroup) { + //添加部分 + RadioButton btn = findRadioButton((ViewGroup) child); + int id = btn.getId(); + // generates an id if it's missing + if (id == View.NO_ID) { + id = btn.hashCode(); + btn.setId(id); + } + btn.setOnCheckedChangeListener(mChildOnCheckedChangeListener); + } + + if (mOnHierarchyChangeListener != null) { + mOnHierarchyChangeListener.onChildViewAdded(parent, child); + } + } + + public void onChildViewRemoved(View parent, View child) { + if (parent == StrongRadioGroup.this && child instanceof RadioButton) { + ((RadioButton) child).setOnCheckedChangeListener(null); + } else if (parent == StrongRadioGroup.this && child instanceof ViewGroup) { + //添加部分 + findRadioButton((ViewGroup) child).setOnCheckedChangeListener( + null); + } + if (mOnHierarchyChangeListener != null) { + mOnHierarchyChangeListener.onChildViewRemoved(parent, child); + } + } + } +} diff --git a/common_base/src/main/res/drawable-xhdpi/popup_icon_close.png b/common_base/src/main/res/drawable-xhdpi/popup_icon_close.png new file mode 100644 index 0000000000000000000000000000000000000000..220beb4a888edc40f7f9679dad4c19d663634af4 GIT binary patch literal 498 zcmVPx$tVu*cR9Fe^m+NhWFc5@~a2=$G^pKPQRoo?2-J=Q+6_6HEMM^+q2YHcYVRpTs zib|5>D9S|Mpy6&ZEnpd%*vH`T9scHTsHG^` zPOJk>XmdH1i+~8Ms_KIT?<|r68G*Y)ll9he^?X|C=$+ulrA{m{p^h35fhirPv<;#B zauT2xaxXaamkcODqTVece?ef*MW+H{V#x#uv6xG)ZWlOcnE@RL?`<;>-gCmrw>md# z@Pjp9auQm5z(Gf~52E33rN2AGOGC@24b{zaa_dkZEkhTB!-9YwZ8KQq6C`q1e#|zr z21jm9N1mpQ)|jL@n9^}d+cj7d3S*F)!U|68=wK zLbsO6qJy~L5M0l})@>u=Px&PDw;TRA>e5noWp}VHAMp$BZ%K-$V#SQARQODHbTPzygbD6j@BHWJMMd3!)?o znGH533oIB33zR4n3WZ`pDS!D(=8vmq*}=P)ULLuG)_ zHZe2eDY*%1YWzclb{V3QdJJRZH&g})?GrO29*`TQrp7%)rWy_!qLR7`&2by5?vbg1 z!(hcNlEc*WxQEEp!ZFK~+;tcnx1s7DnSO8rthholo&Rx>sfW{+DY=UgH9$-LB@tT#)}6*TFiV}=_bT3=SZIPx%9!W$&R9Fe^m`y~bVHC%E`ICsMRteC9oHgduDF4%2(weQU(Vg^~msD6>7DN zNCg~;8T}r>y85UGL_kh*2~q6)QIMx+|f#EgCo4OaQ897Jm19Hg!o>Q$ju%ZL=i zrI^t#pw=p1or6qgNY0Ht>QKu7gg(QmGmF;^z0vXvbrwREa2ywO?GC=GgDnFPDu+Xm zdSGa=JVTv@P$}$#)DuIiI@mG*A@{D{6+^oF8{BSrhB^zOLf8Q*_Ytd09c&qZP(Eyl zA>B##TArcKLMRtDAzc0HV9Nl^a$r4d$UJCyhB^zOELimPx$XGugsR9FdPWS|hJsHjH+jp%|JQ+DUh&83tW$w-N2Jv}|KZ{L1C{{R0!8^|0+ zM#f)UTuDML)Y6R)~{{6QG%rPK7hz$}0vB?D#ISA+g4E@-|NO2s7fuv}r zh1yXE5en7O5E>03LLop%el!h@h7h3;ASBNMQUI#8p%o>GY3jcLrUm~ER8&Z-UxBTJ zf1I4GH$bffMreCx9&)XXX$kE`Kus5*ElD5;Jq0>OiuP6#wgKp!u#_ZfV08B*y98)(A+Rxf0a=U?8>k17s0k^?ClAa`4*&oE+mEb< zk&(&q&Yc?vki|%056Uz|iU(+}b~J3R9`7pm@&p>(@@eJ;k(9d z7W>5&tSpO@OgdIbxg6NU$~WO=fnyGj&?AP30>;x~0&Jp5H+T-Ku`&FL*ArQ?@IJ`b N44$rjF6*2UngFd;WQ70# diff --git a/common_base/src/main/res/drawable-xxhdpi/input_add_disabled.png b/common_base/src/main/res/drawable-xxhdpi/input_add_disabled.png index dd67fb78726ad071302d627feedfec651b3b2133..cee60c96edd36a24648b3b38b884331341a98fbf 100644 GIT binary patch literal 388 zcmV-~0ek+5P)Px$K1oDDR9Fe^SWOCoP!R5Abc7Z``*!LL>KyI5K^qUzrW>^D9CZV8*FJL55dyRM z!k}L2sDmLi!2{>_eSS>Lho&d|g<-g$7VE4{;QRhg($YwZqbM4sX?mtJL?2_!jn2e% z-D}gn{icN(fawbiY&;X7sida}P?98H^?ANJ0KXd6DQ+WI0dcGG!)^C$+hSlPO3ip?xOX z7KU?eoevjvZey6v*mA^OS3$&yXR)J;L5GB+rO1@R4v*V>4wv67RFh-5#J(VBjfk-D zWq*aZqZR-D{JiZTx`^(5jGi8E=St94K$=1vR*HICC$sr>sZs&@XXO9 z>tKeA01smmSBIbLf=#SxQby8hZQW`|n?fC&-!&Ml5ICHwu*-tssgPCrR-yNSK>sj! My85}Sb4q9e02_r|XaE2J diff --git a/common_base/src/main/res/drawable-xxhdpi/input_minus_default.png b/common_base/src/main/res/drawable-xxhdpi/input_minus_default.png index 753174d19826c0d7c6749de11e4ec7d23aacbe3c..1f8d10029f6768a4b6b674a3570ab668e561df70 100644 GIT binary patch literal 181 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|l3?zm1T2})p#^NA%Cx&(BWL^R}asfUet{@dE zTFT05Dk?yv0Y+*-E(CG;a})tpaFzu51v3~1)HU>7c>izK7t3ovK?6@0#}JM4$q5py zI~pUN`-m7QPgE>clbUfXpi|FeuA)$Eh8FYWPHwJ(FbUrHOAHKePwRf2%>OSDsF%Uh L)z4*}Q$iB}oscef literal 138 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaN3?zjj6;1;w#^NA%Cx&(BWL^R}`~f~8u0UEv zMNLIT9f*{b)x3?8=L3aUN`m}?8CpO8TtC;{9LSgSba4!kxSX6IQK0aKiM@?Si=$6? d)tLuO3`-|-Jb#pFv>vF4!PC{xWt~$(699h5A>;r6 diff --git a/common_base/src/main/res/drawable-xxhdpi/input_minus_disabled.png b/common_base/src/main/res/drawable-xxhdpi/input_minus_disabled.png index 7b18444686adf7a37b88d29d3e3edca7e580f679..525e156480398c44f9a74c6074aec8e9bd0303f0 100644 GIT binary patch literal 204 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k1|%Oc%$NbB7>k44ofy`glX(f`w0XKXhD30_ zowSj+!GMRQP%M#of_WmV+G(yFp~DU{%oq8*4cH^??N_+|w7+mWTSfyE1@U&wT)8`3 zFmi+H)PDyLu-(#s6C0J?_S;IyqrFmW$t-JrXTOO{8)Dio{J!w3jP3q5#n=)Jre*v$ p%1b;#`%5euO&pk^=z}pc|My1<86S6sn*&|M;OXk;vd$@?2>_*mML_@n literal 155 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjjKx9jP7LeL$-D$|LOop^Lp*qs z6C_v{D;h{KIoq>HoS$!h|I~>S5ug75uQ$u8V$XP{zhI_qkGNjU51y0{0hbGAL^^oy zGhpPM&$5YE%|ln}RkP<6qx>s#E(%ESHYUn4F}!hPx%rAb6VRA>e5n!Qc}K@^2uH6{j$1y2JVJ(bZyOB!S2!)Re_EVaN`(bK`xP#7U5 zM!|awLxw?M=I*`YPwpmWc6H{S^PSnB*{oYzwpjv}fF)oFSOS)SC143y0+vA51g6vJ zPQTyZ&nik{(1bQux8MxycDqM3?v8}3MN!;VDwWG-v-!@c6+5Qa>+O!m<15lUC(Rcc z*KW01PqE`&ziqb@+s@Jj>>-WWruKr2+`~|8jnsZK*n4QrG@%U-$upe{JQxi2NT}+Y zrsESWXb<)z(5%9X|GSv|WZ*`l@ru(pEUp2)3KrV%0574BO~=W=D2Qv81Uq4IN$3r* z9e4=!V~$xjEfkJ0bjH1rY1U=~Ye8$m!gDELX=rU&5nw6k9I#@*WubGyiUMim%dAf1>Nz6*?UAkf<1QqU8@NT4K-jC zUk8o9hnqGm^i+W%5DT3HHVd!^{qWr>{AHpj9_gArbFN5IZkP$_-GV7SMkz#IV17%nWvi2;`}US@16ya=#_VTl?s@TGwzjY`&91z!qS z!=Oe@AD#`YX-u;=3s}>Tn++`u*1}^n8eL<7;LN#Ja%qS+Ct94Gty!F0Io*^td4}Px&PDw;TRA>e5noWp}VHAMp$BZ%K-$V#SQARQODHbTPzygbD6j@BHWJMMd3!)?o znGH533oIB33zR4n3WZ`pDS!D(=8vmq*}=P)ULLuG)_ zHZe2eDY*%1YWzclb{V3QdJJRZH&g})?GrO29*`TQrp7%)rWy_!qLR7`&2by5?vbg1 z!(hcNlEc*WxQEEp!ZFK~+;tcnx1s7DnSO8rthholo&Rx>sfW{+DY=UgH9$-LB@tT#)}6*TFiV}=_bT3=SZIv_J*b>H`AyZ?IPEzM0hSkJLCFfeeyO%1J&*Px&8 znbXH#u_xELj~8K*kpsyF?@0qXZV|KypBs zX?fsr3aFnL1u~9s%w}NF(IXR39zGZnz#VfP>jwjFzGwpiuxJ?2UKOE;AQ)i0u%LksddEJT%cjJzanfS?gE;hasT=WSp-bQHu-%{-vvRy#IL(0RsMlkbGdk|0Lyr zuml+3126zp1yy+uMW_luT~h(73RTg7f&og3P-TdsG6bqD4^`4q)YO8i0{(u0$I$}N zo?6z1#(&2;KEZ%qBoaXj0tpTdRtQ#Bzz1B1Ks7ZrA&N>6B_;V|gglYrM?#V1{fLsk z6bvy$j{q!zgvI*-ek!8e@qr{5@Ho@|lz=1rBkM=}yG_RpgOE`K2vkAwXGy<+2*m#n z#o_)z6G_&X|K|ID3KNkO0tRA@A>soAJdOwFDfu%LLCYWjgCgMrka)cBuP$18;YoO+ z7oGqxFaUt;v3_WLFj3|&I0B&s_al-}ejXUOAq;pdpn%1qwe*cu)r^#s3{?zOjG<5? z)l0_uM*7B3HGLy>RYiR@jbB_tyhk7o<45|%MgNy;^sn5XPQVe4BO77@ut6BKaR43% z_^V>^=L$OE+Q!7!k=v~uKTlu zd}-Ow&z-_AC`V09!S+M=)68kpe9n2s4)}h1@m52$B>$A$?Ul-k8F=D#wO}t#VuAUe|ahY;%;H?)YMv$v7TD|R*^2f7vwFFU6GpAr3&-jzA1Oi>q z@gdLn_n-aFSh^^x9dV$(KpBBmLAWu=bM+ zZQ085!y@XHiZ!OYdFdTM=g*uw(pP?uhC1%LWP5kmCB!Dxsa!tiVI*$%6zCg6n1fW- z!iASQ_hmTBdXX{mmX{S&+|I(_UOncqDVYHEP zM{Qqp33XybTQ82a8gXEz)fFldYzInfn(gUDvmGu9PAomnXCnERA$ZlI|13XoNS}XV z6zAlH_jw6!h-$qV89DK2yi@0m;WrFzpXMH!r|GETW6A9@EqTazehJ`2pkKK;F=>Vq zd(0(R-W(aprZ2;mn4XNF5ov@)Oug^na3#;Vt3qv1r?*Q_mg^8BH#+!MHr(v2D(f{% zG=uIr8unvCK95kkS>jpm$o3X}U{_E|G||X9NJQpcTuaQx-h(fF|89P+cgI_)F`@s< z$TcQU>Zq`OZgEUl`pD!p3I2sKz8Ls?J6)KLHm@eGsb{bDe^ktKNi~4jW?G@lKRrIA zY=rI+Qs@S=1&sIJw5Y!~R!TRQnt(E&|ipUYzm)P~8zkG*&zkhwG zt)(VdB1x`K*+AVa#onQDIK#G0L_mw~tQH#@gn& zN}s@-_bR?t(7}%@_fuz0gmx=2!ybzQKK?#ZZv4wAf$}O?6Jzvzmq~C_NgJehepB;F zmaq4V6#CYChmMXfQ)Rm@go}D_3hh4inhXsG`n_AgrmWuB9Qn4C86`jT!M?kaJ>etg zqdcU8=vm80?tM@#=pszJI9dU8uP3K3x!(JY6)>x<$G~|CH}t_`h8p^c;Ub4W$mg|e zbkGoiS-TpKEbCsPtt5mVs`cbMFejhZFc_{^k*Zrrq}F;GPRKYGn2s;wp3L`z);Nd$W}T5bsfc_spM9weE;z-m~NOU z&+8;sLdE=}VxCF}Ju@K{@)cj-{ zNC@Yj55&^9*SJb}5TTzw5AUugVO_qYNq5N=aaYJHW}ycdcy$#X5-vY(;}-kO6UVpxDrzZq4?LStq}#7K zI9P1NkyxQA=_=AYn0_{ITP@DC?a=!EoM4q6<+7=RD8D*j_yd_qZx7@WA7lBfG16p_ zyRC_0rBje0yHi(4b%3g!@14{oVtiN5Fq-4U&Y;q=e5J&ARxEa!Z;9Eq%(qdrc={orI<8#Q*qw0@D9s_`&kRM`76rgs8ceE&TN#=3Kz39ZJ-_G^pe| zsvNgpL@7P1=PaR^j*HgCsDGWEAvcmVLu67~{&0^MyxM6|?P#=qCkcVu6^HY*DOoh| zeXR6_E!Y8aa#4|oh0%b%?UlwAjWZpbBXhZ26|bA$B_`lpjFF%GE?$1B#ksn8=1Wv1 zZ11qXKmT=EmB<@#0a1+VqCbue6CH8oIUOc&K{acml)d8%eRVQ*Dmx9N5yz z!9qaFz20I}^N8PgVa2q+D_ip*^99YwfSRlk1{T=O87 zuirgCuVIpRv_>Tn{@q`Xc`x%5&PC_);s}KuD;OOpvfVxI9&tA-8}T_t^yUX1Oxy<> z@YBAmZb1t*;oVj>q1m2ssgR;9bY=_s8PnWMMs{<<_a zYQ0YtuIiBMZR9rNqdjy+Y2`$b2_0P5dDUvB=T-3U8VT@NkHU8Xi7XfjDGU>iyfQN4 z=VkSh`;0Rl%~qQ{zAW8PEcwxJx*`>B3?G0n_cF$p#5vcU)Qej)^v@>N@OzXq&-0VWGp z80?}I$v#Q4rj&E0bCGdujS)=yxpVVprGPoQXP#gr1=>m_qLS;T2gDMqM@;*I^t2}* z@i(l0K3#er=B)j7jz>T_&zX0idXX*?k8O6BH>m|K%d|Hi??*0WxqxVy7ME6 zDJ8%;Kw32O2ch__T0Qn!D6??>&VyLTXFEUcjs{g=TH&W#1l_)0JIev04L&GD>pzC% zOsZN4n$s6IYzEY#ZFZ;LdzO><-uCnoiZ1)U^P`dnJ0H{Dsp>yaR7;kRG1xURk~ z_{3_*y}7zrP}aigk<*k~#0a&L$Xepo*9hc*kZ--7(?llBr#^Zbu$*RBWYn#EM-cYR z0_ot!%{1^pon2$XS1F{dh&op_6m`y{c%O^tw_S^oQn_?SwL-?C$gvQ2Y8z19v)T52Yi(Sw#?Cr zYl5a;?pon9dk!o-Nt7`T#5O+{o;KsYcEY`#YpwX>BOjSIPd>q~5;E4kXbXw z-8jrOyl+{ba4;6x+UUFs!(4W7Lj|9WAiWx<&LIp%vbXgigLWa_jVr%Fv%%^i=;&E3yXs1V z+G+4{zs9?Q4?&WzNz`dOi4C3V&s3>HhOh{5|6=wL5VitJ;|u?-aeMMbRq3RW!&ipx zG?02!rNq&F&Gds8ByHA&BBLqgjj+sXu1|yKmGeg?XcBxho0%%&#GXRigu4TkVrcI(1596;vkJ8$N0HO4__^T$LcvJAcRcNwk~ zki~a`JWJrGjF?+#p~-w&a646$!EZBDd$h@{x2ZR@xfNYoyN@n1Wz6V~YFXN%I<3HF zB0=8~Qc=lP1#YjH7C|UMVDdE9nmSAa_+Ed=fa=s(ATNOam`Y4q?b3^opt=E`t_zNQp<%L11s@;DaBfqYVRT6N7~6TbaHIBhUeLMmXNR}%#Qb1W aWLRxkS{}P;(*N@}6x_(%utMK0@_ztU708$X diff --git a/common_base/src/main/res/drawable-xxxhdpi/input_add_default.png b/common_base/src/main/res/drawable-xxxhdpi/input_add_default.png deleted file mode 100644 index 34fa1464300807a0ebf2d4eba7591877aee718c7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 429 zcmV;e0aE^nP)Px$XGugsR9FdPWS|hJsHjH+jp%|JQ+DUh&83tW$w-N2Jv}|KZ{L1C{{R0!8^|0+ zM#f)UTuDML)Y6R)~{{6QG%rPK7hz$}0vB?D#ISA+g4E@-|NO2s7fuv}r zh1yXE5en7O5E>03LLop%el!h@h7h3;ASBNMQUI#8p%o>GY3jcLrUm~ER8&Z-UxBTJ zf1I4GH$bffMreCx9&)XXX$kE`Kus5*ElD5;Jq0>OiuP6#wgKp!u#_ZfV08B*y98)(A+Rxf0a=U?8>k17s0k^?ClAa`4*&oE+mEb< zk&(&q&Yc?vki|%056Uz|iU(+}b~J3R9`7pm@&p>(@@ePx$K1oDDR9Fe^SWOCoP!R5Abc7Z``*!LL>KyI5K^qUzrW>^D9CZV8*FJL55dyRM z!k}L2sDmLi!2{>_eSS>Lho&d|g<-g$7VE4{;QRhg($YwZqbM4sX?mtJL?2_!jn2e% z-D}gn{icN(fawbiY&;X7sida}P?98H^?ANJ0KXd6DQ+WI0dcG|l3?zm1T2})p#^NA%Cx&(BWL^R}asfUet{@dE zTFT05Dk?yv0Y+*-E(CG;a})tpaFzu51v3~1)HU>7c>izK7t3ovK?6@0#}JM4$q5py zI~pUN`-m7QPgE>clbUfXpi|FeuA)$Eh8FYWPHwJ(FbUrHOAHKePwRf2%>OSDsF%Uh L)z4*}Q$iB}oscef diff --git a/common_base/src/main/res/drawable-xxxhdpi/input_minus_disabled.png b/common_base/src/main/res/drawable-xxxhdpi/input_minus_disabled.png deleted file mode 100644 index 525e156480398c44f9a74c6074aec8e9bd0303f0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 204 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k1|%Oc%$NbB7>k44ofy`glX(f`w0XKXhD30_ zowSj+!GMRQP%M#of_WmV+G(yFp~DU{%oq8*4cH^??N_+|w7+mWTSfyE1@U&wT)8`3 zFmi+H)PDyLu-(#s6C0J?_S;IyqrFmW$t-JrXTOO{8)Dio{J!w3jP3q5#n=)Jre*v$ p%1b;#`%5euO&pk^=z}pc|My1<86S6sn*&|M;OXk;vd$@?2>_*mML_@n diff --git a/module_market/src/main/res/drawable/market_shape_round_red.xml b/common_base/src/main/res/drawable/market_shape_round_red.xml similarity index 100% rename from module_market/src/main/res/drawable/market_shape_round_red.xml rename to common_base/src/main/res/drawable/market_shape_round_red.xml diff --git a/common_base/src/main/res/values/colors.xml b/common_base/src/main/res/values/colors.xml index b26bb20..325e36f 100644 --- a/common_base/src/main/res/values/colors.xml +++ b/common_base/src/main/res/values/colors.xml @@ -5,7 +5,7 @@ #00000000 #FFFFFF #BBBBBB - #DC143C + #FF0000 #0099FF #000000 #FFA82E diff --git a/module_main/src/main/AndroidManifest.xml b/module_main/src/main/AndroidManifest.xml index 6acc797..045e9df 100644 --- a/module_main/src/main/AndroidManifest.xml +++ b/module_main/src/main/AndroidManifest.xml @@ -1,6 +1,7 @@ + @@ -26,5 +27,7 @@ + + diff --git a/module_main/src/main/java/com/wss/module/main/ui/main/MainActivity.java b/module_main/src/main/java/com/wss/module/main/ui/main/MainActivity.java index c5ad7bb..41bce46 100644 --- a/module_main/src/main/java/com/wss/module/main/ui/main/MainActivity.java +++ b/module_main/src/main/java/com/wss/module/main/ui/main/MainActivity.java @@ -88,6 +88,7 @@ public void onCheckedChanged(RadioGroup group, @IdRes int checkedId) { presenter.checkUpdate(); } presenter.getTabList(); + } diff --git a/module_main/src/main/java/com/wss/module/main/ui/main/mvp/MainPresenter.java b/module_main/src/main/java/com/wss/module/main/ui/main/mvp/MainPresenter.java index bb0607b..074bc25 100644 --- a/module_main/src/main/java/com/wss/module/main/ui/main/mvp/MainPresenter.java +++ b/module_main/src/main/java/com/wss/module/main/ui/main/mvp/MainPresenter.java @@ -15,7 +15,9 @@ import com.wss.module.main.ui.page.FlowLayoutActivity; import com.wss.module.main.ui.page.MultipleItemActivity; import com.wss.module.main.ui.page.ObserverButtonActivity; +import com.wss.module.main.ui.page.RadioGroupActivity; import com.wss.module.main.ui.page.ScaleImageActivity; +import com.wss.module.main.ui.page.YumanmanActivity; import com.wss.module.main.ui.refresh.RefreshStringActivity; import com.wss.module.main.ui.selector.SelectorActivity; @@ -80,6 +82,8 @@ public void getTabList() { list.add(new Template("流式布局", R.drawable.main_icon_15, FlowLayoutActivity.class, "流式布局,从左上角位置开始,自动换行")); list.add(new Template("聊天", R.drawable.main_icon_16, IMActivity.class, "聊天布局样式,用于测试多功能列表适配器")); list.add(new Template("图片查看器", R.drawable.main_icon_18, ScaleImageActivity.class, "大图查看器、支持下载、删除、缩放等操作")); + list.add(new Template("于慢慢计算器", R.drawable.main_icon_19, YumanmanActivity.class, "某一个初始值递增某次计算结果")); + list.add(new Template("自定义RadioGroup", R.drawable.main_icon_20, RadioGroupActivity.class, "自定义RadioGroup")); getView().tabList(list); } } diff --git a/module_main/src/main/java/com/wss/module/main/ui/page/DialogActivity.java b/module_main/src/main/java/com/wss/module/main/ui/page/DialogActivity.java index 3a1fe5b..07ae005 100644 --- a/module_main/src/main/java/com/wss/module/main/ui/page/DialogActivity.java +++ b/module_main/src/main/java/com/wss/module/main/ui/page/DialogActivity.java @@ -60,6 +60,7 @@ public void onBtnClick(View view) { new AppDialog(mContext) .setContent("我的自定义默认对话框") .show(); + } else if (view.getId() == R.id.btn_02) { new AppDialog(mContext, DialogType.INPUT) .setTitle("来一段文字") @@ -112,16 +113,17 @@ public void onItemClick(int position) { .show(); } else if (view.getId() == R.id.btn_07) { - View progressView = View.inflate(mContext, R.layout.update_progress_layout, null); - progressBar = progressView.findViewById(R.id.number_progress); - progressDialog = new AppDialog(mContext); - mProgress = 0; - progressBar.setProgress(mProgress); - - progressDialog.setTitle("更新") - .addDialogView(progressView) - .show(); - update(); +// View progressView = View.inflate(mContext, R.layout.update_progress_layout, null); +// progressBar = progressView.findViewById(R.id.number_progress); +// progressDialog = new AppDialog(mContext); +// mProgress = 0; +// progressBar.setProgress(mProgress); +// +// progressDialog.setTitle("更新") +// .addDialogView(progressView) +// .show(); +// update(); + } } diff --git a/module_main/src/main/java/com/wss/module/main/ui/page/RadioGroupActivity.java b/module_main/src/main/java/com/wss/module/main/ui/page/RadioGroupActivity.java new file mode 100644 index 0000000..e502940 --- /dev/null +++ b/module_main/src/main/java/com/wss/module/main/ui/page/RadioGroupActivity.java @@ -0,0 +1,48 @@ +package com.wss.module.main.ui.page; + +import android.widget.TextView; + +import com.wss.common.base.ActionBarActivity; +import com.wss.common.base.mvp.BasePresenter; +import com.wss.common.widget.StrongRadioGroup; +import com.wss.module.main.R; +import com.wss.module.main.R2; + +import butterknife.BindView; + +/** + * Describe: + * Created by 吴天强 on 2019/3/18. + */ + +public class RadioGroupActivity extends ActionBarActivity { + + + @BindView(R2.id.mg) + StrongRadioGroup mainTab; + + @BindView(R2.id.tv_count) + TextView tvCount; + + + @Override + protected BasePresenter createPresenter() { + return null; + } + + @Override + protected int getLayoutId() { + return R.layout.main_activity_radio_group; + } + + @Override + protected void initView() { + setTitleText("自定义RadioGroup"); + mainTab.setOnCheckedChangeListener(new StrongRadioGroup.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(StrongRadioGroup group, int checkedId) { + + } + }); //检查文件权限 + } +} diff --git a/module_main/src/main/java/com/wss/module/main/ui/page/YumanmanActivity.java b/module_main/src/main/java/com/wss/module/main/ui/page/YumanmanActivity.java new file mode 100644 index 0000000..69fb72d --- /dev/null +++ b/module_main/src/main/java/com/wss/module/main/ui/page/YumanmanActivity.java @@ -0,0 +1,196 @@ +package com.wss.module.main.ui.page; + +import android.annotation.SuppressLint; +import android.content.ClipData; +import android.content.ClipboardManager; +import android.content.Context; +import android.os.Handler; +import android.os.Message; +import android.view.View; +import android.widget.EditText; +import android.widget.TextView; + +import com.wss.common.base.ActionBarActivity; +import com.wss.common.base.mvp.BasePresenter; +import com.wss.common.utils.MoneyUtils; +import com.wss.common.utils.ToastUtils; +import com.wss.common.widget.ObserverButton; +import com.wss.module.main.R; +import com.wss.module.main.R2; + +import butterknife.BindView; +import butterknife.OnClick; + +/** + * Describe:于慢慢牌计算器 + * Created by 吴天强 on 2019/3/12. + */ + +public class YumanmanActivity extends ActionBarActivity { + + @BindView(R2.id.edt_initial_value) + EditText edtInitialValue; + + @BindView(R2.id.edt_count_value) + EditText edtCountValue; + + @BindView(R2.id.edt_increment_value) + EditText edtIncrementValue; + + @BindView(R2.id.tv_result) + TextView tvResult; + + @BindView(R2.id.tv_result_detail) + TextView tvResultDetail; + + @BindView(R2.id.ob_btn) + ObserverButton button; + + @BindView(R2.id.root) + View root; + + @BindView(R2.id.values) + View values; + + + //设置一个默认值 + private int recordVisibleRec = 0; + + @Override + protected BasePresenter createPresenter() { + return null; + } + + @Override + protected int getLayoutId() { + return R.layout.main_activity_yumanman; + } + + @Override + protected void initView() { + setTitleText("于慢慢计算器"); + button.observer(edtInitialValue, edtIncrementValue, edtCountValue); + } + + + @OnClick({R2.id.ob_btn, R2.id.tv_result}) + public void addValue(View v) { + if (v.getId() == R.id.ob_btn) { + Double a = Double.valueOf(edtInitialValue.getText().toString().trim()); + Integer b = Integer.valueOf(edtCountValue.getText().toString().trim()); + Double c = Double.valueOf(edtIncrementValue.getText().toString().trim()); + add(new Bean(a, b, c)); + } else { + ClipboardManager cm = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE); + cm.setPrimaryClip(ClipData.newPlainText(null, ((TextView) v).getText())); + ToastUtils.showToast(mContext, "结果已复制到粘贴板"); + } + } + + private void add(final Bean bean) { + showLoading("正在疯狂计算···"); + new Thread(new Runnable() { + @Override + public void run() { + double a = bean.getA(); + int b = bean.getB(); + double c = bean.getC(); + double sum = a; + StringBuilder sb = new StringBuilder(); + String str; + if (b > 1) { + for (int i = 0; i < b; i++) { + sb.append(a); + sb.append("+"); + a = Double.valueOf(MoneyUtils.Algorithm.add(a, c)); + sum = Double.valueOf(MoneyUtils.Algorithm.add(sum, a)); + } + str = sb.toString(); + str = str.substring(0, str.length() - 1); + } else { + str = String.valueOf(a); + } + Message message = handler.obtainMessage(); + message.obj = new Bean(sum, str); + handler.sendMessage(message); + } + + }).start(); + } + + @SuppressLint("HandlerLeak") + private Handler handler = new Handler() { + @Override + public void handleMessage(Message msg) { + super.handleMessage(msg); + Bean bean = (Bean) msg.obj; + tvResult.setText(String.format("计算结果:%s", bean.getSum())); + tvResultDetail.setText(String.format("计算详情:%s", bean.getStr())); + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + dismissLoading(); + } + }, 500); + } + }; + + private class Bean { + double a; + int b; + double c; + double sum; + String str; + + public Bean(double sum, String str) { + this.sum = sum; + this.str = str; + } + + public double getSum() { + return sum; + } + + public void setSum(double sum) { + this.sum = sum; + } + + public String getStr() { + return str; + } + + public void setStr(String str) { + this.str = str; + } + + Bean(double a, int b, double c) { + this.a = a; + this.b = b; + this.c = c; + } + + public double getA() { + return a; + } + + public void setA(double a) { + this.a = a; + } + + public int getB() { + return b; + } + + public void setB(int b) { + this.b = b; + } + + public double getC() { + return c; + } + + public void setC(double c) { + this.c = c; + } + } +} diff --git a/module_main/src/main/res/layout/main_activity_radio_group.xml b/module_main/src/main/res/layout/main_activity_radio_group.xml new file mode 100644 index 0000000..fad34a0 --- /dev/null +++ b/module_main/src/main/res/layout/main_activity_radio_group.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/module_main/src/main/res/layout/main_activity_scale_image.xml b/module_main/src/main/res/layout/main_activity_scale_image.xml index c31337f..0c3e47f 100644 --- a/module_main/src/main/res/layout/main_activity_scale_image.xml +++ b/module_main/src/main/res/layout/main_activity_scale_image.xml @@ -11,5 +11,9 @@ android:layout_height="45dp" android:layout_marginTop="10dp" android:text="图片查看" /> + diff --git a/module_main/src/main/res/layout/main_activity_yumanman.xml b/module_main/src/main/res/layout/main_activity_yumanman.xml new file mode 100644 index 0000000..91f35a9 --- /dev/null +++ b/module_main/src/main/res/layout/main_activity_yumanman.xml @@ -0,0 +1,148 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/module_market/src/main/assets/html/goods_detail.html b/module_market/src/main/assets/html/goods_detail.html new file mode 100644 index 0000000..2a678af --- /dev/null +++ b/module_market/src/main/assets/html/goods_detail.html @@ -0,0 +1,83 @@ + + + + + + + + + + 商品详情 + + + + + +
+
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+
+ + + + + \ No newline at end of file diff --git a/module_market/src/main/java/com/wss/module/market/ui/goods/detail/GoodsDetailActivity.java b/module_market/src/main/java/com/wss/module/market/ui/goods/detail/GoodsDetailActivity.java index 5d816eb..824e1f1 100644 --- a/module_market/src/main/java/com/wss/module/market/ui/goods/detail/GoodsDetailActivity.java +++ b/module_market/src/main/java/com/wss/module/market/ui/goods/detail/GoodsDetailActivity.java @@ -1,7 +1,9 @@ package com.wss.module.market.ui.goods.detail; +import android.os.Handler; import android.text.TextUtils; import android.view.View; +import android.widget.ImageView; import android.widget.TextView; import com.wss.common.adapter.FragmentPagerAdapter; @@ -48,6 +50,9 @@ public class GoodsDetailActivity extends BaseActivity { @BindView(R2.id.tv_count) TextView tvCount;//购物车数量 + @BindView(R2.id.iv_cart) + ImageView ivCart;//购物车 + //TODO 测试使用列表造的伪数据表示不同商品做加入购物车操作 private GoodsInfo goodsInfo; @@ -128,11 +133,28 @@ public void onViewClicked(View view) { } else if (i == R.id.tv_add_cart) { //加入购物车 if (goodsInfo != null) { - goodsInfo.setNum(goodsInfoMainFragment.getGoodsCount()); - ShoppingCartUtils.addCartGoods(goodsInfo); - EventBusUtils.sendEvent(new Event(EventAction.EVENT_SHOPPING_CART_REFRESH)); - }else { - ToastUtils.showToast(mContext,"没有正经的商品信息~"); + final long time = 500; + ivCart.animate() + .scaleX(1.3f) + .scaleY(1.3f) + .setDuration(time) + .start(); + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + goodsInfo.setNum(goodsInfoMainFragment.getGoodsCount()); + ShoppingCartUtils.addCartGoods(goodsInfo); + EventBusUtils.sendEvent(new Event(EventAction.EVENT_SHOPPING_CART_REFRESH)); + ivCart.animate() + .scaleX(1.0f) + .scaleY(1.0f) + .setDuration(time) + .start(); + } + }, time * 2 ); + + } else { + ToastUtils.showToast(mContext, "没有正经的商品信息~"); } } else if (i == R.id.tv_buy_now) { //立即购买 diff --git a/module_market/src/main/java/com/wss/module/market/ui/goods/detail/fragment/GoodsInfoMainFragment.java b/module_market/src/main/java/com/wss/module/market/ui/goods/detail/fragment/GoodsInfoMainFragment.java index 3210eff..b9f50a0 100644 --- a/module_market/src/main/java/com/wss/module/market/ui/goods/detail/fragment/GoodsInfoMainFragment.java +++ b/module_market/src/main/java/com/wss/module/market/ui/goods/detail/fragment/GoodsInfoMainFragment.java @@ -22,6 +22,7 @@ import com.wss.module.market.ui.goods.detail.GoodsDetailActivity; import com.wss.module.market.ui.goods.detail.adapter.GoodsCommentAdapter; import com.wss.module.market.ui.goods.detail.adapter.RecommendGoodsAdapter; +import com.wss.module.market.ui.goods.detail.helper.GoodsSpecificationPop; import com.wss.module.market.ui.goods.detail.mvp.GoodsDetailPresenter; import com.wss.module.market.ui.goods.detail.mvp.contract.GoodsDetailContract; @@ -100,13 +101,17 @@ protected void initView() { } - @OnClick({R2.id.ll_pull_up, R2.id.ll_comment}) + @OnClick({R2.id.ll_pull_up, R2.id.ll_comment, R2.id.miv_goods_specification}) public void onClick(View v) { - if (v.getId() == R.id.ll_pull_up) {//上拉查看图文详情 + if (v.getId() == R.id.ll_pull_up) { + //上拉查看图文详情 svSwitch.smoothOpen(true); } else if (v.getId() == R.id.ll_comment) { //查看评论 goodsDetailActivity.setCurrentFragment(2); + } else if (v.getId() == R.id.miv_goods_specification) { + //选择商品规格 + GoodsSpecificationPop.getInstance(mContext).show(v); } } diff --git a/module_market/src/main/java/com/wss/module/market/ui/goods/detail/fragment/child/GoodsConfigFragment.java b/module_market/src/main/java/com/wss/module/market/ui/goods/detail/fragment/child/GoodsConfigFragment.java index f1093ff..1899300 100644 --- a/module_market/src/main/java/com/wss/module/market/ui/goods/detail/fragment/child/GoodsConfigFragment.java +++ b/module_market/src/main/java/com/wss/module/market/ui/goods/detail/fragment/child/GoodsConfigFragment.java @@ -31,8 +31,20 @@ protected int getLayoutId() { protected void initView() { listView.setFocusable(false); List data = new ArrayList<>(); - data.add(new GoodsConfigBean("品牌", "小米Mix 3")); - data.add(new GoodsConfigBean("型号", "全面屏 小米Mix 3")); + data.add(new GoodsConfigBean("品牌", "小米(MI)")); + data.add(new GoodsConfigBean("型号", "小米MIX3")); + data.add(new GoodsConfigBean("入网型号", "以官网信息为准")); + data.add(new GoodsConfigBean("上市时间", "2018年10月")); + data.add(new GoodsConfigBean("操作系统", "Android")); + data.add(new GoodsConfigBean("CPU", "骁龙845 八核")); + data.add(new GoodsConfigBean("ROM", "128GB")); + data.add(new GoodsConfigBean("RAM", "8GM")); + data.add(new GoodsConfigBean("网络支持", "2G/3G/4G")); + data.add(new GoodsConfigBean("屏幕尺寸", "3.98英寸")); + data.add(new GoodsConfigBean("分辨率", "2340*1080")); + data.add(new GoodsConfigBean("摄像头", "2400万+2000万像素")); + data.add(new GoodsConfigBean("电池容量(mAh)", "3200mAh (typ)/ 3100mAh (min)")); + data.add(new GoodsConfigBean("数据接口", "蓝牙/NFC")); listView.setAdapter(new GoodsConfigAdapter(mContext, data, R.layout.market_item_of_goods_config_list)); } diff --git a/module_market/src/main/java/com/wss/module/market/ui/goods/detail/fragment/child/GoodsInfoWebFragment.java b/module_market/src/main/java/com/wss/module/market/ui/goods/detail/fragment/child/GoodsInfoWebFragment.java index 9932a0c..d126588 100644 --- a/module_market/src/main/java/com/wss/module/market/ui/goods/detail/fragment/child/GoodsInfoWebFragment.java +++ b/module_market/src/main/java/com/wss/module/market/ui/goods/detail/fragment/child/GoodsInfoWebFragment.java @@ -31,9 +31,9 @@ protected void initView() { } public void initWebView() { - String url = "http://m.okhqb.com/item/description/1000334264.html?fromApp=true"; +// String url = "http://m.okhqb.com/item/description/1000334264.html?fromApp=true"; webView.setFocusable(false); - webView.loadUrl(url); + webView.loadUrl("file:///android_asset/html/goods_detail.html"); webSettings = webView.getSettings(); webSettings.setLoadWithOverviewMode(true); webSettings.setBuiltInZoomControls(true); diff --git a/module_market/src/main/java/com/wss/module/market/ui/goods/detail/helper/GoodsSpecificationPop.java b/module_market/src/main/java/com/wss/module/market/ui/goods/detail/helper/GoodsSpecificationPop.java new file mode 100644 index 0000000..58e3bee --- /dev/null +++ b/module_market/src/main/java/com/wss/module/market/ui/goods/detail/helper/GoodsSpecificationPop.java @@ -0,0 +1,106 @@ +package com.wss.module.market.ui.goods.detail.helper; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.PopupWindow; +import android.widget.TextView; + +import com.wss.common.utils.ImageUtils; +import com.wss.common.utils.PxUtils; +import com.wss.common.widget.FlowLayout; +import com.wss.module.market.R; +import com.wss.module.market.R2; + +import butterknife.BindView; +import butterknife.ButterKnife; + +/** + * Describe:商品规格Pop + * Created by 吴天强 on 2019/1/31. + */ + +public class GoodsSpecificationPop extends PopupWindow { + + private String imgUrl = "https://img14.360buyimg.com/n0/jfs/t1/1867/31/11716/401006/5bd072f8E6db292ab/f3610e2e816ade0f.jpg"; + private String[] colors = new String[]{"黑色", "宝石蓝", "翡翠绿", "红色", "藏青色", "胡杨黄"}; + private String[] versions = new String[]{"6GB+128G", "8GB+128GB", "8GB+256GB", "10GB+256GB"}; + private String[] buyWays = new String[]{"官网套餐", "碎屏保险服务", "故宫特别版", "贴膜套装"}; + + + private Context context; + @SuppressLint("StaticFieldLeak") + private static GoodsSpecificationPop specificationPop; + + @BindView(R2.id.fl_color) + FlowLayout flColor;//颜色 + + @BindView(R2.id.fl_version) + FlowLayout flVersion;//版本 + + @BindView(R2.id.fl_buy_way) + FlowLayout flBuyWay;//购买方式 + + @BindView(R2.id.iv_goods_img) + ImageView imageView; + + public GoodsSpecificationPop(Context context) { + this.context = context; + } + + public static synchronized GoodsSpecificationPop getInstance(Context context) { + if (specificationPop == null) { + specificationPop = new GoodsSpecificationPop(context); + } + return specificationPop; + } + + public void show(View parent) { + View view = View.inflate(context, R.layout.market_pop_goods_specification, null); + ButterKnife.bind(this, view); + setAnimationStyle(R.style.AnimSheetBottom); + setBackgroundDrawable(new ColorDrawable(0)); + setWidth(ViewGroup.LayoutParams.MATCH_PARENT); + setHeight(ViewGroup.LayoutParams.MATCH_PARENT); + setFocusable(true); + setOutsideTouchable(true); + setContentView(view); + showAtLocation(parent, Gravity.CENTER, 0, 0); + loadData(); + update(); + } + + private void loadData() { + ImageUtils.loadImage(imageView, imgUrl); + flColor.removeAllViews(); + //加载颜色 + for (String color : colors) { + TextView textView = new TextView(context); + textView.setText(color); + textView.setBackgroundResource(R.drawable.market_bg_of_ellipse_button_select); +// textView.setTextColor(R.color.market_goods_button_text_color); + textView.setTextColor(Color.BLACK); + ViewGroup.MarginLayoutParams mlp = new ViewGroup.MarginLayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); + mlp.setMargins(0, PxUtils.dp2px(5), PxUtils.dp2px(5), 0); + textView.setLayoutParams(mlp); + textView.setPadding(PxUtils.dp2px(10), PxUtils.dp2px(4), PxUtils.dp2px(10), PxUtils.dp2px(4)); + textView.setGravity(Gravity.CENTER); + textView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + v.setSelected(!v.isSelected()); + } + }); + + flColor.addView(textView); + } + + + } + +} diff --git a/module_market/src/main/res/color/market_goods_button_text_color.xml b/module_market/src/main/res/color/market_goods_button_text_color.xml new file mode 100644 index 0000000..236489e --- /dev/null +++ b/module_market/src/main/res/color/market_goods_button_text_color.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/module_market/src/main/res/drawable/market_bg_of_ellipse_button_black.xml b/module_market/src/main/res/drawable/market_bg_of_ellipse_button_black.xml new file mode 100644 index 0000000..24ce153 --- /dev/null +++ b/module_market/src/main/res/drawable/market_bg_of_ellipse_button_black.xml @@ -0,0 +1,12 @@ + + + + + + + + + + \ No newline at end of file diff --git a/module_market/src/main/res/drawable/market_bg_of_ellipse_button_red.xml b/module_market/src/main/res/drawable/market_bg_of_ellipse_button_red.xml new file mode 100644 index 0000000..6b34ee9 --- /dev/null +++ b/module_market/src/main/res/drawable/market_bg_of_ellipse_button_red.xml @@ -0,0 +1,12 @@ + + + + + + + + + + \ No newline at end of file diff --git a/module_market/src/main/res/drawable/market_bg_of_ellipse_button_select.xml b/module_market/src/main/res/drawable/market_bg_of_ellipse_button_select.xml new file mode 100644 index 0000000..7763649 --- /dev/null +++ b/module_market/src/main/res/drawable/market_bg_of_ellipse_button_select.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/module_market/src/main/res/layout/market_activity_goods_details.xml b/module_market/src/main/res/layout/market_activity_goods_details.xml index d37d6a1..c62edb4 100644 --- a/module_market/src/main/res/layout/market_activity_goods_details.xml +++ b/module_market/src/main/res/layout/market_activity_goods_details.xml @@ -2,6 +2,7 @@ diff --git a/module_market/src/main/res/layout/market_item_of_goods_config_list.xml b/module_market/src/main/res/layout/market_item_of_goods_config_list.xml index cc2aae8..d136132 100644 --- a/module_market/src/main/res/layout/market_item_of_goods_config_list.xml +++ b/module_market/src/main/res/layout/market_item_of_goods_config_list.xml @@ -1,7 +1,7 @@ + android:layout_height="match_parent" + android:background="@color/gray" /> - - - - + android:layout_height="1px" + android:background="@color/gray" /> diff --git a/module_market/src/main/res/layout/market_pop_goods_specification.xml b/module_market/src/main/res/layout/market_pop_goods_specification.xml new file mode 100644 index 0000000..b635e41 --- /dev/null +++ b/module_market/src/main/res/layout/market_pop_goods_specification.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From e2a0ed89665efe7d53b7dab160b8e20f6d3d3b5f Mon Sep 17 00:00:00 2001 From: wutq Date: Mon, 3 Jun 2019 16:12:06 +0800 Subject: [PATCH 05/23] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=8A=A8=E6=80=81?= =?UTF-8?q?=E6=9D=83=E9=99=90=E5=BA=93,RX=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/misc.xml | 2 +- app/build.gradle | 4 + common_base/build.gradle | 11 ++ common_base/src/main/AndroidManifest.xml | 3 +- .../com/wss/common/base/BaseFragment.java | 3 +- .../java/com/wss/common/bean/Template.java | 7 +- .../com/wss/common/manage/UpdateManager.java | 8 +- .../wss/common/utils/PermissionsUtils.java | 115 ++++++++++----- .../com/wss/common/utils/StringUtils.java | 11 -- .../java/com/wss/common/utils/ToastUtils.java | 30 ++-- .../pulltorefresh/PullToRefreshLayout.java | 12 +- .../common/widget/scaleImg/ImageViewer.java | 48 +++---- .../src/main/res/drawable-xhdpi/ic_back.png | Bin 0 -> 612 bytes .../res/drawable-xhdpi/input_add_default.png | Bin 0 -> 266 bytes .../res/drawable-xhdpi/input_add_disabled.png | Bin 0 -> 266 bytes .../drawable-xhdpi/input_minus_default.png | Bin 0 -> 138 bytes .../drawable-xhdpi/input_minus_disabled.png | Bin 0 -> 155 bytes .../src/main/res/layout/activity_webview.xml | 2 +- config.gradle | 18 ++- module_main/build.gradle | 5 +- module_main/src/main/AndroidManifest.xml | 7 + .../ui/hortab/fragment/OrderFragment.java | 4 +- .../main/ui/loading/LoadingActivity.java | 2 +- .../wss/module/main/ui/main/MainActivity.java | 12 +- .../main/ui/main/mvp/MainPresenter.java | 3 + .../module/main/ui/page/DialogActivity.java | 47 +++--- .../main/ui/page/ObserverButtonActivity.java | 2 +- .../module/main/ui/page/QRCodeActivity.java | 64 +++++++++ .../module/main/ui/page/YumanmanActivity.java | 2 +- .../main/ui/selector/SelectorActivity.java | 10 +- .../main/res/drawable-xxxhdpi/main_ic_add.png | Bin 0 -> 539 bytes .../res/drawable-xxxhdpi/main_ic_card.png | Bin 0 -> 15777 bytes .../res/drawable-xxxhdpi/main_ic_contact.png | Bin 0 -> 1550 bytes .../res/drawable-xxxhdpi/main_ic_payment.png | Bin 0 -> 15300 bytes .../res/drawable-xxxhdpi/main_ic_scan.png | Bin 0 -> 15343 bytes .../res/drawable-xxxhdpi/main_ic_transfer.png | Bin 0 -> 15538 bytes .../res/drawable-xxxhdpi/mainic_search.png | Bin 0 -> 3225 bytes .../main/res/drawable/main_shape_search.xml | 11 ++ .../main/res/layout/item_of_demo_fragment.xml | 14 ++ .../main_activity_corrdinator_layout.xml | 134 ++++++++++++++++++ .../main/res/layout/main_activity_qr_code.xml | 19 +++ .../main/res/layout/main_demo_activity.xml | 76 ++++++++++ .../main/res/layout/main_demo_fragment.xml | 27 ++++ .../main/res/layout/main_fragment_news.xml | 55 +++++++ .../src/main/res/layout/main_include_open.xml | 115 +++++++++++++++ .../res/layout/main_include_toolbar_close.xml | 46 ++++++ .../res/layout/main_include_toolbar_open.xml | 40 ++++++ module_main/src/main/res/values/attr.xml | 7 + .../src/main/res/values/attrs_orange.xml | 34 +++++ module_main/src/main/res/values/dimens.xml | 5 + .../main/res/values/ids_sticky_nav_layout.xml | 9 ++ module_main/src/main/res/values/styles.xml | 13 ++ module_market/build.gradle | 1 + .../ui/goods/cart/ShoppingCartActivity.java | 2 +- .../ui/goods/detail/GoodsDetailActivity.java | 4 +- .../module/user/ui/account/LoginActivity.java | 2 +- .../user/ui/account/RegisterActivity.java | 6 +- .../user/ui/main/mvp/UserPresenter.java | 2 +- .../wan/ui/collection/CollectionActivity.java | 4 +- .../wan/ui/project/ProjectActivity.java | 4 +- .../module/wan/ui/search/SearchActivity.java | 4 +- .../wan/ui/setup/SystemArticleActivity.java | 4 +- 62 files changed, 905 insertions(+), 165 deletions(-) delete mode 100644 common_base/src/main/java/com/wss/common/utils/StringUtils.java create mode 100644 common_base/src/main/res/drawable-xhdpi/ic_back.png create mode 100644 common_base/src/main/res/drawable-xhdpi/input_add_default.png create mode 100644 common_base/src/main/res/drawable-xhdpi/input_add_disabled.png create mode 100644 common_base/src/main/res/drawable-xhdpi/input_minus_default.png create mode 100644 common_base/src/main/res/drawable-xhdpi/input_minus_disabled.png create mode 100644 module_main/src/main/java/com/wss/module/main/ui/page/QRCodeActivity.java create mode 100644 module_main/src/main/res/drawable-xxxhdpi/main_ic_add.png create mode 100644 module_main/src/main/res/drawable-xxxhdpi/main_ic_card.png create mode 100644 module_main/src/main/res/drawable-xxxhdpi/main_ic_contact.png create mode 100644 module_main/src/main/res/drawable-xxxhdpi/main_ic_payment.png create mode 100644 module_main/src/main/res/drawable-xxxhdpi/main_ic_scan.png create mode 100644 module_main/src/main/res/drawable-xxxhdpi/main_ic_transfer.png create mode 100644 module_main/src/main/res/drawable-xxxhdpi/mainic_search.png create mode 100644 module_main/src/main/res/drawable/main_shape_search.xml create mode 100644 module_main/src/main/res/layout/item_of_demo_fragment.xml create mode 100644 module_main/src/main/res/layout/main_activity_corrdinator_layout.xml create mode 100644 module_main/src/main/res/layout/main_activity_qr_code.xml create mode 100644 module_main/src/main/res/layout/main_demo_activity.xml create mode 100644 module_main/src/main/res/layout/main_demo_fragment.xml create mode 100644 module_main/src/main/res/layout/main_fragment_news.xml create mode 100644 module_main/src/main/res/layout/main_include_open.xml create mode 100644 module_main/src/main/res/layout/main_include_toolbar_close.xml create mode 100644 module_main/src/main/res/layout/main_include_toolbar_open.xml create mode 100644 module_main/src/main/res/values/attr.xml create mode 100644 module_main/src/main/res/values/attrs_orange.xml create mode 100644 module_main/src/main/res/values/dimens.xml create mode 100644 module_main/src/main/res/values/ids_sticky_nav_layout.xml diff --git a/.idea/misc.xml b/.idea/misc.xml index 9ac5bbb..c0d5735 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -42,7 +42,7 @@ - + diff --git a/app/build.gradle b/app/build.gradle index 7ed3cdf..ecc418b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -41,6 +41,10 @@ android { proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } + compileOptions { + targetCompatibility rootProject.ext.versions.javaSDKVersion + sourceCompatibility rootProject.ext.versions.javaSDKVersion + } } configurations.all { diff --git a/common_base/build.gradle b/common_base/build.gradle index 8fda9e6..e03c6fa 100644 --- a/common_base/build.gradle +++ b/common_base/build.gradle @@ -35,6 +35,10 @@ android { dexOptions { javaMaxHeapSize "4g" } + compileOptions { + targetCompatibility rootProject.ext.versions.javaSDKVersion + sourceCompatibility rootProject.ext.versions.javaSDKVersion + } } dependencies { @@ -85,4 +89,11 @@ dependencies { api rootProject.ext.dependencies["greenDao"] //scaleImageView api rootProject.ext.dependencies["scaleImageView"] + //二维码扫描 + api rootProject.ext.dependencies["zxing"] + //危险权限 + api rootProject.ext.dependencies["xxpermissions"] + //RX + api rootProject.ext.dependencies["rx2_java"] + api rootProject.ext.dependencies["rx2_android"] } diff --git a/common_base/src/main/AndroidManifest.xml b/common_base/src/main/AndroidManifest.xml index f0f9a56..fa7d643 100644 --- a/common_base/src/main/AndroidManifest.xml +++ b/common_base/src/main/AndroidManifest.xml @@ -9,8 +9,9 @@ - + + diff --git a/common_base/src/main/java/com/wss/common/base/BaseFragment.java b/common_base/src/main/java/com/wss/common/base/BaseFragment.java index 745f750..cbb55b4 100644 --- a/common_base/src/main/java/com/wss/common/base/BaseFragment.java +++ b/common_base/src/main/java/com/wss/common/base/BaseFragment.java @@ -34,6 +34,7 @@ public abstract class BaseFragment extends Fragment { private Unbinder unBinder; protected Context mContext; protected LoadingDialog loadingDialog; + protected HorizontalTabTitle tabTitle; @Override @@ -118,7 +119,7 @@ protected void onPageClick() { * 给Fragment设置数据 */ public void setFragmentData(HorizontalTabTitle data) { - + this.tabTitle = data; } /** diff --git a/common_base/src/main/java/com/wss/common/bean/Template.java b/common_base/src/main/java/com/wss/common/bean/Template.java index 28eaad8..7a25167 100644 --- a/common_base/src/main/java/com/wss/common/bean/Template.java +++ b/common_base/src/main/java/com/wss/common/bean/Template.java @@ -1,6 +1,7 @@ package com.wss.common.bean; -import com.wss.common.base.BaseActivity; +import android.app.Activity; + import com.wss.common.base.bean.BaseBean; import java.util.Map; @@ -32,11 +33,11 @@ public Template(String title, int res, String url, int type, String describe) { this.describe = describe; } - public Template(String title, int res, Class clazz) { + public Template(String title, int res, Class clazz) { this(title, res, clazz, ""); } - public Template(String title, int res, Class clazz, String describe) { + public Template(String title, int res, Class clazz, String describe) { this.title = title; this.res = res; this.clazz = clazz; diff --git a/common_base/src/main/java/com/wss/common/manage/UpdateManager.java b/common_base/src/main/java/com/wss/common/manage/UpdateManager.java index 45ae0b5..59cc479 100644 --- a/common_base/src/main/java/com/wss/common/manage/UpdateManager.java +++ b/common_base/src/main/java/com/wss/common/manage/UpdateManager.java @@ -63,7 +63,7 @@ public static synchronized UpdateManager getInstance(Context context) { */ public void download(String url) { if (TextUtils.isEmpty(url)) { - ToastUtils.showToast(mContext, "请设置下载Url"); + ToastUtils.show(mContext, "请设置下载Url"); return; } progressDialog.show(); @@ -107,16 +107,16 @@ public void handleMessage(Message msg) { break; case DOWNLOAD_SUCCESS: progressDialog.dismiss(); - ToastUtils.showToast(mContext, "下载完成"); + ToastUtils.show(mContext, "下载完成"); installApk(); break; case DOWNLOAD_FAILED: progressDialog.dismiss(); - ToastUtils.showToast(mContext, "下载失败"); + ToastUtils.show(mContext, "下载失败"); break; case DOWNLOAD_CANCEL: progressDialog.dismiss(); - ToastUtils.showToast(mContext, "已取消下载"); + ToastUtils.show(mContext, "已取消下载"); break; default: break; diff --git a/common_base/src/main/java/com/wss/common/utils/PermissionsUtils.java b/common_base/src/main/java/com/wss/common/utils/PermissionsUtils.java index b53bc02..565412a 100644 --- a/common_base/src/main/java/com/wss/common/utils/PermissionsUtils.java +++ b/common_base/src/main/java/com/wss/common/utils/PermissionsUtils.java @@ -1,14 +1,17 @@ package com.wss.common.utils; import android.app.Activity; -import android.content.pm.PackageManager; -import android.os.Build; -import android.support.v4.app.ActivityCompat; -import android.support.v4.content.ContextCompat; -import java.util.ArrayList; +import com.hjq.permissions.OnPermission; +import com.hjq.permissions.Permission; +import com.hjq.permissions.XXPermissions; + import java.util.List; +import io.reactivex.Observable; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.schedulers.Schedulers; + /** * Describe:6.0动态权限管理帮助类 * Created by 吴天强 on 2018/10/25. @@ -16,47 +19,93 @@ public class PermissionsUtils { - /** - * 判断权限 + * 授权所有权限 * - * @param context context - * @param permissions 权限列表 + * @param activity activity */ - public static boolean checkPermissions(Activity context, String... permissions) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - List permissionsList = new ArrayList<>(); - if (permissions != null && permissions.length != 0) { - for (String permission : permissions) { - if (!isHavePermissions(context, permission)) { - permissionsList.add(permission); + public static void authorizationAllPermissions(Activity activity) { + XXPermissions.with(activity) + .request(new OnPermission() { + @Override + public void hasPermission(List granted, boolean isAll) { + } + + @Override + public void noPermission(List denied, boolean quick) { + } + }); + } + + /** + * 检查相机权限 + */ + public static Observable checkPermissions(Activity activity, String... permissions) { + return Observable.create( + subscriber -> { + if (XXPermissions.isHasPermission(activity, permissions)) { + subscriber.onNext(true); + } else { + XXPermissions.with(activity) + .permission(permissions) + .request(new OnPermission() { + @Override + public void hasPermission(List granted, boolean isAll) { + subscriber.onNext(true); + } + + @Override + public void noPermission(List denied, boolean quick) { + subscriber.onNext(false); + ToastUtils.show(activity, "您必须授权必要权限才可使用该功能!"); + } + }); } - } - if (permissionsList.size() > 0) { - // 遍历完后申请 - applyPermissions(context, permissionsList); - return false; - } - } - } - return true; + }) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()); } + /** - * 检查是否授权某权限 + * 检查相机权限 */ - private static boolean isHavePermissions(Activity context, String permissions) { - return ContextCompat.checkSelfPermission(context, permissions) == PackageManager.PERMISSION_GRANTED; + public static Observable checkCamera(Activity activity) { + return checkPermissions(activity, Permission.CAMERA); } /** - * 申请权限 + * 检查相机、文件读写权限 + * + * @param activity activity + * @return boolean + */ + public static Observable checkCameraAndStorage(Activity activity) { + String[] storage = { + Permission.READ_EXTERNAL_STORAGE, + Permission.WRITE_EXTERNAL_STORAGE, + Permission.CAMERA}; + return checkPermissions(activity, storage); + } + + + /** + * 检查录音相关权限 + */ + public static Observable checkRecord(Activity activity) { + String[] storage = { + Permission.READ_EXTERNAL_STORAGE, + Permission.WRITE_EXTERNAL_STORAGE, + Permission.RECORD_AUDIO}; + return checkPermissions(activity, storage); + } + + /** + * 检查拨打电话相关权限 */ - private static void applyPermissions(Activity context, List permissions) { - if (!permissions.isEmpty()) { - ActivityCompat.requestPermissions(context, permissions.toArray(new String[permissions.size()]), 1); - } + public static Observable checkCallPhone(Activity activity) { + return checkPermissions(activity, Permission.CALL_PHONE); } diff --git a/common_base/src/main/java/com/wss/common/utils/StringUtils.java b/common_base/src/main/java/com/wss/common/utils/StringUtils.java deleted file mode 100644 index 55a80df..0000000 --- a/common_base/src/main/java/com/wss/common/utils/StringUtils.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.wss.common.utils; - -/** - * Describe:字符串工具类 - * Created by 吴天强 on 2018/10/17. - */ - -public class StringUtils { - - -} diff --git a/common_base/src/main/java/com/wss/common/utils/ToastUtils.java b/common_base/src/main/java/com/wss/common/utils/ToastUtils.java index bf07c16..109f3f5 100644 --- a/common_base/src/main/java/com/wss/common/utils/ToastUtils.java +++ b/common_base/src/main/java/com/wss/common/utils/ToastUtils.java @@ -1,8 +1,12 @@ package com.wss.common.utils; import android.content.Context; +import android.view.View; +import android.widget.TextView; import android.widget.Toast; +import com.wss.common.base.R; + /** * Describe:Toast @@ -11,12 +15,12 @@ public class ToastUtils { - public static void showToast(Context context, int strings) { - showToast(context, context.getString(strings)); + public static void show(Context context, int strings) { + show(context, context.getString(strings)); } - public static void showToast(Context context, String text) { -// showToast(context, title, Gravity.BOTTOM); + public static void show(Context context, String text) { +// show(context, title, Gravity.BOTTOM); Toast.makeText(context, text, Toast.LENGTH_SHORT).show(); } @@ -27,14 +31,14 @@ public static void showToast(Context context, String text) { * @param gravity 弹出位置 */ - public static void showToast(Context context, CharSequence s, int gravity) { -// Toast toast = new Toast(context); -// View toastView = View.inflate(context, R.layout.toast, null); -// toast.setView(toastView); -// toast.setDuration(Toast.LENGTH_SHORT); -// TextView textView = toastView.findViewById(R.id.tv_message); -// textView.setText(s); -// toast.setGravity(gravity, 0, 100); -// toast.show(); + public static void show(Context context, CharSequence s, int gravity) { + Toast toast = new Toast(context); + View toastView = View.inflate(context, R.layout.toast, null); + toast.setView(toastView); + toast.setDuration(Toast.LENGTH_SHORT); + TextView textView = toastView.findViewById(R.id.tv_message); + textView.setText(s); + toast.setGravity(gravity, 0, 100); + toast.show(); } } diff --git a/common_base/src/main/java/com/wss/common/widget/pulltorefresh/PullToRefreshLayout.java b/common_base/src/main/java/com/wss/common/widget/pulltorefresh/PullToRefreshLayout.java index 079311b..7f04698 100644 --- a/common_base/src/main/java/com/wss/common/widget/pulltorefresh/PullToRefreshLayout.java +++ b/common_base/src/main/java/com/wss/common/widget/pulltorefresh/PullToRefreshLayout.java @@ -75,7 +75,7 @@ public PullToRefreshLayout(Context context, AttributeSet attrs, int defStyleAttr init(); } - private void cal() { + private void init() { head_height = PxUtils.dp2px(getContext(), HEAD_HEIGHT); foot_height = PxUtils.dp2px(getContext(), FOOT_HEIGHT); head_height_2 = PxUtils.dp2px(getContext(), HEAD_HEIGHT * 2); @@ -84,15 +84,6 @@ private void cal() { mTouchSlope = ViewConfiguration.get(getContext()).getScaledTouchSlop(); } - private void init() { - cal(); - int count = getChildCount(); - if (count != 1) { - new IllegalArgumentException("child only can be one"); - } - - } - @Override protected void onFinishInflate() { super.onFinishInflate(); @@ -110,6 +101,7 @@ protected void onAttachedToWindow() { private void addHeadView() { if (mHeaderView == null) { mHeaderView = new RefreshView(getContext()); + mHeaderView.setType(true); } else { removeView(mHeaderView.getView()); } diff --git a/common_base/src/main/java/com/wss/common/widget/scaleImg/ImageViewer.java b/common_base/src/main/java/com/wss/common/widget/scaleImg/ImageViewer.java index a36b162..875225f 100644 --- a/common_base/src/main/java/com/wss/common/widget/scaleImg/ImageViewer.java +++ b/common_base/src/main/java/com/wss/common/widget/scaleImg/ImageViewer.java @@ -1,6 +1,5 @@ package com.wss.common.widget.scaleImg; -import android.Manifest; import android.annotation.SuppressLint; import android.app.Activity; import android.app.Dialog; @@ -17,6 +16,7 @@ import com.bumptech.glide.request.target.Target; import com.davemorrissey.labs.subscaleview.ImageSource; import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView; +import com.hjq.permissions.Permission; import com.orhanobut.logger.Logger; import com.wss.common.base.R; import com.wss.common.utils.PermissionsUtils; @@ -43,21 +43,18 @@ public class ImageViewer { private Activity mActivity; //图片下载器 - private ImageDownloader mImageDownloader = new ImageDownloader() { - @Override - public File downLoad(String url, Activity activity) { - File file = null; - try { - file = Glide.with(activity) - .load(url) - .downloadOnly(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL) - .get(); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - Logger.e("下载图片异常" + e.getMessage()); - } - return file; + private ImageDownloader mImageDownloader = (url, activity) -> { + File file = null; + try { + file = Glide.with(activity) + .load(url) + .downloadOnly(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL) + .get(); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + Logger.e("下载图片异常" + e.getMessage()); } + return file; }; private List mUrls = new ArrayList<>(); @@ -207,16 +204,19 @@ public void onClick(View v) { imDownload.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - if (PermissionsUtils.checkPermissions(mActivity, Manifest.permission.WRITE_EXTERNAL_STORAGE)) { - try { - MediaStore.Images.Media.insertImage(mActivity.getContentResolver(), - mDownloadFiles.get(mSelectedPosition).getAbsolutePath(), - mDownloadFiles.get(mSelectedPosition).getName(), null); - } catch (FileNotFoundException e) { - e.printStackTrace(); + + PermissionsUtils.checkPermissions(mActivity, Permission.WRITE_EXTERNAL_STORAGE).subscribe(r -> { + if (r) { + try { + MediaStore.Images.Media.insertImage(mActivity.getContentResolver(), + mDownloadFiles.get(mSelectedPosition).getAbsolutePath(), + mDownloadFiles.get(mSelectedPosition).getName(), null); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + ToastUtils.show(mActivity, "图片保存成功"); } - ToastUtils.showToast(mActivity, "图片保存成功"); - } + }); } }); mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { diff --git a/common_base/src/main/res/drawable-xhdpi/ic_back.png b/common_base/src/main/res/drawable-xhdpi/ic_back.png new file mode 100644 index 0000000000000000000000000000000000000000..e395a62989c6957e4ff4deeba44e2949e6137ef1 GIT binary patch literal 612 zcmV-q0-ODbP)Px%9!W$&R9Fe^m`y~bVHC%E`ICsMRteC9oHgduDF4%2(weQU(Vg^~msD6>7DN zNCg~;8T}r>y85UGL_kh*2~q6)QIMx+|f#EgCo4OaQ897Jm19Hg!o>Q$ju%ZL=i zrI^t#pw=p1or6qgNY0Ht>QKu7gg(QmGmF;^z0vXvbrwREa2ywO?GC=GgDnFPDu+Xm zdSGa=JVTv@P$}$#)DuIiI@mG*A@{D{6+^oF8{BSrhB^zOLf8Q*_Ytd09c&qZP(Eyl zA>B##TArcKLMRtDAzc0HV9Nl^a$r4d$UJCyhB^zOELimJ;k(9d z7W>5&tSpO@OgdIbxg6NU$~WO=fnyGj&?AP30>;x~0&Jp5H+T-Ku`&FL*ArQ?@IJ`b N44$rjF6*2UngFd;WQ70# literal 0 HcmV?d00001 diff --git a/common_base/src/main/res/drawable-xhdpi/input_add_disabled.png b/common_base/src/main/res/drawable-xhdpi/input_add_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..dd67fb78726ad071302d627feedfec651b3b2133 GIT binary patch literal 266 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjjKx9jP7LeL$-D$|j(EB_hIsHM zrzi-;?5m0Vd49gVwZo~%hzOgK($e=ri>G!)^C$+hSlPO3ip?xOX z7KU?eoevjvZey6v*mA^OS3$&yXR)J;L5GB+rO1@R4v*V>4wv67RFh-5#J(VBjfk-D zWq*aZqZR-D{JiZTx`^(5jGi8E=St94K$=1vR*HICC$sr>sZs&@XXO9 z>tKeA01smmSBIbLf=#SxQby8hZQW`|n?fC&-!&Ml5ICHwu*-tssgPCrR-yNSK>sj! My85}Sb4q9e02_r|XaE2J literal 0 HcmV?d00001 diff --git a/common_base/src/main/res/drawable-xhdpi/input_minus_default.png b/common_base/src/main/res/drawable-xhdpi/input_minus_default.png new file mode 100644 index 0000000000000000000000000000000000000000..753174d19826c0d7c6749de11e4ec7d23aacbe3c GIT binary patch literal 138 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaN3?zjj6;1;w#^NA%Cx&(BWL^R}`~f~8u0UEv zMNLIT9f*{b)x3?8=L3aUN`m}?8CpO8TtC;{9LSgSba4!kxSX6IQK0aKiM@?Si=$6? d)tLuO3`-|-Jb#pFv>vF4!PC{xWt~$(699h5A>;r6 literal 0 HcmV?d00001 diff --git a/common_base/src/main/res/drawable-xhdpi/input_minus_disabled.png b/common_base/src/main/res/drawable-xhdpi/input_minus_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..7b18444686adf7a37b88d29d3e3edca7e580f679 GIT binary patch literal 155 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjjKx9jP7LeL$-D$|LOop^Lp*qs z6C_v{D;h{KIoq>HoS$!h|I~>S5ug75uQ$u8V$XP{zhI_qkGNjU51y0{0hbGAL^^oy zGhpPM&$5YE%|ln}RkP<6qx>s#E(%ESHYUn4F}!h + android:layout_height="match_parent" /> diff --git a/config.gradle b/config.gradle index 4e383d8..9233239 100644 --- a/config.gradle +++ b/config.gradle @@ -23,6 +23,7 @@ ext { espressoVersion : "3.0.1", junitVersion : "4.12", annotationsVersion : "24.0.0", + javaSDKVersion : 1.8,//javaSDK版本 multidexVersion : "1.0.2", butterknifeVersion : "8.4.0", @@ -34,7 +35,6 @@ ext { loggerVersion : "2.2.0", fastjsonVersion : "1.1.54", immersionbarVersion : "2.3.2-beta05", -// picassoVersion : "2.71828", glideVersion : "4.8.0", bannerVersion : "2.1.4", javaxVersion : "1.2", @@ -43,6 +43,10 @@ ext { pickerViewVersion : "4.1.6", superAdapterVersion : "3.6.8", scaleImageViewVersion : "3.10.0", + zxingViewVersion : "1.3", + xxpermissionsVersion : "5.5", + rx2JavaVersion : "2.1.5", + rx2AndroidVersion : "2.0.1", ] dependencies = [ @@ -105,7 +109,17 @@ ext { "superAdapter" : "org.byteam.superadapter:superadapter:${versions["superAdapterVersion"]}", //展示大图+手势滑动 - "scaleImageView" : "com.davemorrissey.labs:subsampling-scale-image-view:${versions["scaleImageViewVersion"]}" + "scaleImageView" : "com.davemorrissey.labs:subsampling-scale-image-view:${versions["scaleImageViewVersion"]}", + + //二维码扫描 + "zxing" : "com.github.0xZhangKe:QRCodeView:${versions["zxingViewVersion"]}", + + //危险权限库 + "xxpermissions" : "com.hjq:xxpermissions:${versions["xxpermissionsVersion"]}", + + //RX家族 + "rx2_java" : "io.reactivex.rxjava2:rxjava:${versions["rx2JavaVersion"]}", + "rx2_android" : "io.reactivex.rxjava2:rxandroid:${versions["rx2AndroidVersion"]}", // //图片缩放 // "photoview" : "com.github.chrisbanes.photoview:library:1.2.4", diff --git a/module_main/build.gradle b/module_main/build.gradle index 2f3638f..32f5c9e 100644 --- a/module_main/build.gradle +++ b/module_main/build.gradle @@ -50,13 +50,16 @@ android { } } } + compileOptions { + targetCompatibility rootProject.ext.versions.javaSDKVersion + sourceCompatibility rootProject.ext.versions.javaSDKVersion + } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) //公用依赖包 implementation project(':common_base') - //Arouter路由 annotationProcessor rootProject.ext.dependencies["arouter_compiler"] //黄油刀 diff --git a/module_main/src/main/AndroidManifest.xml b/module_main/src/main/AndroidManifest.xml index 045e9df..8d81011 100644 --- a/module_main/src/main/AndroidManifest.xml +++ b/module_main/src/main/AndroidManifest.xml @@ -29,5 +29,12 @@ + + + diff --git a/module_main/src/main/java/com/wss/module/main/ui/hortab/fragment/OrderFragment.java b/module_main/src/main/java/com/wss/module/main/ui/hortab/fragment/OrderFragment.java index 9818571..4397b6a 100644 --- a/module_main/src/main/java/com/wss/module/main/ui/hortab/fragment/OrderFragment.java +++ b/module_main/src/main/java/com/wss/module/main/ui/hortab/fragment/OrderFragment.java @@ -69,7 +69,7 @@ public void onError(Object tag, String errorMsg) { if (page == 0) { showErrorView(); } else { - ToastUtils.showToast(mContext, errorMsg); + ToastUtils.show(mContext, errorMsg); } } @@ -79,7 +79,7 @@ public void onEmpty(Object tag) { if (page == 0) { showEmptyView(); } else { - ToastUtils.showToast(mContext, "暂无更多数据"); + ToastUtils.show(mContext, "暂无更多数据"); } } diff --git a/module_main/src/main/java/com/wss/module/main/ui/loading/LoadingActivity.java b/module_main/src/main/java/com/wss/module/main/ui/loading/LoadingActivity.java index 2b3e9e1..cf2a6a4 100644 --- a/module_main/src/main/java/com/wss/module/main/ui/loading/LoadingActivity.java +++ b/module_main/src/main/java/com/wss/module/main/ui/loading/LoadingActivity.java @@ -19,7 +19,7 @@ public class LoadingActivity extends BaseActivity { - private long loadingTime = 1500; + private long loadingTime = 1000; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { diff --git a/module_main/src/main/java/com/wss/module/main/ui/main/MainActivity.java b/module_main/src/main/java/com/wss/module/main/ui/main/MainActivity.java index 41bce46..da370e1 100644 --- a/module_main/src/main/java/com/wss/module/main/ui/main/MainActivity.java +++ b/module_main/src/main/java/com/wss/module/main/ui/main/MainActivity.java @@ -1,6 +1,5 @@ package com.wss.module.main.ui.main; -import android.Manifest; import android.support.annotation.IdRes; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentTransaction; @@ -8,6 +7,7 @@ import android.view.KeyEvent; import android.widget.RadioGroup; +import com.hjq.permissions.Permission; import com.wss.common.base.ActionBarActivity; import com.wss.common.base.BaseApplication; import com.wss.common.base.BaseFragment; @@ -84,9 +84,11 @@ public void onCheckedChanged(RadioGroup group, @IdRes int checkedId) { } }); //检查文件权限 - if (PermissionsUtils.checkPermissions(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) { - presenter.checkUpdate(); - } + PermissionsUtils.checkPermissions(this, Permission.WRITE_EXTERNAL_STORAGE).subscribe(r -> { + if (r) { + presenter.checkUpdate(); + } + }); presenter.getTabList(); } @@ -136,7 +138,7 @@ private void hideFragment() { public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { if ((System.currentTimeMillis() - mExitTime) > 2000) { - ToastUtils.showToast(mContext, getString(R.string.main_exit_app)); + ToastUtils.show(mContext, getString(R.string.main_exit_app)); mExitTime = System.currentTimeMillis(); } else { BaseApplication.getApplication().exitApp(); diff --git a/module_main/src/main/java/com/wss/module/main/ui/main/mvp/MainPresenter.java b/module_main/src/main/java/com/wss/module/main/ui/main/mvp/MainPresenter.java index 074bc25..1dfb044 100644 --- a/module_main/src/main/java/com/wss/module/main/ui/main/mvp/MainPresenter.java +++ b/module_main/src/main/java/com/wss/module/main/ui/main/mvp/MainPresenter.java @@ -15,6 +15,7 @@ import com.wss.module.main.ui.page.FlowLayoutActivity; import com.wss.module.main.ui.page.MultipleItemActivity; import com.wss.module.main.ui.page.ObserverButtonActivity; +import com.wss.module.main.ui.page.QRCodeActivity; import com.wss.module.main.ui.page.RadioGroupActivity; import com.wss.module.main.ui.page.ScaleImageActivity; import com.wss.module.main.ui.page.YumanmanActivity; @@ -84,6 +85,8 @@ public void getTabList() { list.add(new Template("图片查看器", R.drawable.main_icon_18, ScaleImageActivity.class, "大图查看器、支持下载、删除、缩放等操作")); list.add(new Template("于慢慢计算器", R.drawable.main_icon_19, YumanmanActivity.class, "某一个初始值递增某次计算结果")); list.add(new Template("自定义RadioGroup", R.drawable.main_icon_20, RadioGroupActivity.class, "自定义RadioGroup")); + list.add(new Template("扫描二维码", R.drawable.main_icon_21, QRCodeActivity.class, "扫描二维码")); + getView().tabList(list); } } diff --git a/module_main/src/main/java/com/wss/module/main/ui/page/DialogActivity.java b/module_main/src/main/java/com/wss/module/main/ui/page/DialogActivity.java index 07ae005..beb7b01 100644 --- a/module_main/src/main/java/com/wss/module/main/ui/page/DialogActivity.java +++ b/module_main/src/main/java/com/wss/module/main/ui/page/DialogActivity.java @@ -1,17 +1,18 @@ package com.wss.module.main.ui.page; -import android.Manifest; import android.annotation.SuppressLint; import android.os.Handler; import android.os.Message; import android.view.View; +import com.hjq.permissions.Permission; import com.wss.common.base.ActionBarActivity; import com.wss.common.base.mvp.BasePresenter; import com.wss.common.utils.PermissionsUtils; import com.wss.common.utils.ToastUtils; import com.wss.common.widget.NumberProgressBar; import com.wss.common.widget.dialog.AppDialog; +import com.wss.common.widget.dialog.AppDialog.OnButtonClickListener; import com.wss.common.widget.dialog.DialogType; import com.wss.module.main.R; import com.wss.module.main.R2; @@ -47,7 +48,7 @@ protected int getLayoutId() { @Override protected void initView() { setTitleText("对话框"); - PermissionsUtils.checkPermissions(this, Manifest.permission.WRITE_EXTERNAL_STORAGE); + PermissionsUtils.checkPermissions(this, Permission.WRITE_EXTERNAL_STORAGE).subscribe(); } /** @@ -64,22 +65,17 @@ public void onBtnClick(View view) { } else if (view.getId() == R.id.btn_02) { new AppDialog(mContext, DialogType.INPUT) .setTitle("来一段文字") - .setLeftButton("输好了", new AppDialog.OnButtonClickListener() { - @Override - public void onClick(String val) { - ToastUtils.showToast(mContext, val); - } - }) + .setLeftButton("输好了", val -> ToastUtils.show(mContext, val)) .setRightButton("不输了") .show(); } else if (view.getId() == R.id.btn_03) { new AppDialog(mContext, DialogType.COUNT) .setTitle("修改数量") .setNumber(1, 10, 2) - .setLeftButton("OK", new AppDialog.OnButtonClickListener() { + .setLeftButton("OK", new OnButtonClickListener() { @Override public void onClick(String val) { - ToastUtils.showToast(mContext, val); + ToastUtils.show(mContext, val); } }) .setLeftButtonTextColor(R.color.red) @@ -103,28 +99,21 @@ public void onClick(String val) { list.add("相册"); new AppDialog(mContext, DialogType.BOTTOM_IN) .setTitle("多条目") - .setBottomItems(list, new AppDialog.OnItemClickListener() { - @Override - public void onItemClick(int position) { - ToastUtils.showToast(mContext, list.get(position)); - } - }) + .setBottomItems(list, position -> ToastUtils.show(mContext, list.get(position))) .setBottomCancelText("再见") .show(); } else if (view.getId() == R.id.btn_07) { -// View progressView = View.inflate(mContext, R.layout.update_progress_layout, null); -// progressBar = progressView.findViewById(R.id.number_progress); -// progressDialog = new AppDialog(mContext); -// mProgress = 0; -// progressBar.setProgress(mProgress); -// -// progressDialog.setTitle("更新") -// .addDialogView(progressView) -// .show(); -// update(); - - + View progressView = View.inflate(mContext, R.layout.update_progress_layout, null); + progressBar = progressView.findViewById(R.id.number_progress); + progressDialog = new AppDialog(mContext); + mProgress = 0; + progressBar.setProgress(mProgress); + + progressDialog.setTitle("更新") + .addDialogView(progressView) + .show(); + update(); } } @@ -150,7 +139,7 @@ public void handleMessage(Message msg) { int progress = (int) msg.obj; progressBar.setProgress(progress); if (progress >= mMaxProgress) { - ToastUtils.showToast(mContext, "下载完成"); + ToastUtils.show(mContext, "下载完成"); progressDialog.dismiss(); } else { update(); diff --git a/module_main/src/main/java/com/wss/module/main/ui/page/ObserverButtonActivity.java b/module_main/src/main/java/com/wss/module/main/ui/page/ObserverButtonActivity.java index bffc410..0f672d2 100644 --- a/module_main/src/main/java/com/wss/module/main/ui/page/ObserverButtonActivity.java +++ b/module_main/src/main/java/com/wss/module/main/ui/page/ObserverButtonActivity.java @@ -53,7 +53,7 @@ protected void initView() { @OnClick(R2.id.ob_btn) public void onClick(View v) { - ToastUtils.showToast(mContext, "可点击"); + ToastUtils.show(mContext, "可点击"); } diff --git a/module_main/src/main/java/com/wss/module/main/ui/page/QRCodeActivity.java b/module_main/src/main/java/com/wss/module/main/ui/page/QRCodeActivity.java new file mode 100644 index 0000000..c15704b --- /dev/null +++ b/module_main/src/main/java/com/wss/module/main/ui/page/QRCodeActivity.java @@ -0,0 +1,64 @@ +package com.wss.module.main.ui.page; + +import com.wss.common.base.ActionBarActivity; +import com.wss.common.base.mvp.BasePresenter; +import com.wss.common.utils.PermissionsUtils; +import com.wss.common.utils.ToastUtils; +import com.wss.module.main.R; +import com.wss.module.main.R2; +import com.zhangke.qrcodeview.QRCodeView; + +import butterknife.BindView; + +/** + * Describe:二维码扫描页面 + * Created by 吴天强 on 2019/3/20. + */ + +public class QRCodeActivity extends ActionBarActivity { + + + @BindView(R2.id.qr_code_view) + QRCodeView qrCodeView; + + @Override + protected BasePresenter createPresenter() { + return null; + } + + @Override + protected int getLayoutId() { + return R.layout.main_activity_qr_code; + } + + @Override + protected void initView() { + + setTitleText("二维码扫描"); + PermissionsUtils.checkCamera(this).subscribe(r -> { + if (r) { + qrCodeView.startPreview(); + qrCodeView.setOnQRCodeListener(result -> { + ToastUtils.show(mContext, result.getText()); + finish(); + }); + } else { + finish(); + } + }); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + qrCodeView.stopPreview(); + } + + @Override + protected void onResume() { + super.onResume(); + + } + + +} diff --git a/module_main/src/main/java/com/wss/module/main/ui/page/YumanmanActivity.java b/module_main/src/main/java/com/wss/module/main/ui/page/YumanmanActivity.java index 69fb72d..0716d8c 100644 --- a/module_main/src/main/java/com/wss/module/main/ui/page/YumanmanActivity.java +++ b/module_main/src/main/java/com/wss/module/main/ui/page/YumanmanActivity.java @@ -83,7 +83,7 @@ public void addValue(View v) { } else { ClipboardManager cm = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE); cm.setPrimaryClip(ClipData.newPlainText(null, ((TextView) v).getText())); - ToastUtils.showToast(mContext, "结果已复制到粘贴板"); + ToastUtils.show(mContext, "结果已复制到粘贴板"); } } diff --git a/module_main/src/main/java/com/wss/module/main/ui/selector/SelectorActivity.java b/module_main/src/main/java/com/wss/module/main/ui/selector/SelectorActivity.java index 4253e0c..ba29531 100644 --- a/module_main/src/main/java/com/wss/module/main/ui/selector/SelectorActivity.java +++ b/module_main/src/main/java/com/wss/module/main/ui/selector/SelectorActivity.java @@ -100,7 +100,7 @@ private void showLunarPicker() { lunarPicker = new TimePickerBuilder(this, new OnTimeSelectListener() { @Override public void onTimeSelect(Date date, View v) {//选中事件回调 - ToastUtils.showToast(mContext, getTime(date)); + ToastUtils.show(mContext, getTime(date)); } }) .setDate(selectedDate) @@ -169,7 +169,7 @@ public void onTimeSelect(Date date, View v) {//选中事件回调 Calendar calendar = Calendar.getInstance(); calendar.setTime(date); selectDate = calendar; - ToastUtils.showToast(mContext, getTime(date)); + ToastUtils.show(mContext, getTime(date)); } }).build(); //注:根据需求来决定是否使用该方法(一般是精确到秒的情况),此项可以在弹出选择器的时候重新设置当前时间, @@ -191,7 +191,7 @@ public void onOptionsSelect(int options1, int options2, int options3, View v) { String tx = options1Items.get(options1).getPickerViewText() + options2Items.get(options1).get(options2) + options3Items.get(options1).get(options2).get(options3); - ToastUtils.showToast(mContext, tx); + ToastUtils.show(mContext, tx); } }) @@ -215,7 +215,7 @@ private void showUserList() {//条件选择器初始化,自定义布局 @Override public void onOptionsSelect(int options1, int option2, int options3, View v) { //返回的分别是三个级别的选中位置 - ToastUtils.showToast(mContext, user.get(options1)); + ToastUtils.show(mContext, user.get(options1)); } }) .setSelectOptions(2) @@ -234,7 +234,7 @@ private void showUserInfoList() { @Override public void onOptionsSelect(int options1, int options2, int options3, View v) { String str = user.get(options1) + "来自" + userFrom.get(options2) + "是一个" + userDes.get(options3); - ToastUtils.showToast(mContext, str); + ToastUtils.show(mContext, str); } }) .setOptionsSelectChangeListener(new OnOptionsSelectChangeListener() { diff --git a/module_main/src/main/res/drawable-xxxhdpi/main_ic_add.png b/module_main/src/main/res/drawable-xxxhdpi/main_ic_add.png new file mode 100644 index 0000000000000000000000000000000000000000..4d563a82e3fc4b4c3f461d2e90b280c5b72839d0 GIT binary patch literal 539 zcmeAS@N?(olHy`uVBq!ia0vp^ejv=j1|<7dDabM~Fh25haSW-5dwa)loo}Ly>&Lx| zC(K}&njz7wxWdFsMX0x>>5z%bN0;wH3q!gbXE1fXn8Cn$GTv{_rOA6l)%#|bzTUlW z_WSSOc3(Z2Tcg;x=#<8xgMu9DG9nE#yRB7r%(R^Sq-v79=e;d|`QC4j+;;lt*)yM2 zzF&*B&;6ZY%vkXu?xCH!<^Fpwy>D}WsGFTy-THgVlSfsr`E&L2)fo82{46vWjKv|w z3G;CsICGSfoi*Xvqn2hSgW|$Nj*K&QT0C69a3*F>K>$OV9)9J~2hN^(ta5$QoW|#u z-(*dC8o2)HSKX7=RRV9O9Y1|?eyhM(f4eOyTAGVSopuX?9R7$EB}Z7f4VmP*z?CHZ&LJ%G?t6jaNjVxm%gWZXF*@;a}Q?FK6_JXvlNNYW^aE3r|OKpRJwuCagO6jg-OXAwzVJ7MH z%W6iCbN~08bN6@eIodC~eAbNVNr@v95d=xf&a%$ozh?;V{&D>0s_n8D_^$+a)?6=w z3`iEE=X}pWp+y07uIFE+^w9{Au!FT!Q~C z3}bRxa0<5|O`ahnlojO6l37>}kZBbSYV~@JezHu3E43J|#?&~fQWF}S z(5PgcFS$99|7G&n9mE{#w9a(Al_oFYI5&Y|KA%tFQ!7|cF{U&cjTo-NR4SC8fqDZB zNBU95J2n)gD~=U-DG%-DXqJ%)aY-9n%B9KWLZa}i^SWH_a3aRr$&ROp`AIjXRNz=o zPIfBn<1Y0$gG;kh7;pj?U^p-Dr|i+sUBYs#w}kB_WmxVtF~27{IpN$ruGi)2F}0V= zEaMS$BJI)Bn-_2cY!2|Ur5*}omhqP|wx_G-Xh&poo{A(Wy{;Yj>0aCfCFB-73ZWe` z@z+XNJb>g_PaexU&7o5^s|%sbVhNrq*~EOBv9mt!BohX^MD{xp4OmGInECT)Kye+a z(&s60Laik<>Qvl7;CNJ!&`c;s4r`|!fo?IBgy5}@juABzj=|TDo#e=8iV{6HDvq5Z z9IVGha%S2^76Z)96q~TfVARa;sUj?_llAb+0%o-d>uEU3D|pg~Y{tux3IP%V7uP-C&P z6dyjaEDcHN^>&95)f;VkRH+08)S$8%QKLqu)hksFwOZ}yN)#2WTcVjBn(uq0Gir`- zEp|ScMyWN}_%)-rQl&w4I*k!Es10fq=#02s>riTyl(s8H4`I5c%A&peX$?f3V*V@# zJ6kSz^Xbtp!AS=@l$-Q;flz;G@~#35x3qA_5`2PnOpuh&+su?u9>8wGo*IoTE9}|n zMt9%NXG0K*ALZVA4qpji#L6oaDmbh6AYRtN`A84QDCSSdvs8X4>eFs;coQc47dYwv z!A5w=vhTMI&sJ66XB(gn_5a(3$SI~uNTwLr%~;m~?izTuoeS;f)0Nd#t=%ipB>XuM zd=>L2iVRkd(u8#zi)0SXFA%EHSsI+LSK<5%QwpD*uF*2=I#=8^T83RCp06=9XXg89 zaG}s}l$Y=i8fx#k{LLOP>$F-m-?`vn*kcy$2hIX3&G%ui&`>C0ycsAXUNz0TDMP zT;hBnRl)@U5jQ1V;(Q=g!UX{lHzi!+d>~cA1pyH^C0ycsAXUNz0TDMPT;hBnRl)@U z5jQ1V;(Q=g!UX{lHzi!+d>~cA1pyH^C0ycsAXUNz0TDMPT;hBnRl)@U5jQ1V;(Q=g z!UX{lHzi!+d>~cA1pyH^C0ycsAXUNz0TDMPT;hBnRl)@U5jQ1V;(Q=g!UX{lHzi!+ zd>~cA1pyH^C0ycsAXUNz0TDMPT;hBnRl)@U5jQ1V;(Q=g!UX{lH$`zJMjqh=4FBAw zPk2DH^|+0HxKl=D&B;NK@|O_g-Ngv<;0gbI9YIQQ1nDS35TY7EhOujY{@FAHiN&(5 z8F~JTH)~G6*(!UkF*oTmyfCgRjWMpZU>%l)4I>(3f6?bgY;s_UWldnufsd+K^=yS`k`^VV>Z#Cb3v@-p}|2(NT)j#yC zzg8tbJIs2!>H&=pj-6h&cXI1Hib0vRGy7gz8sD^GTWmweogppE7I3ENz)0lqSB|({ z<^p#9_|&3}pMU%7Lm4TTk~DSuRVUk9`^1lKW05*-X-2wHWlyO4;Pqj}pMq^xU)kL;8{fThd<)=Ydk=8^K7i5Dx2 z_KbgN=)$jc+3}~Ut}L;{RMnPE+3#DI@Y^rh^n+`!E$KgS=-=FMN_x4yeO<)?oeIBrKEf8~N()0-Ik-rA%qEmzAQRqiWn-#%gP#nIq75@b%Vx~s` literal 0 HcmV?d00001 diff --git a/module_main/src/main/res/drawable-xxxhdpi/main_ic_contact.png b/module_main/src/main/res/drawable-xxxhdpi/main_ic_contact.png new file mode 100644 index 0000000000000000000000000000000000000000..802747bf5065205aeff0c560ddff4c3b50bed713 GIT binary patch literal 1550 zcmV+p2J!icP)K}0@_$U9Z#zjtX zrnrO4fc8a1c=)%fN*(rhglBoRsR#L&0=ciMH=9w(Shxka_X$ZOu=}b?eYH9QL>iMv z34qU3)l&_u?rA>36&wH_l6oy3uW3={HPv0|$UU*(YN! zn@qN+3&?jvD@7|+t8cN<>dV*Tc36f6<|aMXIv z3tW7VCi-oH1%TG|+zejR7iGP?R^Xam9RRUv7~pc0)Bu-5$(S?14RD97+|Y43LIHqT zk9iE)GzoZIv*_LFzo9# zy!<#Tfq9`tRSEzT2dtXSNB4xL7dR_Ba#vNExpf@?xaRF>(PVZc#I`3KHvv`s9|t$f7Jp z;((hwGItUj0Cp@f%@q4xt6sh#wW(-?z9OC9109`N_w0|Op6cVvTEg|JhQ=HAbfj7z zJpH)ofKxkv5x{UGs#`Sp!ZsU+pv%~Wxzq=@8X7IV>O?3ve}vb!>-P}V;4*>H!)FU? zR^RUmyqxRR4PY_2OkiZdzF#&=yL}ZCew!hf)eqcN0<*ydy+9qd*8TX7#-Ubm=V<3p zcc28$8*i*fIfsc(w`A({Bdg#-yf|6PrE{?zpTOMf45=Rt){$}X(uXC4M#T3#Bdr0Ov0wI;_!cLV^h<)X} zh~ZUBT%wA^y}9{gtw6095bHB3K5`&i6O7I37TKu%*El4ShFs($qk>($ma8WW6GFcU zje})Mcd3>v^=o{;%NTX7A#5ivJbd<{LJFJMypbO0V0N`9{6A_}l&zxMF3w+x)emYBa|B*DyeQF?tfb>8C; z$MH7?xXQOSzzuMf1S%gJ5;wqA5~zG^NL(ejUkJC%ZHZ;Jg#Z8m07*qoM6N<$f)KIU ADgXcg literal 0 HcmV?d00001 diff --git a/module_main/src/main/res/drawable-xxxhdpi/main_ic_payment.png b/module_main/src/main/res/drawable-xxxhdpi/main_ic_payment.png new file mode 100644 index 0000000000000000000000000000000000000000..7b6b4cc11c6f465078891d2f084f72d63649a0c5 GIT binary patch literal 15300 zcmeI3U2GIp6o7}+QY=40FaZR0vq1QBc4qc(c8A>s>=s*aYg3ACfdI2JciXYMGwaT@ zyDcyLBp6>b(P%*M1w#y2N=yjiZ)rdcPvCp+*%(4PTY`kPv%{%$EKJJ&^OLpcFDNC881oR48WjEAM&9>L2BUbmz0 zaYkz4T___bgqG;WLO3Xeon3~J78oX*&APH4mzL>dxL`2Iux`ffrr``)?^6viN2~f$ z%Sq8s6zEb$NgIl$I!wP}TZ?KwYEnM$vNsSF4G@9(7@%1{?dDrKR`B=)uV)P# z5Lnjc#F~lth-tEt=$qh!6QH$koDbVf)Ca5|Sv15cd9ly6`H>|dp=DB{5m8cNCt%WQ zXNV~e+GdurN~qJ4S_Uo)L_8s;(y+}cpJ_s)svDvzfyQVA4!9IW7WhCQ5nux>9S?8` zn)iC$w8(h@?U#7gABej_ob%-&#$tB!39h4>)MHi)bZs>jS(Bjq^0NGVz#H)Td72N# zd79%ufDX9hK|1L5`*_Zs@OV6lVj!Ed34vb9D6sE|N!uKAFER`!`=q#s6TP$;kXf1+ zy*@hbV*wrab8Zjo6Md53N(i`@3T`HZYEX2Tt$nsEhPj;YY+Jyq<422%q>}GYX)&V% zv;M-)VgZ&~TB&21Hu*XhM9J)J5y>nMAcvT7qvd6lEDL7J#N(VA0?WV6eDWCCE}-Jd z%W{>UHMtXAOBh)(12%NR44F#hTVBVTq3%PB`CpJ!{)2ybv~0OmRg8$c5Dgi&S(*Q!R(sz9AND}R@AG+J7e9i_F>)ZCw!n_gDNT-c1&hyQxpuXqq04gJAfL9_%H0t7D-TzEc+ zmf%8w;6;K9&j-;GTnG@nNO0l#AX4T@FKy5=YwboE(8c(B)IT= z5G}!l0Ktn`T(#v_IDrb^+swijG>i4ymCfMp6CCDQfQliW(h**WW0rhoz|B zcT<#bh@uu~Z|(YeBSlSXX^d`Y&HZ@$`ml15om+k7)NpmGT3N<_I3xS(!Peo+^}*ZD zwQG*7zuLe5(?$E9xv)^at2L@8ha7vWYSh5FH!q)lZIgTX;kO4GHw}KWDg4t>`IVzX z&km}+^#kFHqfhR5Yx&6F&AB`7ocZqB_3F0HZ9jC496z@6#Jlg`Z3?GPsoS?7xVw7m zzN;@^yLbK+J^InH@XzmTyzs@WwzJc3Qn}3^C_4{!&$+bW#x|*TNg#dW{JyH1Io8eM z1+Gh9?z}XxC);<=|I4kzqo*JA*POfc$Kijz(VxifTJd1@(4FeS+>#M;6KNP4tx<;7 z!@Z1~IabwlXn2^d`fE|mi084hOJ*hK%`=uc8&-ZlvYCrt`RwY)3%$d8R?MGSAHIL{ p+f^q9;KCN4`)V3Rjg3`NwQJA(eSc}kdUz64V|`O}@cG^Q{{=9Ex1s<5 literal 0 HcmV?d00001 diff --git a/module_main/src/main/res/drawable-xxxhdpi/main_ic_scan.png b/module_main/src/main/res/drawable-xxxhdpi/main_ic_scan.png new file mode 100644 index 0000000000000000000000000000000000000000..7be7b6400d67675dd18934c3abb77e76c6a648d3 GIT binary patch literal 15343 zcmeI3Yitx%6vw9!w3K%UAXvz{1Y!fTGdr`dnQWJoF3?7{G^NtkwA$&+Y&&*$X5E?6 zZ5y;;z!(#VD32&sMIMF-Y9IuK1gxN+P%s)1#Z(BQ0s@*y2r+tRpVQmzO%pJFxtr|c z-2Xl2-1*&e?#`EavASy6grZqR1VK!wtO(YC?<(_M_yG9axX(5le2tA&H0T5|ZmRh% zAYR+?5J7O)l-hcuKD3+{wWvdov=-Tsh{nKdg77a�TjHf$|&tD=_LZyY^tw<%Jo zz0Mt?L$PwXO{wUP%PYI9YQ^q$k(2C;0!97=4+2DGL$D>H5mo0CrS@c89{e_kDZ4E> z#b__JmzfD|^`UB8xfYjgZij~yX^+?D$3E}C~Sw)D#$ zC<4FyaVgB#1ed1M0jt#BW*9M^qB=V}9i6O0i?>ovj^ikrp%{h)Gf2HlHG~AI>T^>; zGI4^kF2C4?B|bkI~jCrQlu#5&@U z>wL^Yzt$cZ077Q(3 zt7(xys>-S}2yNx%$*QtFTBoRz)~T2HDcB{q-??aVP%z{Gs7D`3dq~Dx>!f+s&AZqI zw2!B0OOVt|C`L$=lyKLO7*3vc^NiCP!!i?&0s2Q03}Hl3taB}KB#{qm@u*+~l&H`u zQ!%yGPvr(JGqY92munF%4wfYcSU;6-*y5F}G`>>R4M7#<%3uHtI21+VeFEoldRUnZ zODso9tcxZEH|rwZt}w%TS*IijOcG)!WOW}BI;e>qX19RQse?t*L=Zl=tQL=(;arS| z^l~j8(&?0aq>pLgNY3SPd!0;}W!Z2hktNuWL@VM7IQN8zWsZ3*5=h31jECVs8H5Fi zB{{E4AUUUpBL$ZzNnsxt@MKfu2{R;Bg`$IM?XpxcsO99zwo-m(@MuPeD9IBlCd75w z?7vcbrUA1@TK2>;eUg353!-_p1w^wwWXVqr8qF;$>zQ^_hHmG`5TxQ;+=tK6*(R%~ z_DY3H&Kf?5u7!)0@yqeVzNrnbs*TbAs>)F`;=1NWO$_J(sv zduC6u`}rexMfWo*6bmPTfS^r`3(W^oF)j!Q+Qhifd>|F$f`Fh+j0?>NQZX(F2-?KB z(0m{j|F$f`Fh+j0?>NQZX(F2-?KB(0m{j|F$f`Fh+ zj0?>NQZX(F2--yAD#|^=DXZYQ%}(%u=68GESq>iVw22ipA%f_hM-aWw6U3c=!1u2N z(Loc$Z_Nb3ZzqTu+UBQDEhUJ8HI>1#+Qj*5Kb)R0>XFGCgr1!R<8CgVIfq=o@!gZF z0#y6XDPPZQuH3p!I`I0fwSUjt_Qor_rV5iL_l}-;uBVXqvX|% zoc*xBl-u(}pL*o_Tjbmuh1(w1Lrnw42kUm6o&D3tSK2pRrF*_sy~}JpAAb3!3`Y zjX7ZS{y8dk<*RiC6MX|<73q)h^XlpehigmY`gON&j(K+XnJ<4_#9S&mwPyFZO{Z@Z zubO0;+dKOA$M(a}l=rAzJ<&$4zhb)Yv%7@qD&D*AO6}#J2aa(!3;Xrr*olG% zGanz0Y58S(q343nbK!&2FH!C1ULKo~%t<}ZHI%cX&$o_$`pvRWw;tX=9xD9fP~py! zEeA`cMbESy^X|PhXa5|{HDg*+!&B~C+ literal 0 HcmV?d00001 diff --git a/module_main/src/main/res/drawable-xxxhdpi/main_ic_transfer.png b/module_main/src/main/res/drawable-xxxhdpi/main_ic_transfer.png new file mode 100644 index 0000000000000000000000000000000000000000..db41da596ecf64d6032d3eba4ffbe9a624944f12 GIT binary patch literal 15538 zcmeI3e{dAl9l#eeF_=U)7wH1vb++vae@*SZK=2lW)p;OQA*|bb)s$w ziye~ew~i0JVYNtt-`eU9(IK@~j7oLg39-4mv4!tm$9o0qqClxH#R3O$QRghFcudyV zl;4{6%Yxs=FlDu*r|9ea)+I(jOIv8UrB+FZ7Pqa2 z%1M(BC+nhFm&201tbtPS%a;%$Y*TPqHXM-r)~K$lEJY=gNn6rsQxYAN-Rt#Iw1aXu zNHBxcHpn`cB4w>A<7C25P}KN@r0S9)TMWNkSn1ULR;v*xcV+h#S95`6Ez1s2q*9zp z*=;mc$VlLGHfm=gmR_2`Q({bvi?Xf(J9|MpHLB=}7FDJRnNv?27@SEcl#5+(z43U# z(3-xq3n0iMEoiB=Y*0n2Nz|0i1TQY_0$Zsnw0m8O#K1Szs%iVr(WGpy5V_F zKLXE2lti4<15%vp5Ghse@KO0e)685}v9(G}Nq}XE0jG~DG;Fd;XBt~CYdR!_7aN6yS|GpaGxnV!!$XmC+><1=e&R>P*N(57ZJY?`-RAxnC|k&Oloo2-m~ z&`f)81~+?RpvDavnva5qVTG#ke3KXc6N=^MSM&7X$DfS^T;3(W`8Vq6dq zw1{z``9NBX3j%@`F)lP8NQ-enK+qz_h2{fkF)j!QTEw`}d>}2x1pz^e7#Erkq{X-( zAZQWeLi2&N7#9QtEn-|~K9CmUf`Fh!j0?>N(qdc?5VVMKq4_{sj0*yS7BMa~A4rRF zK|s(V#)aksX)!Jc2wKFr(0m{*#svXEi%49h`A0ZK89cX{1P^GI#VH$jxYNSdHH8SG zdjUc8^by1-{{`P45kx0V5Es@G1iO*87QH&8ng9ev!3SoESWFM|A7Ofssd!70><1Up3gXI@T^F-#pXA zE^RFO&h|_1%(kw%du-rKyCTJ-k^YhsL&fs?(oZYOHbM=m@ZnzxNy%(p5()^3}3x#5~~;X&@u zh5A2#yJ}~(A zIgS^qcZ_J_qgszffOWp|V#C-k7fL(4>ZY+!@4AiPF<4?5QQqIz-`84f+Q(3PT|4jT zIXZuB&#A6IeK5DeH~fRmr>;J*vQcL1Uw``g;nPQkA9?J%>aKRz#**SBTRs2!wThw+ zV&_omy*+KOy|eqn_ATqHw^VOBFm|*gdg;w0uj*ZM_W$O$&u(kpxP9^8*d3pg?fFO9 z*^|8sHod#&ny`JX`>*G|_1IPBp4X^(AAjZX9de}g=9ha9H)(?Z)f>;!PP@IUb6iA%atEW?T3oWRidNy cKPANXj}t#S6d&IT@{Xuq+8BKP+iN%f51g|vyZ`_I literal 0 HcmV?d00001 diff --git a/module_main/src/main/res/drawable-xxxhdpi/mainic_search.png b/module_main/src/main/res/drawable-xxxhdpi/mainic_search.png new file mode 100644 index 0000000000000000000000000000000000000000..02c7f6868e259bd853629bb947ce9c9318684137 GIT binary patch literal 3225 zcmV;K3}*9*P)KLZ*U+5Lu!Sk^o_Z5E4Meg@_7P6crJiNL9pw)e1;Xm069{HJUZAPk55R%$-RIA z6-eL&AQ0xu!e<4=008gy@A0LT~suv4>S3ILP<0Bm`DLLvaF4FK%)Nj?Pt*r}7;7Xa9z9H|HZjR63e zC`Tj$K)V27Re@400>HumpsYY5E(E}?0f1SyGDiY{y#)Yvj#!WnKwtoXnL;eg03bL5 z07D)V%>y7z1E4U{zu>7~aD})?0RX_umCct+(lZpemCzb@^6=o|A>zVpu|i=NDG+7} zl4`aK{0#b-!z=TL9Wt0BGO&T{GJWpjryhdijfaIQ&2!o}p04JRKYg3k&Tf zVxhe-O!X z{f;To;xw^bEES6JSc$k$B2CA6xl)ltA<32E66t?3@gJ7`36pmX0IY^jz)rRYwaaY4 ze(nJRiw;=Qb^t(r^DT@T3y}a2XEZW-_W%Hszxj_qD**t_m!#tW0KDiJT&R>6OvVTR z07RgHDzHHZ48atvzz&?j9lXF70$~P3Knx_nJP<+#`N z#-MZ2bTkiLfR>_b(HgWKJ%F~Nr_oF3b#wrIijHG|(J>BYjM-sajE6;FiC7vY#};Gd zST$CUHDeuEH+B^pz@B062qXfFfD`NpUW5?BY=V%GM_5c)L#QR}BeW8_2v-S%gfYS= zB9o|3v?Y2H`NVi)In3rTB8+ej^> zQ=~r95NVuDChL%G$=>7$vVg20myx%S50Foi`^m%Pw-h?Xh~i8Mq9jtJloCocWk2Nv zrJpiFnV_ms&8eQ$2&#xWpIS+6pmtC%Q-`S&GF4Q#^mhymh7E(qNMa}%YZ-ePrx>>xFPTiH1=E+A$W$=bG8>s^ zm=Bn5Rah$aDtr}@$`X}2l~$F0mFKEdRdZE8)p@E5RI61Ft6o-prbbn>P~)iy)E2AN zsU20jsWz_8Qg>31P|s0cqrPALg8E|(vWA65poU1JRAaZs8I2(p#xiB`SVGovRs-uS zYnV-9TeA7=Om+qP8+I>yOjAR1s%ETak!GFdam@h^# z)@rS0t$wXH+Irf)+G6c;?H29p+V6F6oj{!|o%K3xI`?%6x;DB|x`n#ibhIR?(H}Q3Gzd138Ei2)WAMz7W9Vy`X}HnwgyEn!VS)>mv$8&{hQn>w4zwy3R}t;BYlZQm5)6pty=DfLrs+A-|>>;~;Q z_F?uV_HFjh9n2gO9o9Q^JA86v({H5aB!kjoO6 zc9$1ZZKsN-Zl8L~mE{`ly3)1N^`o1+o7}D0ZPeY&J;i;i`%NyJ8_8Y6J?}yE@b_5a zam?eLr<8@mESk|3$_SkmS{wQ>%qC18))9_|&j{ZT zes8AvOzF(F2#DZEY>2oYX&IRp`F#{ADl)1r>QS^)ba8a|EY_^#S^HO&t^Rgqwv=MZThqqEWH8 zxJo>d=ABlR_Bh=;eM9Tw|Ih34~oTE|= zX_mAr*D$vzw@+p(E0Yc6dFE}(8oqt`+R{gE3x4zjX+Sb3_cYE^= zgB=w+-tUy`ytONMS8KgRef4hA?t0j zufM;t32jm~jUGrkaOInTZ`zyfns>EuS}G30LFK_G-==(f<51|K&cocp&EJ`SxAh3? zNO>#LI=^+SEu(FqJ)ynt=!~PC9bO$rzPJB=?=j6w@a-(u02P7 zaQ)#(uUl{HW%tYNS3ItC^iAtK(eKlL`f9+{bJzISE?u8_z3;~C8@FyI-5j_jy7l;W z_U#vU3hqqYU3!mrul&B+{ptt$59)uk{;_4iZQ%G|z+lhASr6|H35TBkl>gI*;nGLU zN7W-nBaM%pA0HbH8olyl&XeJ%vZoWz%6?Y=dFykl=imL}`%BMQ{Mhgd`HRoLu6e2R za__6DuR6yg#~-}Tc|Gx_{H@O0eebyMy5GmWADJlpK>kqk(fVV@r_fLLKIeS?{4e)} z^ZO;zpECde03c&XQcVB=dL;k=fP(-4`Tqa_faw4Lbua(`>RI+y?e7jKeZ#YO-C z0mey0K~#9!?3`J01R)GVBdYIzW#t5^&~9&F`G3IuN-{7kAo-(sA4>=XPT)?6r>I|R zVZ}6X3~C3rf@4zqxCI=GtdCQ{RZj}j0IrLmrRMS!CW_!bLe=*q1N-t3F!sv`cq<7S zoRfds9=m{J5wI`qvl<*50JHYT4p!~BEJ}m7oYmH0Et!(Tx(wQGF3bXV60{U}>lABr z%WZvBTW4rHIkHl5BV%2zwlLLAQXH}rcZ=FWmSd`MiGu@VS1HbH*A@LQ!mX-XgKSz} z;}ilXaOnetz&R>TM>M6lTyUClNO1xuaJMYS1Wta) zVqhu#N1aw;b8E5!+#7gotg^D>`Y5)KN4w_V!{Ldbj7z@JB>)xRJU<8l?J)u#oFAp? zG97_2ud-dPuD1u>F9S#2S49ypI1Og$R;{pb)N2yx0L~jCl5#*NaH;=dM8U)GrykAl zrthno2MldU2ktoto~&wu2Py77yg!xrh?TA8NpZ#yIDr$mBjR@e6%TQba~9L^00000 LNkvXXu0mjf%T*az literal 0 HcmV?d00001 diff --git a/module_main/src/main/res/drawable/main_shape_search.xml b/module_main/src/main/res/drawable/main_shape_search.xml new file mode 100644 index 0000000..d766e8c --- /dev/null +++ b/module_main/src/main/res/drawable/main_shape_search.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/module_main/src/main/res/layout/item_of_demo_fragment.xml b/module_main/src/main/res/layout/item_of_demo_fragment.xml new file mode 100644 index 0000000..9f345bd --- /dev/null +++ b/module_main/src/main/res/layout/item_of_demo_fragment.xml @@ -0,0 +1,14 @@ + + + + + + \ No newline at end of file diff --git a/module_main/src/main/res/layout/main_activity_corrdinator_layout.xml b/module_main/src/main/res/layout/main_activity_corrdinator_layout.xml new file mode 100644 index 0000000..473c6aa --- /dev/null +++ b/module_main/src/main/res/layout/main_activity_corrdinator_layout.xml @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/module_main/src/main/res/layout/main_activity_qr_code.xml b/module_main/src/main/res/layout/main_activity_qr_code.xml new file mode 100644 index 0000000..3200908 --- /dev/null +++ b/module_main/src/main/res/layout/main_activity_qr_code.xml @@ -0,0 +1,19 @@ + + + + + + + + \ No newline at end of file diff --git a/module_main/src/main/res/layout/main_demo_activity.xml b/module_main/src/main/res/layout/main_demo_activity.xml new file mode 100644 index 0000000..6a7c99b --- /dev/null +++ b/module_main/src/main/res/layout/main_demo_activity.xml @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/module_main/src/main/res/layout/main_demo_fragment.xml b/module_main/src/main/res/layout/main_demo_fragment.xml new file mode 100644 index 0000000..2b8ebcb --- /dev/null +++ b/module_main/src/main/res/layout/main_demo_fragment.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/module_main/src/main/res/layout/main_fragment_news.xml b/module_main/src/main/res/layout/main_fragment_news.xml new file mode 100644 index 0000000..ddb4959 --- /dev/null +++ b/module_main/src/main/res/layout/main_fragment_news.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/module_main/src/main/res/layout/main_include_open.xml b/module_main/src/main/res/layout/main_include_open.xml new file mode 100644 index 0000000..3d96f85 --- /dev/null +++ b/module_main/src/main/res/layout/main_include_open.xml @@ -0,0 +1,115 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_main/src/main/res/layout/main_include_toolbar_close.xml b/module_main/src/main/res/layout/main_include_toolbar_close.xml new file mode 100644 index 0000000..c00ed71 --- /dev/null +++ b/module_main/src/main/res/layout/main_include_toolbar_close.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/module_main/src/main/res/layout/main_include_toolbar_open.xml b/module_main/src/main/res/layout/main_include_toolbar_open.xml new file mode 100644 index 0000000..f2eda52 --- /dev/null +++ b/module_main/src/main/res/layout/main_include_toolbar_open.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/module_main/src/main/res/values/attr.xml b/module_main/src/main/res/values/attr.xml new file mode 100644 index 0000000..c8aeae3 --- /dev/null +++ b/module_main/src/main/res/values/attr.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/module_main/src/main/res/values/attrs_orange.xml b/module_main/src/main/res/values/attrs_orange.xml new file mode 100644 index 0000000..080521b --- /dev/null +++ b/module_main/src/main/res/values/attrs_orange.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/module_main/src/main/res/values/dimens.xml b/module_main/src/main/res/values/dimens.xml new file mode 100644 index 0000000..da62b5f --- /dev/null +++ b/module_main/src/main/res/values/dimens.xml @@ -0,0 +1,5 @@ + + 180dp + 16dp + 16dp + diff --git a/module_main/src/main/res/values/ids_sticky_nav_layout.xml b/module_main/src/main/res/values/ids_sticky_nav_layout.xml new file mode 100644 index 0000000..e950181 --- /dev/null +++ b/module_main/src/main/res/values/ids_sticky_nav_layout.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/module_main/src/main/res/values/styles.xml b/module_main/src/main/res/values/styles.xml index 7915af4..5bfa0d0 100644 --- a/module_main/src/main/res/values/styles.xml +++ b/module_main/src/main/res/values/styles.xml @@ -20,4 +20,17 @@ @color/white + + + + + diff --git a/module_market/build.gradle b/module_market/build.gradle index 22ab269..c97934a 100644 --- a/module_market/build.gradle +++ b/module_market/build.gradle @@ -57,6 +57,7 @@ dependencies { //公用依赖包 implementation project(':common_base') + //Arouter路由 annotationProcessor rootProject.ext.dependencies["arouter_compiler"] //黄油刀 diff --git a/module_market/src/main/java/com/wss/module/market/ui/goods/cart/ShoppingCartActivity.java b/module_market/src/main/java/com/wss/module/market/ui/goods/cart/ShoppingCartActivity.java index 5f3af53..8774bad 100644 --- a/module_market/src/main/java/com/wss/module/market/ui/goods/cart/ShoppingCartActivity.java +++ b/module_market/src/main/java/com/wss/module/market/ui/goods/cart/ShoppingCartActivity.java @@ -148,7 +148,7 @@ public void onViewClicked(View view) { //删除 ShoppingCartUtils.delete(checkedGoods); } else { - ToastUtils.showToast(mContext, "去结算"); + ToastUtils.show(mContext, "去结算"); } } } diff --git a/module_market/src/main/java/com/wss/module/market/ui/goods/detail/GoodsDetailActivity.java b/module_market/src/main/java/com/wss/module/market/ui/goods/detail/GoodsDetailActivity.java index 824e1f1..8272216 100644 --- a/module_market/src/main/java/com/wss/module/market/ui/goods/detail/GoodsDetailActivity.java +++ b/module_market/src/main/java/com/wss/module/market/ui/goods/detail/GoodsDetailActivity.java @@ -154,11 +154,11 @@ public void run() { }, time * 2 ); } else { - ToastUtils.showToast(mContext, "没有正经的商品信息~"); + ToastUtils.show(mContext, "没有正经的商品信息~"); } } else if (i == R.id.tv_buy_now) { //立即购买 - ToastUtils.showToast(mContext, "立即购买"); + ToastUtils.show(mContext, "立即购买"); } } diff --git a/module_user/src/main/java/com/wss/module/user/ui/account/LoginActivity.java b/module_user/src/main/java/com/wss/module/user/ui/account/LoginActivity.java index 4f317a1..5767f6a 100644 --- a/module_user/src/main/java/com/wss/module/user/ui/account/LoginActivity.java +++ b/module_user/src/main/java/com/wss/module/user/ui/account/LoginActivity.java @@ -76,7 +76,7 @@ public void loginSuccess(User user) { @Override public void onError(Object tag, String errorMsg) { super.onError(tag, errorMsg); - ToastUtils.showToast(mContext, errorMsg); + ToastUtils.show(mContext, errorMsg); } @Override diff --git a/module_user/src/main/java/com/wss/module/user/ui/account/RegisterActivity.java b/module_user/src/main/java/com/wss/module/user/ui/account/RegisterActivity.java index a9be5d9..2569118 100644 --- a/module_user/src/main/java/com/wss/module/user/ui/account/RegisterActivity.java +++ b/module_user/src/main/java/com/wss/module/user/ui/account/RegisterActivity.java @@ -54,12 +54,12 @@ public void viewClick() { if (edtName.getText().toString().trim().length() < 6 || edtPwd.getText().toString().trim().length() < 6 || edtConfirm.getText().toString().trim().length() < 6) { - ToastUtils.showToast(mContext, "用户名或密码长度至少6位!"); + ToastUtils.show(mContext, "用户名或密码长度至少6位!"); return; } if (!TextUtils.equals(edtPwd.getText().toString().trim(), edtConfirm.getText().toString().trim())) { - ToastUtils.showToast(mContext, "两次输入密码不一致!"); + ToastUtils.show(mContext, "两次输入密码不一致!"); edtPwd.setText(""); edtConfirm.setText(""); return; @@ -70,7 +70,7 @@ public void viewClick() { @Override public void onError(Object tag, String errorMsg) { super.onError(tag, errorMsg); - ToastUtils.showToast(mContext, errorMsg); + ToastUtils.show(mContext, errorMsg); } @Override diff --git a/module_user/src/main/java/com/wss/module/user/ui/main/mvp/UserPresenter.java b/module_user/src/main/java/com/wss/module/user/ui/main/mvp/UserPresenter.java index 16944f5..d856f72 100644 --- a/module_user/src/main/java/com/wss/module/user/ui/main/mvp/UserPresenter.java +++ b/module_user/src/main/java/com/wss/module/user/ui/main/mvp/UserPresenter.java @@ -32,7 +32,7 @@ public void onSuccess(boolean success, int code, String msg, Object tag, AppInfo @Override public void onFailure(Object tag, Exception e) { - ToastUtils.showToast(getContext(), Constants.ERROR_MESSAGE); + ToastUtils.show(getContext(), Constants.ERROR_MESSAGE); } @Override diff --git a/module_wan_android/src/main/java/com/wss/module/wan/ui/collection/CollectionActivity.java b/module_wan_android/src/main/java/com/wss/module/wan/ui/collection/CollectionActivity.java index 0fd099e..6219564 100644 --- a/module_wan_android/src/main/java/com/wss/module/wan/ui/collection/CollectionActivity.java +++ b/module_wan_android/src/main/java/com/wss/module/wan/ui/collection/CollectionActivity.java @@ -86,7 +86,7 @@ public void onEmpty(Object tag) { if (page == 0) { showEmptyView("您还没有收藏任何东西"); } else { - ToastUtils.showToast(mContext, "暂无更多收藏~"); + ToastUtils.show(mContext, "暂无更多收藏~"); } } @@ -96,7 +96,7 @@ public void onError(Object tag, String msg) { if (page == 0) { showEmptyView(msg); } else { - ToastUtils.showToast(mContext, msg); + ToastUtils.show(mContext, msg); } } } diff --git a/module_wan_android/src/main/java/com/wss/module/wan/ui/project/ProjectActivity.java b/module_wan_android/src/main/java/com/wss/module/wan/ui/project/ProjectActivity.java index 30aa206..88f48c7 100644 --- a/module_wan_android/src/main/java/com/wss/module/wan/ui/project/ProjectActivity.java +++ b/module_wan_android/src/main/java/com/wss/module/wan/ui/project/ProjectActivity.java @@ -98,7 +98,7 @@ public void onProjectError(String message) { if (page == 1) { showEmptyView(message); } else { - ToastUtils.showToast(mContext, message); + ToastUtils.show(mContext, message); } } @@ -107,7 +107,7 @@ public void onProjectEmpty() { if (page == 1) { showEmptyView("暂无项目数据"); } else { - ToastUtils.showToast(mContext, "暂无更多项目数据"); + ToastUtils.show(mContext, "暂无更多项目数据"); } } diff --git a/module_wan_android/src/main/java/com/wss/module/wan/ui/search/SearchActivity.java b/module_wan_android/src/main/java/com/wss/module/wan/ui/search/SearchActivity.java index 0818bc0..f7622e4 100644 --- a/module_wan_android/src/main/java/com/wss/module/wan/ui/search/SearchActivity.java +++ b/module_wan_android/src/main/java/com/wss/module/wan/ui/search/SearchActivity.java @@ -107,7 +107,7 @@ public void onError(Object tag, String errorMsg) { if (page == 0) { showErrorView(errorMsg); } else { - ToastUtils.showToast(mContext, errorMsg); + ToastUtils.show(mContext, errorMsg); } } @@ -117,7 +117,7 @@ public void onEmpty(Object tag) { if (page == 0) { showEmptyView("木有搜到你想要的"); } else { - ToastUtils.showToast(mContext, "没有更多啦~"); + ToastUtils.show(mContext, "没有更多啦~"); } } } diff --git a/module_wan_android/src/main/java/com/wss/module/wan/ui/setup/SystemArticleActivity.java b/module_wan_android/src/main/java/com/wss/module/wan/ui/setup/SystemArticleActivity.java index 9c88156..bc0bdb4 100644 --- a/module_wan_android/src/main/java/com/wss/module/wan/ui/setup/SystemArticleActivity.java +++ b/module_wan_android/src/main/java/com/wss/module/wan/ui/setup/SystemArticleActivity.java @@ -99,7 +99,7 @@ public void onError(Object tag, String errorMsg) { if (page == 0) { showErrorView(errorMsg); } else { - ToastUtils.showToast(mContext, errorMsg); + ToastUtils.show(mContext, errorMsg); } } @@ -109,7 +109,7 @@ public void onEmpty(Object tag) { if (page == 0) { showEmptyView(); } else { - ToastUtils.showToast(mContext, "暂无更多数据"); + ToastUtils.show(mContext, "暂无更多数据"); } } From 9427d5c9a3e169a57492e7760c0654c0f5a2dacd Mon Sep 17 00:00:00 2001 From: wutq Date: Thu, 13 Aug 2020 16:33:49 +0800 Subject: [PATCH 06/23] =?UTF-8?q?=E5=8D=87=E7=BA=A7=E4=B8=BAandroidX,?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=BD=91=E7=BB=9C=E8=AF=B7=E6=B1=82,?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E4=B8=80=E4=BA=9B=E4=B8=8D=E5=90=88=E7=90=86?= =?UTF-8?q?=E7=9A=84=E5=9C=B0=E6=96=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 13 +- app/build.gradle | 22 +- app/src/main/AndroidManifest.xml | 10 + .../java/com/wss/amd/app/AppApplication.java | 10 +- .../com/wss/amd/main/LoadingActivity.java | 37 + .../java/com/wss/amd/profile/DevProfile.java | 21 + .../com/wss/amd/profile/ProfileFactory.java | 18 + .../src/main/res/layout/activity_loading.xml | 7 +- build.gradle | 35 +- common_base/build.gradle | 78 +- common_base/src/main/AndroidManifest.xml | 5 +- .../src/main/assets/iconfont/iconfont.ttf | Bin 0 -> 16232 bytes .../wss/common/activity/WebViewActivity.java | 91 -- .../wss/common/adapter/BannerImgAdapter.java | 29 +- .../common/adapter/FragmentPagerAdapter.java | 38 +- .../wss/common/base/ActionBarActivity.java | 43 - .../common/base/BaseActionBarActivity.java | 240 ++++ .../com/wss/common/base/BaseActivity.java | 253 ++-- .../com/wss/common/base/BaseApplication.java | 244 +++- .../com/wss/common/base/BaseFragment.java | 142 +- .../common/base/BaseFullScreenActivity.java | 34 + ...ty.java => BaseHorizontalTabActivity.java} | 21 +- .../com/wss/common/base/BaseMvpActivity.java | 51 +- .../com/wss/common/base/BaseMvpFragment.java | 48 +- .../common/base/BaseRefreshListActivity.java | 114 ++ .../common/base/BaseRefreshListFragment.java | 112 ++ .../wss/common/base/RefreshListActivity.java | 77 -- .../wss/common/base/RefreshListFragment.java | 77 -- .../common/base/adapter/BaseListAdapter.java | 48 +- .../listener/OnListItemClickListener.java | 16 + .../com/wss/common/base/bean/BaseBean.java | 3 +- .../com/wss/common/base/mvp/BaseModel.java | 27 + .../wss/common/base/mvp/BasePresenter.java | 60 +- .../com/wss/common/base/mvp/IBaseModel.java | 10 - .../com/wss/common/base/mvp/IBaseView.java | 11 +- .../java/com/wss/common/bean/AppInfo.java | 33 - .../main/java/com/wss/common/bean/Banner.java | 35 + .../main/java/com/wss/common/bean/Event.java | 15 +- .../wss/common/bean/HorizontalTabTitle.java | 10 +- .../com/wss/common/bean/SelectorData.java | 29 + .../java/com/wss/common/bean/Template.java | 34 +- .../main/java/com/wss/common/bean/User.java | 11 +- .../wss/common/constants/ARouterConfig.java | 1 - .../com/wss/common/constants/CacheKey.java | 21 - .../com/wss/common/constants/Constants.java | 156 ++- .../com/wss/common/constants/DBConfig.java | 13 - .../java/com/wss/common/constants/Dic.java | 76 + .../com/wss/common/constants/EventAction.java | 16 +- .../com/wss/common/dao/BaseDBManager.java | 1 - .../com/wss/common/dao/DBMigrationHelper.java | 310 +++-- .../common/exception/NetErrorException.java | 53 + .../listener/OnListItemClickListener.java | 13 - .../com/wss/common/manage/ActivityManage.java | 7 +- .../wss/common/manage/ActivityToActivity.java | 304 ++++ .../wss/common/manage/BlurTransformation.java | 23 +- .../wss/common/manage/CrashHandlerManage.java | 188 --- .../common/manage/GlideRoundTransform.java | 60 + .../com/wss/common/manage/UpdateManager.java | 144 -- .../src/main/java/com/wss/common/net/Api.java | 14 +- .../java/com/wss/common/net/HttpUtils.java | 310 ----- .../java/com/wss/common/net/NetConfig.java | 64 - .../com/wss/common/net/NetworkManage.java | 505 +++++++ .../java/com/wss/common/net/RequestParam.java | 94 -- .../common/net/callback/OnResultCallBack.java | 98 -- .../wss/common/net/request/RequestParam.java | 133 ++ .../wss/common/net/response/BaseResponse.java | 34 + .../java/com/wss/common/profile/IProfile.java | 17 + .../wss/common/profile/IProfileFactory.java | 15 + .../wss/common/profile/ProfileManager.java | 41 + .../java/com/wss/common/secret/AesUtils.java | 66 + .../main/java/com/wss/common/secret/MD5.java | 64 + .../wss/common/secret/ParseSystemUtil.java | 50 + .../com/wss/common/utils/ARouterUtils.java | 2 - .../wss/common/utils/ActivityToActivity.java | 162 --- .../com/wss/common/utils/BeanCopyUtils.java | 3 + .../java/com/wss/common/utils/CacheUtils.java | 137 +- .../java/com/wss/common/utils/DateUtils.java | 220 ++- .../com/wss/common/utils/EventBusUtils.java | 19 +- .../java/com/wss/common/utils/FileUtils.java | 156 ++- .../java/com/wss/common/utils/GroupUtils.java | 15 +- .../java/com/wss/common/utils/ImageUtils.java | 520 ++++++- .../java/com/wss/common/utils/JsonUtils.java | 306 ++++ .../com/wss/common/utils/KeyboardUtils.java | 24 +- .../java/com/wss/common/utils/MoneyUtils.java | 102 +- .../com/wss/common/utils/NetworkUtil.java | 123 +- .../wss/common/utils/PermissionsUtils.java | 51 +- .../java/com/wss/common/utils/PhoneUtils.java | 46 + .../java/com/wss/common/utils/PxUtils.java | 48 +- .../java/com/wss/common/utils/RomUtil.java | 152 ++ .../wss/common/utils/SelectorPopupWindow.java | 175 +++ .../com/wss/common/utils/SystemUtils.java | 247 ++++ .../java/com/wss/common/utils/ToastUtils.java | 374 ++++- .../com/wss/common/utils/UserInfoUtils.java | 61 - .../main/java/com/wss/common/utils/Utils.java | 100 +- .../java/com/wss/common/utils/ValidUtils.java | 39 + .../java/com/wss/common/utils/ZipUtils.java | 390 ------ .../com/wss/common/utils/toast/BaseToast.java | 70 + .../common/utils/toast/IToastInterceptor.java | 21 + .../common/utils/toast/IToastStrategy.java | 40 + .../wss/common/utils/toast/IToastStyle.java | 101 ++ .../wss/common/utils/toast/SafeHandler.java | 34 + .../com/wss/common/utils/toast/SafeToast.java | 39 + .../wss/common/utils/toast/SupportToast.java | 32 + .../wss/common/utils/toast/ToastHelper.java | 152 ++ .../common/utils/toast/ToastInterceptor.java | 18 + .../wss/common/utils/toast/ToastStrategy.java | 144 ++ .../wss/common/utils/toast/WindowHelper.java | 91 ++ .../utils/toast/style/BaseToastStyle.java | 72 + .../utils/toast/style/ToastBlackStyle.java | 46 + .../wss/common/view/SpringboardActivity.java | 44 + .../common/view/browser/BrowserActivity.java | 476 +++++++ .../view/browser/mvp/BrowserPresenter.java | 22 + .../browser/mvp/contract/BrowserContract.java | 23 + .../view/browser/mvp/model/BrowserModel.java | 17 + .../common/view/file/SelectFileActivity.java | 135 ++ .../view/file/adapter/SelectFileAdapter.java | 53 + .../adapter/holder/SelectFileViewHolder.java | 33 + .../wss/common/view/file/bean/FileInfo.java | 28 + .../view/file/mvp/SelectFilePresenter.java | 36 + .../file/mvp/contract/SelectFileContract.java | 48 + .../view/file/mvp/model/SelectFileModel.java | 202 +++ .../scaleImg => view/gallery}/IOThread.java | 2 +- .../gallery}/ImageDownloader.java | 10 +- .../wss/common/view/gallery/ImageGallery.java | 36 + .../view/gallery/ImageGalleryActivity.java | 230 +++ .../gallery}/ImageViewerAdapter.java | 18 +- .../wss/common/view/scan/ScanActivity.java | 106 ++ .../java/com/wss/common/widget/ActionBar.java | 54 +- .../com/wss/common/widget/AutoTextView.java | 65 + .../com/wss/common/widget/CountClickView.java | 54 +- .../wss/common/widget/EnhanceEditText.java | 388 ++++++ .../com/wss/common/widget/FlowLayout.java | 10 +- .../wss/common/widget/GradientTextView.java | 56 + .../com/wss/common/widget/HinderWebView.java | 1 - .../wss/common/widget/IconFontTextView.java | 94 ++ .../com/wss/common/widget/LVCircularRing.java | 4 +- .../wss/common/widget/MultipleItemView.java | 21 +- .../wss/common/widget/NoScrollGridView.java | 47 + .../wss/common/widget/NoScrollListView.java | 38 + .../wss/common/widget/NoScrollViewPager.java | 3 +- .../wss/common/widget/NumberProgressBar.java | 42 +- .../com/wss/common/widget/ObserverButton.java | 11 +- .../common/widget/PagerSlidingTabStrip.java | 356 +++-- .../wss/common/widget/ProgressWebView.java | 108 -- .../com/wss/common/widget/SlideLayout.java | 8 +- .../wss/common/widget/StickyNavLayout.java | 394 ++++++ .../wss/common/widget/StrongRadioGroup.java | 16 +- .../wss/common/widget/SwipeItemLayout.java | 780 +++++++++++ .../common/widget/ViewPagerForScrollView.java | 126 ++ .../wss/common/widget/WebViewProgressBar.java | 44 - .../wss/common/widget/dialog/AppDialog.java | 1232 +++++++++++------ .../wss/common/widget/dialog/DateDialog.java | 261 ++++ .../wss/common/widget/dialog/DialogType.java | 37 +- .../common/widget/dialog/LoadingDialog.java | 12 +- .../widget/dialog/OnButtonClickListener.java | 15 + .../widget/dialog/OnItemClickListener.java | 16 + .../ScrollSpeedLinearLayoutManger.java | 79 ++ .../widget/pulltorefresh/IRefreshView.java | 42 - .../pulltorefresh/OnPullRefreshListener.java | 19 - .../pulltorefresh/PullToRefreshLayout.java | 578 -------- .../widget/pulltorefresh/RefreshView.java | 97 -- .../common/widget/pulltorefresh/State.java | 22 - .../widget/pulltorefresh/ViewStatus.java | 25 - .../common/widget/scaleImg/ImageViewer.java | 300 ---- .../main/res/color/selector_text_color.xml | 5 + .../src/main/res/color/tab_text_color.xml | 5 + .../bg_of_color_f5_4radius.xml | 6 + .../drawable-xxhdpi/header_load_default.png | Bin 0 -> 9374 bytes .../main/res/drawable-xxhdpi/icon_back.png | Bin 0 -> 612 bytes .../main/res/drawable-xxhdpi/icon_refresh.png | Bin 0 -> 1094 bytes .../main/res/drawable/browser_progress_bg.xml | 15 + .../main/res/drawable/corners_black_shape.xml | 8 + .../res/drawable/corners_theme_shape_45.xml | 8 + .../res/drawable/stroke_gray_white_shape.xml | 12 + .../src/main/res/layout/action_bar.xml | 12 +- .../src/main/res/layout/activity_base.xml | 13 +- .../src/main/res/layout/activity_browser.xml | 108 ++ .../res/layout/activity_horizontal_tab.xml | 6 +- .../res/layout/activity_image_gallery.xml | 46 + .../src/main/res/layout/activity_scan.xml | 36 + .../main/res/layout/activity_select_file.xml | 9 +- .../main/res/layout/activity_springboard.xml | 6 + .../src/main/res/layout/activity_webview.xml | 11 - .../main/res/layout/base_tablayout_child.xml | 13 + .../src/main/res/layout/dailog_date.xml | 38 + .../src/main/res/layout/dialog_app.xml | 121 +- .../src/main/res/layout/dialog_loading.xml | 2 +- .../main/res/layout/dialog_scale_image.xml | 53 - .../src/main/res/layout/empty_layout.xml | 24 - .../main/res/layout/item_of_load_all_data.xml | 17 + .../main/res/layout/item_of_select_file.xml | 27 + .../main/res/layout/item_of_select_image.xml | 26 + .../main/res/layout/item_of_selector_pop.xml | 21 + .../src/main/res/layout/layout_banner_img.xml | 2 +- .../{fragment_base.xml => layout_base.xml} | 3 +- .../src/main/res/layout/layout_empty.xml | 34 +- .../src/main/res/layout/layout_error.xml | 24 - .../layout_item_of_dialog_bottom_in.xml | 6 +- .../src/main/res/layout/layout_loading.xml | 18 - .../src/main/res/layout/layout_nothing.xml | 5 + .../src/main/res/layout/layout_refresh.xml | 14 +- .../main/res/layout/layout_refresh_view.xml | 35 - .../src/main/res/layout/layout_search.xml | 49 + .../src/main/res/layout/pop_date_range.xml | 111 ++ .../src/main/res/layout/pop_selector.xml | 19 +- common_base/src/main/res/layout/toast.xml | 16 - .../res/layout/update_progress_layout.xml | 29 - .../src/main/res/layout/view_scale_image.xml | 11 - common_base/src/main/res/values/attrs.xml | 115 +- common_base/src/main/res/values/colors.xml | 4 + common_base/src/main/res/values/dimens.xml | 6 + common_base/src/main/res/values/strings.xml | 155 ++- common_base/src/main/res/values/styles.xml | 5 + config.gradle | 231 ++-- gradle.properties | 7 +- gradle/wrapper/gradle-wrapper.properties | 2 +- module_main/README.txt | 11 + module_main/build.gradle | 4 +- module_main/doc.txt | 3 - module_main/src/main/AndroidManifest.xml | 47 +- .../main/ui/hortab/OrderListActivity.java | 50 - .../ui/hortab/adapter/OrderListAdapter.java | 94 -- .../ui/hortab/fragment/OrderFragment.java | 125 -- .../main/ui/hortab/mvp/OrderPresenter.java | 81 -- .../ui/hortab/mvp/contract/OrderContract.java | 44 - .../com/wss/module/main/ui/im/IMActivity.java | 97 -- .../module/main/ui/im/IMUserInfoActivity.java | 45 - .../module/main/ui/im/adapter/IMAdapter.java | 74 - .../main/ui/loading/LoadingActivity.java | 51 - .../wss/module/main/ui/main/MainActivity.java | 117 +- ...CenterRcyAdapter.java => CaseAdapter.java} | 13 +- .../main/ui/main/fragment/CaseFragment.java | 50 + .../main/ui/main/fragment/CenterFragment.java | 65 - .../main/ui/main/mvp/CasePresenter.java | 53 + .../module/main/ui/main/mvp/MainModel.java | 27 - .../main/ui/main/mvp/MainPresenter.java | 93 -- .../ui/main/mvp/contract/CaseContract.java | 32 + .../ui/main/mvp/contract/MainContract.java | 56 - .../main/ui/main/mvp/model/CaseModel.java | 17 + .../main/ui/page/CountViewActivity.java | 7 +- .../module/main/ui/page/DialogActivity.java | 119 +- .../main/ui/page/FlowLayoutActivity.java | 7 +- .../main/ui/page/MultipleItemActivity.java | 7 +- .../main/ui/page/ObserverButtonActivity.java | 9 +- .../module/main/ui/page/QRCodeActivity.java | 64 - .../main/ui/page/RadioGroupActivity.java | 17 +- .../main/ui/page/ScaleImageActivity.java | 54 - .../module/main/ui/page/YumanmanActivity.java | 196 --- .../ui/refresh/RefreshStringActivity.java | 83 -- .../ui/refresh/adapter/StringAdapter.java | 29 - .../main/ui/refresh/mvp/StringPresenter.java | 63 - .../refresh/mvp/contract/RefreshContract.java | 38 - .../main/ui/selector/SelectorActivity.java | 82 +- .../main/ui/selector/mvp/SelectorModule.java | 32 - .../ui/selector/mvp/SelectorPresenter.java | 66 +- .../selector/mvp/contract/SelectContract.java | 16 +- .../ui/selector/mvp/model/SelectorModule.java | 42 + .../src/main/module/AndroidManifest.xml | 16 +- .../main/res/layout/item_of_demo_fragment.xml | 14 - .../main_activity_corrdinator_layout.xml | 134 -- .../res/layout/main_activity_count_view.xml | 2 +- .../main/res/layout/main_activity_dialog.xml | 15 - .../res/layout/main_activity_flow_layout.xml | 242 +++- .../layout/main_activity_horizontal_tab.xml | 28 - .../src/main/res/layout/main_activity_im.xml | 57 - .../res/layout/main_activity_im_user_info.xml | 23 - .../main/res/layout/main_activity_main.xml | 19 +- .../layout/main_activity_observer_button.xml | 2 +- .../main/res/layout/main_activity_qr_code.xml | 19 - .../main/res/layout/main_activity_refresh.xml | 13 - .../res/layout/main_activity_yumanman.xml | 148 -- .../main/res/layout/main_demo_activity.xml | 76 - .../main/res/layout/main_demo_fragment.xml | 27 - .../main/res/layout/main_fragment_case.xml | 7 + .../main/res/layout/main_fragment_news.xml | 55 - .../src/main/res/layout/main_include_open.xml | 115 -- .../res/layout/main_include_toolbar_close.xml | 46 - .../res/layout/main_include_toolbar_open.xml | 40 - ...er_list.xml => main_item_of_case_list.xml} | 17 +- .../main/res/layout/main_item_of_im_left.xml | 29 - .../main/res/layout/main_item_of_im_right.xml | 31 - .../layout/main_item_of_order_goods_list.xml | 40 - .../res/layout/main_item_of_order_list.xml | 53 - .../res/layout/main_item_of_string_list.xml | 16 - module_main/src/main/res/values/strings.xml | 2 +- module_market/README.txt | 11 + module_market/build.gradle | 9 +- module_market/doc.txt | 4 - .../com/wss/module/market/bean/GoodsInfo.java | 25 +- .../wss/module/market/db/MarketDBFactory.java | 2 +- .../wss/module/market/db/MarketDBManage.java | 4 +- .../ui/goods/cart/ShoppingCartActivity.java | 52 +- .../cart/adapter/ShoppingCartAdapter.java | 9 +- .../ui/goods/cart/mvp/CartPresenter.java | 20 +- .../mvp/contract/ShoppingCartContract.java | 8 +- .../cart/mvp/model/ShoppingCartModel.java | 17 + .../ui/goods/detail/GoodsDetailActivity.java | 16 +- .../detail/adapter/GoodsCommentAdapter.java | 7 +- .../detail/adapter/GoodsConfigAdapter.java | 4 +- .../detail/adapter/RecommendGoodsAdapter.java | 17 +- .../adapter/RecommendGoodsInfoAdapter.java | 10 +- .../fragment/GoodsInfoDetailMainFragment.java | 6 +- .../fragment/GoodsInfoMainFragment.java | 25 +- .../fragment/child/GoodsCommentFragment.java | 14 +- .../fragment/child/GoodsConfigFragment.java | 2 +- .../goods/detail/mvp/GoodsCommentPresent.java | 167 ++- .../detail/mvp/GoodsDetailPresenter.java | 192 ++- .../mvp/contract/GoodsCommentContract.java | 7 +- .../mvp/contract/GoodsDetailContract.java | 15 +- .../detail/mvp/model/GoodsCommentModel.java | 17 + .../detail/mvp/model/GoodsDetailModel.java | 17 + .../market/ui/main/MarketMainActivity.java | 65 +- .../ui/main/adapter/MarketMainAdapter.java | 20 +- .../ui/main/mvp/MarketMainPresenter.java | 33 +- .../main/mvp/contract/MarketMainContract.java | 7 +- .../ui/main/mvp/model/MarketMainModel.java | 17 + .../market/utils/ShoppingCartUtils.java | 1 - .../layout/market_activity_goods_details.xml | 7 +- .../layout/market_activity_market_mian.xml | 2 +- .../layout/market_activity_shopping_cart.xml | 2 +- .../layout/market_fragment_goods_comment.xml | 2 +- .../market_fragment_goods_info_main.xml | 4 +- .../layout/market_item_of_goods_recommend.xml | 2 +- module_user/README.txt | 11 + module_user/build.gradle | 8 +- .../module/user/common/UserApplication.java | 1 - .../module/user/ui/about/AboutActivity.java | 13 +- .../module/user/ui/account/LoginActivity.java | 37 +- .../user/ui/account/RegisterActivity.java | 50 +- .../user/ui/account/mvp/LoginModel.java | 29 - .../user/ui/account/mvp/LoginPresenter.java | 59 +- .../user/ui/account/mvp/RegisterModel.java | 29 - .../ui/account/mvp/RegisterPresenter.java | 57 +- .../account/mvp/contract/LoginContract.java | 31 +- .../mvp/contract/RegisterContract.java | 29 +- .../user/ui/account/mvp/model/LoginModel.java | 31 + .../ui/account/mvp/model/RegisterModel.java | 31 + .../module/user/ui/main/UserMainActivity.java | 1 - .../user/ui/main/fragment/UserFragment.java | 118 +- .../module/user/ui/main/mvp/UserModel.java | 26 - .../user/ui/main/mvp/UserPresenter.java | 42 +- .../ui/main/mvp/contract/UserContract.java | 23 +- .../user/ui/main/mvp/model/UserModel.java | 17 + module_wan_android/README.txt | 11 + module_wan_android/build.gradle | 8 +- .../src/main/AndroidManifest.xml | 4 +- .../java/com/wss/module/wan/bean/Article.java | 2 +- .../wan/ui/collection/CollectionActivity.java | 76 +- .../ui/collection/mvp/CollectionModel.java | 21 - .../collection/mvp/CollectionPresenter.java | 51 +- .../mvp/contract/CollectionContract.java | 16 +- .../collection/mvp/model/CollectionModel.java | 27 + .../module/wan/ui/main/WanMainActivity.java | 1 - .../wan/ui/main/adapter/ArticleAdapter.java | 23 +- ...meRcyAdapter.java => HomeMenuAdapter.java} | 11 +- .../wan/ui/main/fragment/HomeFragment.java | 183 ++- .../wss/module/wan/ui/main/mvp/HomeModel.java | 32 - .../module/wan/ui/main/mvp/HomePresenter.java | 153 +- .../ui/main/mvp/contract/HomeContract.java | 56 +- .../wan/ui/main/mvp/model/HomeModel.java | 39 + .../wan/ui/project/ProjectActivity.java | 145 +- .../wan/ui/project/TypePopupWindow.java | 23 +- .../project/adapter/ProjectListAdapter.java | 12 +- .../wan/ui/project/mvp/ProjectModel.java | 28 - .../wan/ui/project/mvp/ProjectPresenter.java | 85 +- .../project/mvp/contract/ProjectContract.java | 37 +- .../ui/project/mvp/model/ProjectModel.java | 34 + .../module/wan/ui/search/SearchActivity.java | 76 +- .../wan/ui/search/mvp/SearchModule.java | 20 - .../wan/ui/search/mvp/SearchPresenter.java | 47 +- .../search/mvp/contract/SearchContract.java | 23 +- .../wan/ui/search/mvp/model/SearchModule.java | 26 + .../module/wan/ui/series/SeriesActivity.java | 122 ++ .../wan/ui/series/SeriesArticleActivity.java | 130 ++ .../adapter/SeriesAdapter.java} | 13 +- .../adapter/SetupRightAdapter.java | 11 +- .../ui/series/mvp/SeriesArticlePresenter.java | 45 + .../wan/ui/series/mvp/SeriesPresenter.java | 34 + .../mvp/contract/SeriesArticleContract.java | 58 + .../series/mvp/contract/SeriesContract.java | 40 + .../series/mvp/model/SeriesArticleModel.java | 25 + .../wan/ui/series/mvp/model/SeriesModel.java | 29 + .../module/wan/ui/setup/SystemActivity.java | 104 -- .../wan/ui/setup/SystemArticleActivity.java | 122 -- .../wan/ui/setup/mvp/SystemArticleModel.java | 21 - .../ui/setup/mvp/SystemArticlePresenter.java | 64 - .../module/wan/ui/setup/mvp/SystemModel.java | 20 - .../wan/ui/setup/mvp/SystemPresenter.java | 57 - .../mvp/contract/SystemArticleContract.java | 54 - .../ui/setup/mvp/contract/SystemContract.java | 44 - .../wan/ui/wxnumber/WXNumberActivity.java | 58 +- .../ui/wxnumber/adapter/WXArticleAdapter.java | 7 +- .../wxnumber/fragment/WXArticleFragment.java | 97 +- .../wan/ui/wxnumber/mvp/WXArticleModel.java | 21 - .../ui/wxnumber/mvp/WXArticlePresenter.java | 71 +- .../ui/wxnumber/mvp/WXNumberPresenter.java | 35 + .../mvp/contract/WXArticleContract.java | 59 + .../mvp/contract/WXNumberContract.java | 38 +- .../ui/wxnumber/mvp/model/WXArticleModel.java | 25 + .../ui/wxnumber/mvp/model/WXNumberModel.java | 29 + .../src/main/module/AndroidManifest.xml | 4 +- ...vity_setup.xml => wan_activity_series.xml} | 4 +- .../src/main/res/layout/wan_fragment_main.xml | 73 +- .../res/layout/wan_item_of_block_list.xml | 4 +- .../main/res/layout/wan_pop_project_pop.xml | 2 +- settings.gradle | 7 +- 406 files changed, 15425 insertions(+), 10278 deletions(-) create mode 100644 app/src/main/java/com/wss/amd/main/LoadingActivity.java create mode 100644 app/src/main/java/com/wss/amd/profile/DevProfile.java create mode 100644 app/src/main/java/com/wss/amd/profile/ProfileFactory.java rename module_main/src/main/res/layout/main_activity_loading.xml => app/src/main/res/layout/activity_loading.xml (54%) create mode 100644 common_base/src/main/assets/iconfont/iconfont.ttf delete mode 100644 common_base/src/main/java/com/wss/common/activity/WebViewActivity.java delete mode 100644 common_base/src/main/java/com/wss/common/base/ActionBarActivity.java create mode 100644 common_base/src/main/java/com/wss/common/base/BaseActionBarActivity.java create mode 100644 common_base/src/main/java/com/wss/common/base/BaseFullScreenActivity.java rename common_base/src/main/java/com/wss/common/base/{HorizontalTabActivity.java => BaseHorizontalTabActivity.java} (71%) create mode 100644 common_base/src/main/java/com/wss/common/base/BaseRefreshListActivity.java create mode 100644 common_base/src/main/java/com/wss/common/base/BaseRefreshListFragment.java delete mode 100644 common_base/src/main/java/com/wss/common/base/RefreshListActivity.java delete mode 100644 common_base/src/main/java/com/wss/common/base/RefreshListFragment.java create mode 100644 common_base/src/main/java/com/wss/common/base/adapter/listener/OnListItemClickListener.java create mode 100644 common_base/src/main/java/com/wss/common/base/mvp/BaseModel.java delete mode 100644 common_base/src/main/java/com/wss/common/base/mvp/IBaseModel.java delete mode 100644 common_base/src/main/java/com/wss/common/bean/AppInfo.java create mode 100644 common_base/src/main/java/com/wss/common/bean/Banner.java create mode 100644 common_base/src/main/java/com/wss/common/bean/SelectorData.java delete mode 100644 common_base/src/main/java/com/wss/common/constants/CacheKey.java delete mode 100644 common_base/src/main/java/com/wss/common/constants/DBConfig.java create mode 100644 common_base/src/main/java/com/wss/common/constants/Dic.java create mode 100644 common_base/src/main/java/com/wss/common/exception/NetErrorException.java delete mode 100644 common_base/src/main/java/com/wss/common/listener/OnListItemClickListener.java create mode 100644 common_base/src/main/java/com/wss/common/manage/ActivityToActivity.java delete mode 100644 common_base/src/main/java/com/wss/common/manage/CrashHandlerManage.java create mode 100644 common_base/src/main/java/com/wss/common/manage/GlideRoundTransform.java delete mode 100644 common_base/src/main/java/com/wss/common/manage/UpdateManager.java delete mode 100644 common_base/src/main/java/com/wss/common/net/HttpUtils.java delete mode 100644 common_base/src/main/java/com/wss/common/net/NetConfig.java create mode 100644 common_base/src/main/java/com/wss/common/net/NetworkManage.java delete mode 100644 common_base/src/main/java/com/wss/common/net/RequestParam.java delete mode 100644 common_base/src/main/java/com/wss/common/net/callback/OnResultCallBack.java create mode 100644 common_base/src/main/java/com/wss/common/net/request/RequestParam.java create mode 100644 common_base/src/main/java/com/wss/common/net/response/BaseResponse.java create mode 100644 common_base/src/main/java/com/wss/common/profile/IProfile.java create mode 100644 common_base/src/main/java/com/wss/common/profile/IProfileFactory.java create mode 100644 common_base/src/main/java/com/wss/common/profile/ProfileManager.java create mode 100644 common_base/src/main/java/com/wss/common/secret/AesUtils.java create mode 100644 common_base/src/main/java/com/wss/common/secret/MD5.java create mode 100644 common_base/src/main/java/com/wss/common/secret/ParseSystemUtil.java delete mode 100644 common_base/src/main/java/com/wss/common/utils/ActivityToActivity.java create mode 100644 common_base/src/main/java/com/wss/common/utils/JsonUtils.java create mode 100644 common_base/src/main/java/com/wss/common/utils/PhoneUtils.java create mode 100644 common_base/src/main/java/com/wss/common/utils/RomUtil.java create mode 100644 common_base/src/main/java/com/wss/common/utils/SelectorPopupWindow.java create mode 100644 common_base/src/main/java/com/wss/common/utils/SystemUtils.java delete mode 100644 common_base/src/main/java/com/wss/common/utils/UserInfoUtils.java create mode 100644 common_base/src/main/java/com/wss/common/utils/ValidUtils.java delete mode 100644 common_base/src/main/java/com/wss/common/utils/ZipUtils.java create mode 100644 common_base/src/main/java/com/wss/common/utils/toast/BaseToast.java create mode 100644 common_base/src/main/java/com/wss/common/utils/toast/IToastInterceptor.java create mode 100644 common_base/src/main/java/com/wss/common/utils/toast/IToastStrategy.java create mode 100644 common_base/src/main/java/com/wss/common/utils/toast/IToastStyle.java create mode 100644 common_base/src/main/java/com/wss/common/utils/toast/SafeHandler.java create mode 100644 common_base/src/main/java/com/wss/common/utils/toast/SafeToast.java create mode 100644 common_base/src/main/java/com/wss/common/utils/toast/SupportToast.java create mode 100644 common_base/src/main/java/com/wss/common/utils/toast/ToastHelper.java create mode 100644 common_base/src/main/java/com/wss/common/utils/toast/ToastInterceptor.java create mode 100644 common_base/src/main/java/com/wss/common/utils/toast/ToastStrategy.java create mode 100644 common_base/src/main/java/com/wss/common/utils/toast/WindowHelper.java create mode 100644 common_base/src/main/java/com/wss/common/utils/toast/style/BaseToastStyle.java create mode 100644 common_base/src/main/java/com/wss/common/utils/toast/style/ToastBlackStyle.java create mode 100644 common_base/src/main/java/com/wss/common/view/SpringboardActivity.java create mode 100644 common_base/src/main/java/com/wss/common/view/browser/BrowserActivity.java create mode 100644 common_base/src/main/java/com/wss/common/view/browser/mvp/BrowserPresenter.java create mode 100644 common_base/src/main/java/com/wss/common/view/browser/mvp/contract/BrowserContract.java create mode 100644 common_base/src/main/java/com/wss/common/view/browser/mvp/model/BrowserModel.java create mode 100644 common_base/src/main/java/com/wss/common/view/file/SelectFileActivity.java create mode 100644 common_base/src/main/java/com/wss/common/view/file/adapter/SelectFileAdapter.java create mode 100644 common_base/src/main/java/com/wss/common/view/file/adapter/holder/SelectFileViewHolder.java create mode 100644 common_base/src/main/java/com/wss/common/view/file/bean/FileInfo.java create mode 100644 common_base/src/main/java/com/wss/common/view/file/mvp/SelectFilePresenter.java create mode 100644 common_base/src/main/java/com/wss/common/view/file/mvp/contract/SelectFileContract.java create mode 100644 common_base/src/main/java/com/wss/common/view/file/mvp/model/SelectFileModel.java rename common_base/src/main/java/com/wss/common/{widget/scaleImg => view/gallery}/IOThread.java (92%) rename common_base/src/main/java/com/wss/common/{widget/scaleImg => view/gallery}/ImageDownloader.java (61%) create mode 100644 common_base/src/main/java/com/wss/common/view/gallery/ImageGallery.java create mode 100644 common_base/src/main/java/com/wss/common/view/gallery/ImageGalleryActivity.java rename common_base/src/main/java/com/wss/common/{widget/scaleImg => view/gallery}/ImageViewerAdapter.java (78%) create mode 100644 common_base/src/main/java/com/wss/common/view/scan/ScanActivity.java create mode 100644 common_base/src/main/java/com/wss/common/widget/AutoTextView.java create mode 100644 common_base/src/main/java/com/wss/common/widget/EnhanceEditText.java create mode 100644 common_base/src/main/java/com/wss/common/widget/GradientTextView.java create mode 100644 common_base/src/main/java/com/wss/common/widget/IconFontTextView.java create mode 100644 common_base/src/main/java/com/wss/common/widget/NoScrollGridView.java create mode 100644 common_base/src/main/java/com/wss/common/widget/NoScrollListView.java delete mode 100644 common_base/src/main/java/com/wss/common/widget/ProgressWebView.java create mode 100644 common_base/src/main/java/com/wss/common/widget/StickyNavLayout.java create mode 100644 common_base/src/main/java/com/wss/common/widget/SwipeItemLayout.java create mode 100644 common_base/src/main/java/com/wss/common/widget/ViewPagerForScrollView.java delete mode 100644 common_base/src/main/java/com/wss/common/widget/WebViewProgressBar.java create mode 100644 common_base/src/main/java/com/wss/common/widget/dialog/DateDialog.java create mode 100644 common_base/src/main/java/com/wss/common/widget/dialog/OnButtonClickListener.java create mode 100644 common_base/src/main/java/com/wss/common/widget/dialog/OnItemClickListener.java create mode 100644 common_base/src/main/java/com/wss/common/widget/manager/ScrollSpeedLinearLayoutManger.java delete mode 100644 common_base/src/main/java/com/wss/common/widget/pulltorefresh/IRefreshView.java delete mode 100644 common_base/src/main/java/com/wss/common/widget/pulltorefresh/OnPullRefreshListener.java delete mode 100644 common_base/src/main/java/com/wss/common/widget/pulltorefresh/PullToRefreshLayout.java delete mode 100644 common_base/src/main/java/com/wss/common/widget/pulltorefresh/RefreshView.java delete mode 100644 common_base/src/main/java/com/wss/common/widget/pulltorefresh/State.java delete mode 100644 common_base/src/main/java/com/wss/common/widget/pulltorefresh/ViewStatus.java delete mode 100644 common_base/src/main/java/com/wss/common/widget/scaleImg/ImageViewer.java create mode 100644 common_base/src/main/res/color/selector_text_color.xml create mode 100644 common_base/src/main/res/color/tab_text_color.xml create mode 100644 common_base/src/main/res/drawable-xxhdpi/bg_of_color_f5_4radius.xml create mode 100644 common_base/src/main/res/drawable-xxhdpi/header_load_default.png create mode 100644 common_base/src/main/res/drawable-xxhdpi/icon_back.png create mode 100644 common_base/src/main/res/drawable-xxhdpi/icon_refresh.png create mode 100644 common_base/src/main/res/drawable/browser_progress_bg.xml create mode 100644 common_base/src/main/res/drawable/corners_black_shape.xml create mode 100644 common_base/src/main/res/drawable/corners_theme_shape_45.xml create mode 100644 common_base/src/main/res/drawable/stroke_gray_white_shape.xml create mode 100644 common_base/src/main/res/layout/activity_browser.xml create mode 100644 common_base/src/main/res/layout/activity_image_gallery.xml create mode 100644 common_base/src/main/res/layout/activity_scan.xml rename module_main/src/main/res/layout/main_fragment_center.xml => common_base/src/main/res/layout/activity_select_file.xml (65%) create mode 100644 common_base/src/main/res/layout/activity_springboard.xml delete mode 100644 common_base/src/main/res/layout/activity_webview.xml create mode 100644 common_base/src/main/res/layout/base_tablayout_child.xml create mode 100644 common_base/src/main/res/layout/dailog_date.xml delete mode 100644 common_base/src/main/res/layout/dialog_scale_image.xml delete mode 100644 common_base/src/main/res/layout/empty_layout.xml create mode 100644 common_base/src/main/res/layout/item_of_load_all_data.xml create mode 100644 common_base/src/main/res/layout/item_of_select_file.xml create mode 100644 common_base/src/main/res/layout/item_of_select_image.xml create mode 100644 common_base/src/main/res/layout/item_of_selector_pop.xml rename common_base/src/main/res/layout/{fragment_base.xml => layout_base.xml} (86%) delete mode 100644 common_base/src/main/res/layout/layout_error.xml delete mode 100644 common_base/src/main/res/layout/layout_loading.xml create mode 100644 common_base/src/main/res/layout/layout_nothing.xml delete mode 100644 common_base/src/main/res/layout/layout_refresh_view.xml create mode 100644 common_base/src/main/res/layout/layout_search.xml create mode 100644 common_base/src/main/res/layout/pop_date_range.xml rename module_main/src/main/res/layout/main_activity_scale_image.xml => common_base/src/main/res/layout/pop_selector.xml (56%) delete mode 100644 common_base/src/main/res/layout/toast.xml delete mode 100644 common_base/src/main/res/layout/update_progress_layout.xml delete mode 100644 common_base/src/main/res/layout/view_scale_image.xml create mode 100644 module_main/README.txt delete mode 100644 module_main/doc.txt delete mode 100644 module_main/src/main/java/com/wss/module/main/ui/hortab/OrderListActivity.java delete mode 100644 module_main/src/main/java/com/wss/module/main/ui/hortab/adapter/OrderListAdapter.java delete mode 100644 module_main/src/main/java/com/wss/module/main/ui/hortab/fragment/OrderFragment.java delete mode 100644 module_main/src/main/java/com/wss/module/main/ui/hortab/mvp/OrderPresenter.java delete mode 100644 module_main/src/main/java/com/wss/module/main/ui/hortab/mvp/contract/OrderContract.java delete mode 100644 module_main/src/main/java/com/wss/module/main/ui/im/IMActivity.java delete mode 100644 module_main/src/main/java/com/wss/module/main/ui/im/IMUserInfoActivity.java delete mode 100644 module_main/src/main/java/com/wss/module/main/ui/im/adapter/IMAdapter.java delete mode 100644 module_main/src/main/java/com/wss/module/main/ui/loading/LoadingActivity.java rename module_main/src/main/java/com/wss/module/main/ui/main/adapter/{CenterRcyAdapter.java => CaseAdapter.java} (59%) create mode 100644 module_main/src/main/java/com/wss/module/main/ui/main/fragment/CaseFragment.java delete mode 100644 module_main/src/main/java/com/wss/module/main/ui/main/fragment/CenterFragment.java create mode 100644 module_main/src/main/java/com/wss/module/main/ui/main/mvp/CasePresenter.java delete mode 100644 module_main/src/main/java/com/wss/module/main/ui/main/mvp/MainModel.java delete mode 100644 module_main/src/main/java/com/wss/module/main/ui/main/mvp/MainPresenter.java create mode 100644 module_main/src/main/java/com/wss/module/main/ui/main/mvp/contract/CaseContract.java delete mode 100644 module_main/src/main/java/com/wss/module/main/ui/main/mvp/contract/MainContract.java create mode 100644 module_main/src/main/java/com/wss/module/main/ui/main/mvp/model/CaseModel.java delete mode 100644 module_main/src/main/java/com/wss/module/main/ui/page/QRCodeActivity.java delete mode 100644 module_main/src/main/java/com/wss/module/main/ui/page/ScaleImageActivity.java delete mode 100644 module_main/src/main/java/com/wss/module/main/ui/page/YumanmanActivity.java delete mode 100644 module_main/src/main/java/com/wss/module/main/ui/refresh/RefreshStringActivity.java delete mode 100644 module_main/src/main/java/com/wss/module/main/ui/refresh/adapter/StringAdapter.java delete mode 100644 module_main/src/main/java/com/wss/module/main/ui/refresh/mvp/StringPresenter.java delete mode 100644 module_main/src/main/java/com/wss/module/main/ui/refresh/mvp/contract/RefreshContract.java delete mode 100644 module_main/src/main/java/com/wss/module/main/ui/selector/mvp/SelectorModule.java create mode 100644 module_main/src/main/java/com/wss/module/main/ui/selector/mvp/model/SelectorModule.java delete mode 100644 module_main/src/main/res/layout/item_of_demo_fragment.xml delete mode 100644 module_main/src/main/res/layout/main_activity_corrdinator_layout.xml delete mode 100644 module_main/src/main/res/layout/main_activity_horizontal_tab.xml delete mode 100644 module_main/src/main/res/layout/main_activity_im.xml delete mode 100644 module_main/src/main/res/layout/main_activity_im_user_info.xml delete mode 100644 module_main/src/main/res/layout/main_activity_qr_code.xml delete mode 100644 module_main/src/main/res/layout/main_activity_refresh.xml delete mode 100644 module_main/src/main/res/layout/main_activity_yumanman.xml delete mode 100644 module_main/src/main/res/layout/main_demo_activity.xml delete mode 100644 module_main/src/main/res/layout/main_demo_fragment.xml create mode 100644 module_main/src/main/res/layout/main_fragment_case.xml delete mode 100644 module_main/src/main/res/layout/main_fragment_news.xml delete mode 100644 module_main/src/main/res/layout/main_include_open.xml delete mode 100644 module_main/src/main/res/layout/main_include_toolbar_close.xml delete mode 100644 module_main/src/main/res/layout/main_include_toolbar_open.xml rename module_main/src/main/res/layout/{main_item_of_center_list.xml => main_item_of_case_list.xml} (68%) delete mode 100644 module_main/src/main/res/layout/main_item_of_im_left.xml delete mode 100644 module_main/src/main/res/layout/main_item_of_im_right.xml delete mode 100644 module_main/src/main/res/layout/main_item_of_order_goods_list.xml delete mode 100644 module_main/src/main/res/layout/main_item_of_order_list.xml delete mode 100644 module_main/src/main/res/layout/main_item_of_string_list.xml create mode 100644 module_market/README.txt delete mode 100644 module_market/doc.txt create mode 100644 module_market/src/main/java/com/wss/module/market/ui/goods/cart/mvp/model/ShoppingCartModel.java create mode 100644 module_market/src/main/java/com/wss/module/market/ui/goods/detail/mvp/model/GoodsCommentModel.java create mode 100644 module_market/src/main/java/com/wss/module/market/ui/goods/detail/mvp/model/GoodsDetailModel.java create mode 100644 module_market/src/main/java/com/wss/module/market/ui/main/mvp/model/MarketMainModel.java create mode 100644 module_user/README.txt delete mode 100644 module_user/src/main/java/com/wss/module/user/ui/account/mvp/LoginModel.java delete mode 100644 module_user/src/main/java/com/wss/module/user/ui/account/mvp/RegisterModel.java create mode 100644 module_user/src/main/java/com/wss/module/user/ui/account/mvp/model/LoginModel.java create mode 100644 module_user/src/main/java/com/wss/module/user/ui/account/mvp/model/RegisterModel.java delete mode 100644 module_user/src/main/java/com/wss/module/user/ui/main/mvp/UserModel.java create mode 100644 module_user/src/main/java/com/wss/module/user/ui/main/mvp/model/UserModel.java create mode 100644 module_wan_android/README.txt delete mode 100644 module_wan_android/src/main/java/com/wss/module/wan/ui/collection/mvp/CollectionModel.java create mode 100644 module_wan_android/src/main/java/com/wss/module/wan/ui/collection/mvp/model/CollectionModel.java rename module_wan_android/src/main/java/com/wss/module/wan/ui/main/adapter/{HomeRcyAdapter.java => HomeMenuAdapter.java} (61%) delete mode 100644 module_wan_android/src/main/java/com/wss/module/wan/ui/main/mvp/HomeModel.java create mode 100644 module_wan_android/src/main/java/com/wss/module/wan/ui/main/mvp/model/HomeModel.java delete mode 100644 module_wan_android/src/main/java/com/wss/module/wan/ui/project/mvp/ProjectModel.java create mode 100644 module_wan_android/src/main/java/com/wss/module/wan/ui/project/mvp/model/ProjectModel.java delete mode 100644 module_wan_android/src/main/java/com/wss/module/wan/ui/search/mvp/SearchModule.java create mode 100644 module_wan_android/src/main/java/com/wss/module/wan/ui/search/mvp/model/SearchModule.java create mode 100644 module_wan_android/src/main/java/com/wss/module/wan/ui/series/SeriesActivity.java create mode 100644 module_wan_android/src/main/java/com/wss/module/wan/ui/series/SeriesArticleActivity.java rename module_wan_android/src/main/java/com/wss/module/wan/ui/{setup/adapter/SetupLeftAdapter.java => series/adapter/SeriesAdapter.java} (73%) rename module_wan_android/src/main/java/com/wss/module/wan/ui/{setup => series}/adapter/SetupRightAdapter.java (81%) create mode 100644 module_wan_android/src/main/java/com/wss/module/wan/ui/series/mvp/SeriesArticlePresenter.java create mode 100644 module_wan_android/src/main/java/com/wss/module/wan/ui/series/mvp/SeriesPresenter.java create mode 100644 module_wan_android/src/main/java/com/wss/module/wan/ui/series/mvp/contract/SeriesArticleContract.java create mode 100644 module_wan_android/src/main/java/com/wss/module/wan/ui/series/mvp/contract/SeriesContract.java create mode 100644 module_wan_android/src/main/java/com/wss/module/wan/ui/series/mvp/model/SeriesArticleModel.java create mode 100644 module_wan_android/src/main/java/com/wss/module/wan/ui/series/mvp/model/SeriesModel.java delete mode 100644 module_wan_android/src/main/java/com/wss/module/wan/ui/setup/SystemActivity.java delete mode 100644 module_wan_android/src/main/java/com/wss/module/wan/ui/setup/SystemArticleActivity.java delete mode 100644 module_wan_android/src/main/java/com/wss/module/wan/ui/setup/mvp/SystemArticleModel.java delete mode 100644 module_wan_android/src/main/java/com/wss/module/wan/ui/setup/mvp/SystemArticlePresenter.java delete mode 100644 module_wan_android/src/main/java/com/wss/module/wan/ui/setup/mvp/SystemModel.java delete mode 100644 module_wan_android/src/main/java/com/wss/module/wan/ui/setup/mvp/SystemPresenter.java delete mode 100644 module_wan_android/src/main/java/com/wss/module/wan/ui/setup/mvp/contract/SystemArticleContract.java delete mode 100644 module_wan_android/src/main/java/com/wss/module/wan/ui/setup/mvp/contract/SystemContract.java delete mode 100644 module_wan_android/src/main/java/com/wss/module/wan/ui/wxnumber/mvp/WXArticleModel.java create mode 100644 module_wan_android/src/main/java/com/wss/module/wan/ui/wxnumber/mvp/WXNumberPresenter.java create mode 100644 module_wan_android/src/main/java/com/wss/module/wan/ui/wxnumber/mvp/contract/WXArticleContract.java create mode 100644 module_wan_android/src/main/java/com/wss/module/wan/ui/wxnumber/mvp/model/WXArticleModel.java create mode 100644 module_wan_android/src/main/java/com/wss/module/wan/ui/wxnumber/mvp/model/WXNumberModel.java rename module_wan_android/src/main/res/layout/{wan_activity_setup.xml => wan_activity_series.xml} (87%) diff --git a/.gitignore b/.gitignore index 39fb081..2a42e3e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,20 @@ *.iml .gradle /local.properties -/.idea/workspace.xml +/.idea/caches /.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +/.idea/ +/.idea/misc.xml .DS_Store /build /captures .externalNativeBuild +.cxx +*.apk +*.ap_ +*.dex +*.class diff --git a/app/build.gradle b/app/build.gradle index ecc418b..5a6cb23 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -47,22 +47,18 @@ android { } } -configurations.all { - resolutionStrategy.force 'com.android.support:support-annotations:27.1.1' -} - dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) - annotationProcessor rootProject.ext.dependencies["butterknife_compiler"] + annotationProcessor rootProject.ext.dependencies["butterknifeCompiler"] //公用依赖包 implementation project(':common_base') - if (!Boolean.valueOf(rootProject.ext.isModule)) { - //main模块 - implementation project(':module_main') - implementation project(':module_market') - implementation project(':module_wan_android') - implementation project(':module_user') - - } + //main模块 + implementation project(':module_main') + //商城模块 + implementation project(':module_market') + //用户模块 + implementation project(':module_user') + //玩Android模块 + implementation project(':module_wan_android') } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index d468f7e..55ada32 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -10,6 +10,16 @@ android:supportsRtl="true" android:theme="@style/AdmTheme"> + + + + + + + + { + ActivityToActivity.toActivity(this, MainActivity.class); + }, 2200); + + + } + + @Override + protected BasePresenter createPresenter() { + return null; + } +} diff --git a/app/src/main/java/com/wss/amd/profile/DevProfile.java b/app/src/main/java/com/wss/amd/profile/DevProfile.java new file mode 100644 index 0000000..11be77c --- /dev/null +++ b/app/src/main/java/com/wss/amd/profile/DevProfile.java @@ -0,0 +1,21 @@ +package com.wss.amd.profile; + + +import com.wss.common.profile.IProfile; + +/** + * Describe:开发环境配置 + * Created by 吴天强 on 2020/4/13. + */ +public class DevProfile implements IProfile { + + /** + * Api服务器地址 + */ + private static final String SERVICE_BAR_URL = "https://www.wanandroid.com"; + + @Override + public String getServiceBase() { + return SERVICE_BAR_URL; + } +} diff --git a/app/src/main/java/com/wss/amd/profile/ProfileFactory.java b/app/src/main/java/com/wss/amd/profile/ProfileFactory.java new file mode 100644 index 0000000..a49e786 --- /dev/null +++ b/app/src/main/java/com/wss/amd/profile/ProfileFactory.java @@ -0,0 +1,18 @@ +package com.wss.amd.profile; + + +import com.wss.common.profile.IProfile; +import com.wss.common.profile.IProfileFactory; + +/** + * Describe:创建环境工厂 + * Created by 吴天强 on 2020/4/13. + */ +public class ProfileFactory implements IProfileFactory { + + @Override + public IProfile createProfile() { + //根据不同的环境生成不同的配置文件,这里仅生成DEV配置文件 + return new DevProfile(); + } +} diff --git a/module_main/src/main/res/layout/main_activity_loading.xml b/app/src/main/res/layout/activity_loading.xml similarity index 54% rename from module_main/src/main/res/layout/main_activity_loading.xml rename to app/src/main/res/layout/activity_loading.xml index 627936c..1dbabdb 100644 --- a/module_main/src/main/res/layout/main_activity_loading.xml +++ b/app/src/main/res/layout/activity_loading.xml @@ -1,8 +1,7 @@ - - - + android:background="@drawable/bg_of_orange_gradient_radius" + tools:ignore="MissingDefaultResource" /> diff --git a/build.gradle b/build.gradle index 87207ac..4800373 100644 --- a/build.gradle +++ b/build.gradle @@ -3,27 +3,38 @@ apply from: "config.gradle" buildscript { repositories { - google() - jcenter() - mavenCentral() + maven { url 'https://maven.aliyun.com/repository/google' } + maven { url 'http://maven.aliyun.com/nexus/content/repositories/jcenter' } + maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } +// google() +// jcenter( } dependencies { - classpath "com.android.tools.build:gradle:3.0.1" - //黄油刀 - classpath "com.jakewharton:butterknife-gradle-plugin:8.4.0" + classpath 'com.android.tools.build:gradle:3.6.2' + classpath 'com.jakewharton:butterknife-gradle-plugin:10.2.1' //数据库GreenDAO classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2' + //听云 + classpath 'com.networkbench.newlens.agent.android:agent-gradle-plugin:2.7.1' } +} - allprojects { - repositories { - google() - jcenter() - maven { url 'https://jitpack.io' } - } +allprojects { + repositories { + maven { url "https://dl.bintray.com/tencentqcloudterminal/maven" } + maven { url 'https://maven.aliyun.com/repository/google' } + maven { url 'http://maven.aliyun.com/nexus/content/repositories/jcenter' } + maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } + maven { url 'https://jitpack.io' } + maven { url "http://mvn.gt.igexin.com/nexus/content/repositories/releases/" } +// google() +// jcenter() } } + task clean(type: Delete) { delete rootProject.buildDir } + + diff --git a/common_base/build.gradle b/common_base/build.gradle index e03c6fa..a364a2f 100644 --- a/common_base/build.gradle +++ b/common_base/build.gradle @@ -43,57 +43,53 @@ android { dependencies { // 在项目中的libs中的所有的.jar结尾的文件,都是依赖 - compile fileTree(include: ['*.jar'], dir: 'libs') - //把implementation 用api代替,它是对外部公开的, 所有其他的module就不需要添加该依赖 - api rootProject.ext.dependencies["appcompat_v7"] - api rootProject.ext.dependencies["constraint_layout"] - api rootProject.ext.dependencies["cardview-v7"] - api rootProject.ext.dependencies["recyclerview-v7"] - api rootProject.ext.dependencies["support-v4"] - api rootProject.ext.dependencies["design"] - api rootProject.ext.dependencies["support_annotations"] - api rootProject.ext.dependencies["junit"] - //MultiDex分包方法 + api fileTree(include: ['*.jar'], dir: 'libs') + //android基础库 + api rootProject.ext.dependencies["appcompat"] + api rootProject.ext.dependencies["recyclerview"] + api rootProject.ext.dependencies["cardview"] + api rootProject.ext.dependencies["annotation"] + api rootProject.ext.dependencies["material"] api rootProject.ext.dependencies["multidex"] - //黄油刀 - annotationProcessor rootProject.ext.dependencies["butterknife_compiler"] + api rootProject.ext.dependencies["junit"] + api rootProject.ext.dependencies["swiperefreshlayout"] + api rootProject.ext.dependencies["localbroadcastmanager"] + //Lombok + api rootProject.ext.dependencies["lombok"] + api rootProject.ext.dependencies["javaxAnnotation"] + //阿里ARouter + api rootProject.ext.dependencies["arouter"] + annotationProcessor rootProject.ext.dependencies["arouterCompiler"] + //Butterknife api rootProject.ext.dependencies["butterknife"] - //Arouter路由 - annotationProcessor rootProject.ext.dependencies["arouter_compiler"] - api rootProject.ext.dependencies["arouter_api"] - api rootProject.ext.dependencies["arouter_annotation"] - //eventbus 发布/订阅事件总线 - api rootProject.ext.dependencies["eventbus"] - //网络 - api rootProject.ext.dependencies["novate"] - //日志 + annotationProcessor rootProject.ext.dependencies["butterknifeCompiler"] + //EventBus + api rootProject.ext.dependencies["eventBus"] + //Logger api rootProject.ext.dependencies["logger"] - //fastJson - api rootProject.ext.dependencies["fastjson"] //沉浸栏 api rootProject.ext.dependencies["immersionbar"] - //banner + //Bnnaer api rootProject.ext.dependencies["banner"] -// //图片加载 -// api rootProject.ext.dependencies["picasso"] - //图片加载 + //Glude api rootProject.ext.dependencies["glide"] - //lombok - api rootProject.ext.dependencies["lombok"] - api rootProject.ext.dependencies["lombokJavax"] - //时间 日期 地址 条件选中器 + //弹窗选择器 api rootProject.ext.dependencies["pickerView"] - //万能Adapter + //危险权限申请 + api rootProject.ext.dependencies["xxpermissions"] + //网络 + api rootProject.ext.dependencies["rxHttp"] + api rootProject.ext.dependencies["rxLife"] + api rootProject.ext.dependencies["rxAndroid"] + annotationProcessor rootProject.ext.dependencies["rxCompiler"] + //万能适配器 api rootProject.ext.dependencies["superAdapter"] - //GreenDao - api rootProject.ext.dependencies["greenDao"] - //scaleImageView + //图片预览 api rootProject.ext.dependencies["scaleImageView"] //二维码扫描 api rootProject.ext.dependencies["zxing"] - //危险权限 - api rootProject.ext.dependencies["xxpermissions"] - //RX - api rootProject.ext.dependencies["rx2_java"] - api rootProject.ext.dependencies["rx2_android"] + //刷新库 + api rootProject.ext.dependencies["refreshLayout"] + //GreenDao + api rootProject.ext.dependencies["greenDao"] } diff --git a/common_base/src/main/AndroidManifest.xml b/common_base/src/main/AndroidManifest.xml index fa7d643..146ce8a 100644 --- a/common_base/src/main/AndroidManifest.xml +++ b/common_base/src/main/AndroidManifest.xml @@ -13,12 +13,13 @@ - + + diff --git a/common_base/src/main/assets/iconfont/iconfont.ttf b/common_base/src/main/assets/iconfont/iconfont.ttf new file mode 100644 index 0000000000000000000000000000000000000000..e24ea224a3f53755ede16c4d29dbd751f5b6e015 GIT binary patch literal 16232 zcmd^md3@Yuo&WRso^#*xoy<&Tl9^;?a^IQhktU%HZBt5{(v!2Dw7H-;+N9W)Rs$li zyR0IJatX8`g35vd3f0BRPpHcwg32OZxbBWF>Utoo3(YtCe!kyH8d{Xs>-YNo_e=6z zpXc~K$LD^YFk+0^*)$Vb)2fY|mp`mO@;k<85unT0Z)|Moc(>Pr@*$MB>>SNc{IJsX zdB%k28IxT@yAKS0cGs)*j9D&XtZ8a^Aipc}8+kX{zK)O`2EeLHuOR;ogv#O3sr~=c zHTyG+_XCvwvU_}I{;D_k9c4`Y3CbTH&F`O}&Fs6VFG0C{EI&HXxk*3F*rM;@o1+us zlT&Ap97p}qZpNe(!`#K`*=cr>yma=rvp#ioO@h9pVirT9{x|V+u$+*;CAElsVLfU&dyQvRQ9qaaPBuXXV;W=xGjY*3j;e zp*ǒ$y@0YXeELQ$4vx`D~eBK#fSQT7QlrQfg?LSKQ&BB1Z{(>HkbF4kSx@hdXd zkGX#i&5En%pIR8?rSB~-tTXeozdaMi`^?U~Km2cvH#>V~pV@bd-zlbltN;If9hNO4 z@I9+Dw?NR$Js}UEe0S=Q;uHaw*uSH!F)U9xZeyobyj%53^;#Q z_<|XL39Rr%GXN)8;Y(%!cCf;OW&obB!atb-7{dw=n*q4P3STw@u!t4DVg}$7D?DNb zU=}MpY6jpKD?DZfU>hrZ)eOKpR(RYDz(7`b!VJJgRybw`U?nSj-3-7_Rscum0hr1P z|7-@%*$PjZ0ocn5-!ud8m=%tj0T|5+-!cPmn-!ii1F)PGzHJ8JJ1abG24FrbJYxn< z)rAvg05!0}cgz5~V1<7%11N+Qo;3q#g%zGN1E_`-o;L&NhZSBh11O0VAW?V#O|im@ zW&m}u0;CQPpfgr@$qb-4R(RPApgmUjz8OG;tN^LT1L%7Fro61W)FtY7EFMdTWv}H)%RAOh*88l_+Tylt zwvXHHusiHuatMxL$7|00&VP4JyKU~(?){!=?>g^yebc^I{d@h>f$6}@!9Z|%@XlaC zJEYyFy&7r?tqpy<1bEHoKl=mmVKIl*27rn6ppNAriv~(60j(vQOSEVKr6Q3`w`Iiz zz&Hh51aJejb<%bW`(G9Nts&tLGk}n%Pf(oO}@< z@o1p<&4qpSx8DaCf1hzU4bDzOBb(0d$Yyiut=9#9J+XCwMyH2d$$Xgn$Ovt zB|gFJDNxuB4^!dM%*=pXm=A-FZfTh=K_X*&vs*v)74#5%)vNh9GSkSvT9j z@@x;gl6{gLVP9sD8ZvYus8AXUDMkiGg{dh16}Z2(la>LaGZjgNA4F^DbU+Hb&s$*s zjTVX1$`z-TQ^k>%lG#sgKQ%gsonEgdieJW&^6v=j75$g8OtDv9p_nY|zkKB>BBZlV zJ*CeAPEUP6{W7FD@pE^CqX?*L+vIeO}mewa@!pVxwUwtql9eS-KDRWiOr3k!D`b3ZkM({jV7%Ktq-fSR9&s^3$U z2w!PL0g-Y#HF1VPhT0&T%b+iGfle#pIE%J)QjzC#;$OiL5yGb>6bHY~Wg(7Kmyo8u zCW=-?@kgJS%U$^a=i*jfeoMvq{pTlDzgw*y*>@TJA;5=-2FzsU>JQpAFM2A;N+Dfg z!B{m70`wp*(`Tn8242MJf@|~~-$4XvW=b9ve5I2F_L}~4;7{VU*C+ve`uS@geNYr1 z{HPI&(;Tp%!FT3rP+yc2bKi)8@|Lqr_>w_osj#D$hlfg^FwBm$${)*z(J z$|6ZL2(2g^Y!AeiLp|nJoKtZMk8IGY$~~U)s=DejulL3cPOrDDy3PdY?-c7a6a1RS z+c-Bgb`m+9ztfeXhCnlB~*yenG8OPjSdnk#+6AEW+0Uy>;4>*H4&(pNzh4;n_?KsWt6&ci=_T{pbSb9hk zpg@S&6y$ME4WzbU!;)A(Hqqp7H2c|^&ZQk=J4w3snkQ2gEAzd_1|R>kEdTlO$KR5q zw;r!ruO&77O$+zmcq7&9$*-(Pee+}2>L+*ho-2NNzS-k%-P)qR*3v@h7M*!DEfE5< z;rin<;^&38ik!8Lod<)jsX5umbsWqH^WyZOESw`SWWEZjVIWRm#FXH;X3$hXsU*Dc|>bN$vK#XDdtU;D(x7z-nA|N6R!P1q#t**x_5+>(2T zHt*42ogb~K`#vFF7pHhbeCCrBb^n)#$P@8?AzkagC!~ zb=+#zEY#>w%g^|r{x$s%SKBS+_Rm->RAEmT{?6Is;r-sywBEhJE zzFM?nI5&q9OD}uw`;kOKbM3LFV$vx+%s=s&L^-oCB6W4pLeMq!EA$Hq;ai6E> zP#aoo@${~J>!VlRu?n@V84Ud#QCzQ}gP!4OAyK1_fd9$Te#|`;sICs>0&Yg9na^fxO9-P@_;LrYE^I3kKi4#*=7zk923hyH@JPIjj~&P>1)B{0@% zzdP+#&XrT^%K8Tf`!B?vb6Gbh=R@#El4dPo21{&bHZ<}N>oxWB$0;>XkpW?_sEuFV2cVQKd!{VRHbA{~zk`I)0|3c^=0`=&T#=#3_2V_KMp zfyb2Kx*Pdh;sk6@Gzj3#0=wloQGD(eBc>Mpd8+E|>#b^YYl7b`>w{)0PD{_;a_h5_ z^z5y-JgeVXv$CdUrQR1P3kd{P9}96+HC6^{>bM^-VpI@}BX@%^4xM6GV3|5y$;}Z)y>z@vzZB<$F z_~dv`d8DVQ-XHhmwr&8bnE0{&JF)eV&Rd( zth-Ua%N6juDev<8|Iy*5>T2DE;E-D0A)41KGkkHVwmkNJs5!j$ND z&b(A!>$2~#yM%R1DQlYfGtX4Dldxf#(B$E+oVhs)ufU@Szax4144_qUO$jHPpx@A? z((||VUOkkPp8xR`_lo+@gdggkzWsSAH*|IHZO=>MJ%{)>SR|rpjAI9FV6}#B)e27> zR_Q+tb>+0l47m!-*)om_QanvlR;SZSE38g(SjRH0M6H>b*V8;r(~QNZe6HUbwq2`0 z^-&M^+rqXlE9CMyoqnhALu$$BJ2EYVl9xY-p<;-wb=*}^cWkq}+OzqXS)d>3k8)QTtwn5jG<4o< zv)jEHP3Z-AH}n^{4+0*ExxL{u!@xPpIW-$}0?i9t5Y!?B6VOw+MW1NvgkAFjWq0h} zktJbj>(;5~R$n!k)sMrkp&!ogXXZSaF|tajK*$bMSMLtbo{kK=EkYD1*q4SNr6we zh`Vb7Fvs9Sh66HXAOO|{SW0Vcfh1qbeQ$G}xVq{RplX6-6iuA;RF}Ck>D! zdB?2{A9%f&_cHwI z*FC1c0gk_6R1iitaB^+x7HL_d#iJGX{YLR;VgxH`!j5;s*R&R-oN$RTfg@@N&RoMq z(jdqQunYLbMOZr-&ac3z{S~l=Aa~nv*Wn_#rnnF`3&I!mFD#qb+GzdKha;c-WQ1oM zw@&Dzw54h53a%rp*xIycaw<1)ttehQ(BmtwEcY1^-F7yeDv1$l*gDa9o%`^;;w`rr z+0Kcr4Ly}TTbr(H+S*fj;DC6|;B|x7>M#2E0I4#cugrfci}RX&clJW55n)4IxRO9kyuFQ>4lwt940f94uZBm)b`Wh*nbPL?MjZT>?(m3w~QstD`MeU&4 z7PJ*qMM7I(0sSAZ-|xNfph*6NA5xE(Zh2k`B>dt%QrY_C^%b_LAPV`lboQ|)?(WVf zx0I<9Q7OJ`$!GFM?NRGS=zW*}bGIy6HrmNDMS?wM&nIrb>mL1$ngNU8x?Z@*82R8u z9>3qS?7UC%lJwlIymas$JrW`)&b*1JC zT1!&cU$NYK!n*E+V6~B)3hNJY*FJ63k`_U-%i;-P=KKOj{{n8D=5gZ6B2M%#z=S&l)$*^b zs;n9s+l4(b^`4i+kMWlS+!#|$65uy!bGlW7p~i4tVNin*q&s{rtG&eTDh=w-aRuwS zV5!|I2Q*RE=#HRx#R*#~pvj`gu0IH;->*EH=J^$s25F+eUk|LY;UYRh9=8U)m82)}`GgcBj>UR1kQwyr*{ zN?)_$d_g#Wg&Eg(2tr4_5z}kq6^PIA|W&ks3q@WL=3LF>3w+2dufj|aIfnLmmjEgCbEQSjm9NEmZ zhvsqsakf#BL@&BpqNc6Gi`}_Y!%+6>ha|efqKNja&E{`xq(WOx{M6{!O`>?ySW~0j z9+L&-p`|&$rh4PZaiTLo7N4+3mJ^9%vh=>$2n0yw)j%O9D$%0y%^>i$nHW&uyAoe&vIr@OPIf zHD_P+Q#jzOaqlJ+Q+}ykiF<8dh{Ba2N#?4Y;itF?Z(^>7AFPXQ15Y;S6I;}pHEu&f z&^k5Fn^IhPYXkMQ!{&oG$9Txm8W&?+UOnT?)}i%&FY7}9;MXfa0&wK4#DYgmnvTOF!ZD3I&rDs-4_p(0j9eklHgW~NjQm=whOKMlx}c10L4V*FG+ypa z1*!stVZCV?j^~QX@sHm;(L3I_m1?ZMm`{IYMbILJe8CcrI}_Yi>P@HPw(dZn;_4@@ zG2f=9ZC1Ba6GY3F4!cDXk68Uy)nw5)%j;U>1u+}5#Pkk>E% z!WyM?MWpu&C<*IlE)fQ!sZ{j2?UG&G{v5JbW@v3Dqd%H~muG#4Ub}b=oug<{cn$R} zr58HZpOcE}t;bC$|JwpE){xqni`*L0q z@414P@*mX?l}OqJB|R}gTGw_ZRl`@lE*e$#M9wN{Ue^(83oGy*b*qxxddtN&zq;J- z+e7dmTl&g>cJ=hZXrC=)p^x*S*5m~bZgiG6@xsA-L=?oUq;OYsPpL%{1zOjkzpKAG z-MX%{C#+l$6ib>Lmc@FirmaDBx$3uGa!ZRWsw=$iiv){i?TZ}x@JD~1>{A3&r{I1Z z`V;r#_^mWXH{$nCu-tCqklCM#&xy6LqVUF3F5Y=Hh`@j20Tu{|i}jWq=ihBbg$E7| zzTZ5?wLA6^?7x!?b_B{&ad(TD+ZDhh{P8zg_|rlGyxxE+fZZ-`I5)fa%PdZEXbAZa zH3#--yYT@&g=`l*zs7GGFPFG0g;$C9?zFkxwhP5zRlSyIvy&{!4(zmK5lK=+L6AgI zQ6$xBgL!L{lw{Bu@_9wk?o>nWvSxp6)M*#-Kt&cstIZ)otk@(qrG?wHMY6-LQ?4&k zYV#^q5ypooTa}R8maXV0i4+?gC3ALFaazDJWtT;;sK|*9M>y+l zFLPrb!s)W0#SsfGQ|+SacZM-1K@dG|P`_fA!quf2x6>uclGQ<~!)fzi9^~^lQre<) zz!S%0{ZYHq5wzM|N{!8@*dpGRwLZID?5!wEO`c;bar+|{j2UTlt<<8zlNQ)fo${RPBKhw@b16lb*08rIn^SwK~}kAFUx{j)VTYLH|kqG8H`UeSF@W zq2e@fL~$d7A`T934{iy2(wW7<$f65(e6}=_sBdfxcvq~h-}mHjg9q*Na<&HT(~F_T%1XJ!p{2DD`sZqTR%BdKi3+44E6*Z{hIh6;%dyXjK9uJ zaZPpEyo)t~sqov3lzHDA&>-Wu3pAk7+b<}ZYa1SBP-mm?Vk4~hu0~x+H#eWt+)S%d zMtalBR=?{Qb=1@A^&Ny%FGo7tvZiJJ58GnU$$jE>wwBkTA0ggbaeTl zvh?O{n>w1>^q)NZh2f^maPP`kLwGY?ykb+NK7MxZa8=Xb{SQ+`Thp?Q+cu}muPC0u z;U)0htx2c&Ybce$xl<5BwYzXTAQX<$Kl(U2)A&cNS;;0JiFGj)+o}s!} z=z$}aU_^g5T;)7sFNsixR{bYAVD)%EZL{5B30niw9ipH@aKM+a;I0m~(tEsnK#@6& zfry6hpc6uv+Yh*^JMA6NvA@XjUyd0uZTe3izd-W+r^n};UierDoqFb4p)F0_U<(B4 zl3>7ggDsIxU>~`@V7}{c!;U?NZ3R!myLf`rmHVE#>cf4{U|HOnsWtpO;9PLga)Skl z#;qB}AE>1us*{=aiX?O;=u^BB?P7i1MV9*3NwRX5EY{YE(pjo3t?QFyQQAgQr$pPN`3&7F{Y5(MPn<6Co*MS# zH>5?2B(lr>JHSQS+a-s*qhGeuuVp@rJU`sb8?wAimRB1wX)>=NL*xUW4ZT0YUo~2x zPQkWq5O8VVBBbbfcU(I;4Cjs;**ejx+r0G&qVh%$y^R-1TxLv*Uo&)u3?vFza;~{k ziHzt}a)Ua-!vj?t1vH!)H-EKA``GNdF<#$J(nkt-5`wnUK@z zT(^1KU5A%1KYZ7=B@->*`0~?lo~q`pfMV~#Iqp|(It}lPcW36C%lCSfp}Rn0883X! zM8T)=!co@WefnwrU0mhKo^qNlFW0BbN$^Gad)??6$XJJFPcP_3Zoq{HuoSM>qt^fMmMTjXs~s~L+Mgq+`7f>_q(@P zoZKOh-@xC0EtCUE7CGi9!J;L?`w3tunZ?)ZGAKA&sB)&6L*t0@v`>gq8Qip^Y^ z?IjWuuY7X!hF8jM*{n-Hyyt|Q~*_hYT+xkQ=}uDsM6l}Yp2My5eM_)mSj-Es%wxs8 z2zX^NFCmZr=QDcBz^S%kUIDzTn784T;HqNYj@!At;M62>ZNG+nte7X}VGkAa*dO-I zVqOINg<@Vp{-?#f4B7j;VqRe$;6U@LlOy9}<;@LEbD&iNV*`8V#+kf)sAXzuuzYau_-Oe` z3^=fR_jvil-tkKZc1|@6PfblMX>8;l;_!x@#&oU})ws!s+c#FKq&R<_rfglikRdvk9Z_QjD_`tsC%fGrZRX{ynP^zjG^^ zYu{k3bd)0s$2k52Q{a7n@VAILeM0_ zgm;2e3daJ!P60hrk}9Z@Qk13)Rlx?T!R==q)q~YFQWG^(3$^0mP&;KQM~i4NEy3ky z2cEsd^T@pX$hYqq85rJ|9~&GP+cRRI%l69vXm%Qvllk!jBZ%BaY1hc;$k@=tNPf&= zlrKeYB0pwU4(4|bY~Q(iWanjO*8>=I4}xoAWasvw@v)(U`^Km8BWC3kFAtA2o8t`c z8{Y+hS(qHokL?`ZXHI2mWO8`KTKxFbKD&|Ik5LZ}xK8DV(b=q;9N#y&Z`|xKI=*+n z9A(!CzGZ%R7pBbnho(>4{YBxFqq%Bdur$S!~yp_dJ}- z8s9ar-IxOZtO=XKsMw6%`4K+8xv%~C@&17kKFaRmzGAB`8!$I(a(LgR`>^HvM}p=u zM)KqPM@}D>AH*q`$DFS5B{UuzDgx$*YAzncz}UpV2=8k#dgOQQGB$%%pdWg(+>uI;J0n%jmg8P1Ov zPiA-khhXMEG%$ksn^W19AL-AJO>w}GIq-e}ikZRks^+oU!NOi oYzQkd3q?#YKfPyUB0q(itemView) { + return new Holder(itemView) { LinearLayout layout; ImageView imageView; @Override protected void initView(View itemView) { layout = itemView.findViewById(R.id.ll_img_parent); - if (getImageView() != null) { + imageView = getImageView(); + if (imageView != null) { layout.removeAllViews(); - imageView = getImageView(); layout.addView(imageView); } else { imageView = itemView.findViewById(R.id.image); @@ -35,8 +46,12 @@ protected void initView(View itemView) { } @Override - public void updateUI(String data) { - ImageUtils.loadImage(imageView, data); + public void updateUI(Banner data) { + if (circle) { + ImageUtils.loadImageCircleBead(imageView, data.getImageUrl(), 4); + } else { + ImageUtils.loadImage(imageView, data.getImageUrl()); + } } }; } @@ -48,6 +63,8 @@ public int getLayoutId() { /** * 可以传入自定义的ImageView + * + * @return ImageView */ public ImageView getImageView() { return null; diff --git a/common_base/src/main/java/com/wss/common/adapter/FragmentPagerAdapter.java b/common_base/src/main/java/com/wss/common/adapter/FragmentPagerAdapter.java index 8c9f0d4..3c5af2d 100644 --- a/common_base/src/main/java/com/wss/common/adapter/FragmentPagerAdapter.java +++ b/common_base/src/main/java/com/wss/common/adapter/FragmentPagerAdapter.java @@ -1,16 +1,20 @@ package com.wss.common.adapter; -import android.support.annotation.NonNull; -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentManager; -import android.support.v4.app.FragmentStatePagerAdapter; -import android.view.ViewGroup; +import android.util.Log; import com.wss.common.base.BaseFragment; import com.wss.common.bean.HorizontalTabTitle; +import org.jetbrains.annotations.NotNull; + import java.util.List; +import androidx.annotation.NonNull; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentStatePagerAdapter; + + /** * Describe:滑动Fragment适配器 * 如果滑动Fragment是同一个 使用双参构造方法 覆写 getTabFragment 返回Fragment @@ -18,18 +22,25 @@ *

* Created by 吴天强 on 2018/10/22. */ - public class FragmentPagerAdapter extends FragmentStatePagerAdapter { private List titles; private List fragments; /** * 使用该构造方法 必须重写 getTabFragment 返回对应的Fragment + * + * @param fm FragmentManager + * @param titles Tab */ public FragmentPagerAdapter(FragmentManager fm, List titles) { this(fm, titles, null); } + /** + * @param fm FragmentManager + * @param titles Tab + * @param fragments 滑动的Fragment集合 + */ public FragmentPagerAdapter(FragmentManager fm, List titles, List fragments) { super(fm); this.titles = titles; @@ -43,18 +54,20 @@ public int getCount() { } + @NotNull @Override public Fragment getItem(int position) { - BaseFragment fragment; + Log.e("调用了Fragment", "postion:" + position); + BaseFragment fragment = null; if (fragments == null || fragments.isEmpty()) { fragment = getTabFragment(); } else { fragment = fragments.get(position); } if (fragment == null) { - throw new NullPointerException("Fragment is null,please give me a fragment!"); + throw new NullPointerException("Switch Fragment can not be empty!"); } - fragment.setFragmentData(titles.get(position)); + fragment.setTabTitle(titles.get(position)); return fragment; } @@ -63,10 +76,6 @@ public int getItemPosition(@NonNull Object object) { return POSITION_NONE; } - @Override - public void startUpdate(ViewGroup container) { - super.startUpdate(container); - } @Override public CharSequence getPageTitle(int position) { @@ -75,8 +84,11 @@ public CharSequence getPageTitle(int position) { /** * 使用两参构造方法 必须重写 该方法 返回对应的Fragment + * + * @return BaseFragment */ public BaseFragment getTabFragment() { return null; } + } diff --git a/common_base/src/main/java/com/wss/common/base/ActionBarActivity.java b/common_base/src/main/java/com/wss/common/base/ActionBarActivity.java deleted file mode 100644 index 1c291db..0000000 --- a/common_base/src/main/java/com/wss/common/base/ActionBarActivity.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.wss.common.base; - -import android.os.Bundle; -import android.support.annotation.Nullable; - -import com.wss.common.base.mvp.BasePresenter; -import com.wss.common.widget.ActionBar; - -/** - * Describe:所有带actionBar的Activity基类 - * Created by 吴天强 on 2018/10/18. - */ - -public abstract class ActionBarActivity

extends BaseMvpActivity

{ - - // @BindView(R2.id.actionbar) - protected ActionBar actionBar; - - - @Override - protected void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - actionBar = findViewById(R.id.actionbar); - } - - protected void setTitleText(String title) { - if (actionBar != null) { - actionBar.setCenterText(title); - } - } - - protected void setTitleText(int title) { - if (actionBar != null) { - actionBar.setCenterText(getString(title)); - } - } - - @Override - protected boolean isActionBar() { - return true; - } -} diff --git a/common_base/src/main/java/com/wss/common/base/BaseActionBarActivity.java b/common_base/src/main/java/com/wss/common/base/BaseActionBarActivity.java new file mode 100644 index 0000000..5f2e01f --- /dev/null +++ b/common_base/src/main/java/com/wss/common/base/BaseActionBarActivity.java @@ -0,0 +1,240 @@ +package com.wss.common.base; + +import android.os.Bundle; +import android.view.View; + +import com.wss.common.base.mvp.BasePresenter; +import com.wss.common.widget.ActionBar; + +import androidx.annotation.Nullable; +import butterknife.BindView; + +/** + * Describe:所有带actionBar的Activity基类 + * Created by 吴天强 on 2018/10/18. + */ +public abstract class BaseActionBarActivity

extends BaseMvpActivity

{ + + @BindView(R2.id.actionbar) + ActionBar actionBar; + + @BindView(R2.id.action_bar_line) + View actionBarLine; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + actionBar.setVisibility(View.VISIBLE); + //沉浸式状态栏 + setImmersionBarColor(R.color.white); + } + + + /** + * 设置左边文字 + * + * @param text 文字 + */ + protected void setLeftText(String text) { + setLeftText(text, null); + } + + /** + * @param text 文字 + * @param listener 事件监听 + */ + protected void setLeftText(String text, View.OnClickListener listener) { + setLeftText(text, R.color.color_333333, listener); + } + + /** + * 设置左边文字 + * + * @param text 文字 + * @param textColor 文字颜色 + * @param listener 事件监听 + */ + protected void setLeftText(String text, int textColor, View.OnClickListener listener) { + if (actionBar != null) { + if (textColor != 0) { + actionBar.setLeftTextColor(getResources().getColor(textColor)); + } + actionBar.setLeftText(text, listener); + } + } + + /** + * 设置左边icon + * + * @param drawable icon resId + * @param listener 事件监听 + */ + protected void setLeftIcon(int drawable, View.OnClickListener listener) { + if (actionBar != null) { + actionBar.setLeftIcon(drawable, listener); + } + } + + /** + * 设置左边icon + * + * @param listener 事件监听 + */ + protected void setLeftIcon(View.OnClickListener listener) { + setLeftIcon(R.drawable.ic_back_black, listener); + } + + /** + * 设置左边View + * + * @param view view + */ + protected void setLeftView(View view) { + if (actionBar != null) { + actionBar.setLeftView(view); + } + } + + /** + * 设置中间文字 + * + * @param text text + */ + protected void setCenterText(int text) { + setCenterText(getString(text)); + } + + /** + * 设置中间文字 + * + * @param text text + */ + protected void setCenterText(String text) { + setCenterText(text, R.color.color_333333); + } + + /** + * 设置中间文字 + * + * @param text text + * @param textColor 文字颜色 + */ + protected void setCenterText(String text, int textColor) { + setCenterText(text, textColor, null); + } + + /** + * 设置中间文字 + * + * @param text text + * @param textColor 文字颜色 + * @param listener 事件监听 + */ + protected void setCenterText(String text, int textColor, View.OnClickListener listener) { + if (actionBar != null) { + if (textColor != 0) { + actionBar.setCenterTextColor(textColor); + } + //加粗 + actionBar.setCenterTextBold(true); + actionBar.setCenterText(text, listener); + } + } + + /** + * 设置中间View + * + * @param view view + */ + protected void setCenterView(View view) { + if (actionBar != null) { + actionBar.setCenterView(view); + } + } + + /** + * 设置右边文字 + * + * @param resId 文字 + * @param listener 事件监听 + */ + protected void setRightText(int resId, View.OnClickListener listener) { + setRightText(getString(resId), listener); + } + + /** + * 设置右边文字 + * + * @param text 文字 + * @param listener 事件监听 + */ + protected void setRightText(String text, View.OnClickListener listener) { + setRightText(text, R.color.color_333333, listener); + } + + /** + * 设置右边文字 + * + * @param text 文字 + * @param textColor 文字颜色 + * @param listener 事件监听 + */ + protected void setRightText(String text, int textColor, View.OnClickListener listener) { + if (actionBar != null) { + if (textColor != 0) { + actionBar.setRightTextColor(textColor); + } + actionBar.setRightText(text, listener); + } + } + + /** + * 设置右边icon + * + * @param drawable 图片 + * @param listener 事件监听 + */ + protected void setRightIcon(int drawable, View.OnClickListener listener) { + if (actionBar != null) { + actionBar.setRightIcon(drawable, listener); + } + } + + /** + * 设置右边View + * + * @param view view + */ + protected void setRightView(View view) { + if (actionBar != null) { + actionBar.setRightView(view); + } + } + + /** + * 返回顶部TitleBar + * + * @return ActionBar + */ + protected ActionBar getTitleBar() { + return actionBar; + } + + /** + * 设置ActionBar下面的横线 + * + * @param show 是否显示 + */ + protected void showActionBarLine(boolean show) { + actionBarLine.setVisibility(show ? View.VISIBLE : View.GONE); + } + + /** + * 设置左边返回图标是否显示 + * + * @param show 是否显示 + */ + public void showBackImg(boolean show) { + actionBar.showBackImg(show); + } +} diff --git a/common_base/src/main/java/com/wss/common/base/BaseActivity.java b/common_base/src/main/java/com/wss/common/base/BaseActivity.java index 8cd0568..1c44553 100644 --- a/common_base/src/main/java/com/wss/common/base/BaseActivity.java +++ b/common_base/src/main/java/com/wss/common/base/BaseActivity.java @@ -2,29 +2,24 @@ import android.content.Context; import android.content.Intent; -import android.net.Uri; import android.os.Bundle; -import android.provider.Settings; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.app.FragmentActivity; import android.view.View; import android.view.ViewGroup; import android.view.ViewStub; import android.view.WindowManager; import android.widget.TextView; -import com.gyf.barlibrary.ImmersionBar; -import com.orhanobut.logger.Logger; +import com.gyf.immersionbar.BarHide; +import com.gyf.immersionbar.ImmersionBar; +import com.scwang.smartrefresh.layout.SmartRefreshLayout; import com.wss.common.bean.Event; import com.wss.common.utils.EventBusUtils; -import com.wss.common.widget.dialog.LoadingDialog; import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; -import java.util.Arrays; - +import androidx.annotation.Nullable; +import androidx.fragment.app.FragmentActivity; import butterknife.ButterKnife; import butterknife.Unbinder; @@ -32,53 +27,72 @@ * Describe:所有Activity的基类 * Created by 吴天强 on 2018/10/15. */ - public abstract class BaseActivity extends FragmentActivity { - private Unbinder unbinder; private ViewStub emptyView; - protected Context mContext; - protected ImmersionBar mImmersionBar; - protected LoadingDialog loadingDialog; - + protected Context context; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); - mContext = this; + //加入Activity管理器 + BaseApplication.i().getActivityManage().addActivity(this); + context = this; getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN); - if (isActionBar()) { + if (!isFullScreenLayout()) { setContentView(R.layout.activity_base); ((ViewGroup) findViewById(R.id.fl_content)).addView(getLayoutInflater().inflate(getLayoutId(), null)); - } else { - setContentView(getLayoutId()); + unbinder = ButterKnife.bind(this); } - //初始化ButterKnife - unbinder = ButterKnife.bind(this); - - //沉浸式状态栏 - initImmersionBar(R.color.blue); - - //加入Activity管理器 - BaseApplication.getApplication().getActivityManage().addActivity(this); - if (regEvent()) { + if (registerEventBus()) { EventBusUtils.register(this); } - loadingDialog = new LoadingDialog(mContext); + } + + /** + * 设置沉浸栏颜色 + * + * @param statusBarColor 颜色 + */ + protected void setImmersionBarColor(int statusBarColor) { + setImmersionBarColor(statusBarColor, false); + } + /** + * 设置沉浸栏颜色 + * + * @param statusBarColor 沉浸栏颜色 + */ + protected void setImmersionBarColor(int statusBarColor, boolean fitsSystemWindows) { + setImmersionBarColor(statusBarColor, R.color.black, fitsSystemWindows); } /** - * 沉浸栏颜色 + * 设置沉浸栏颜色 + * + * @param statusBarColor 沉浸栏颜色 + * @param navigationBarColor 沉浸栏图标颜色 */ - protected void initImmersionBar(int color) { - mImmersionBar = ImmersionBar.with(this); - if (color != 0) { - mImmersionBar.statusBarColor(color); - } - mImmersionBar.init(); + protected void setImmersionBarColor(int statusBarColor, int navigationBarColor, boolean fitsSystemWindows) { + ImmersionBar.with(this) + .statusBarColor(statusBarColor) + .navigationBarColor(navigationBarColor) + .fitsSystemWindows(fitsSystemWindows) + .autoDarkModeEnable(true) + .statusBarDarkFont(true) + .init(); + } + + /** + * 隐藏状态栏、导航栏 + */ + protected void setImmersionBarHide() { + ImmersionBar.with(this) + .fitsSystemWindows(false) + .hideBar(BarHide.FLAG_HIDE_BAR) + .init(); } @Override @@ -87,15 +101,11 @@ protected void onDestroy() { if (unbinder != null) { unbinder.unbind(); } - if (regEvent()) { + if (registerEventBus()) { EventBusUtils.unregister(this); } - //必须调用该方法,防止内存泄漏 - if (mImmersionBar != null) { - mImmersionBar.destroy(); - } //将Activity从管理器移除 - BaseApplication.getApplication().getActivityManage().removeActivity(this); + BaseApplication.i().getActivityManage().removeActivity(this); } @Override @@ -104,39 +114,91 @@ public void onAttachedToWindow() { initView(); } - //***************************************空页面方法************************************* - protected void showEmptyView(String text) { - showEmptyOrErrorView(text, R.drawable.bg_no_data); + + @Override + public void startActivity(Intent intent) { + super.startActivity(intent); + if (isAnimate()) { + overridePendingTransition(R.anim.anim_right_in, R.anim.anim_right_out); + } + } + + @Override + public void startActivityForResult(Intent intent, int requestCode) { + super.startActivityForResult(intent, requestCode); + if (isAnimate()) { + overridePendingTransition(R.anim.anim_right_in, R.anim.anim_right_out); + } + } + + @Override + public void finish() { + if (isAnimate()) { + overridePendingTransition(R.anim.anim_right_in, R.anim.anim_right_out); + } + super.finish(); } + + //***************************************空页面方法 start************************************* + + /** + * 数据为空页面 + */ protected void showEmptyView() { showEmptyView(getString(R.string.no_data)); } - protected void showErrorView(String text) { - showEmptyOrErrorView(text, R.drawable.bg_no_net); + /** + * 数据为空页面 + * + * @param text 显示文案 + */ + protected void showEmptyView(String text) { + showEmptyOrErrorView(text, R.drawable.bg_no_data, false); } + + /** + * 请求数据报错页面 + */ protected void showErrorView() { - showErrorView(getString(R.string.error_data)); + showErrorView(getString(R.string.network_error_server_error)); + } + + /** + * 请求数据报错页面 + * + * @param text 显示文案 + */ + protected void showErrorView(String text) { + showEmptyOrErrorView(text, R.drawable.bg_no_net , true); } - public void showEmptyOrErrorView(String text, int img) { + /** + * 请求数据报错或者为空页面 + * + * @param text 提示文案 + * @param iconResId 显示的icon + */ + public void showEmptyOrErrorView(String text, int iconResId, boolean showRefreshButton) { if (emptyView == null) { emptyView = findViewById(R.id.vs_empty); } emptyView.setVisibility(View.VISIBLE); - findViewById(R.id.iv_empty).setBackgroundResource(img); + findViewById(R.id.iv_empty).setBackgroundResource(iconResId); ((TextView) findViewById(R.id.tv_empty)).setText(text); - findViewById(R.id.ll_empty).setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - onPageClick(); - } - }); + if (showRefreshButton) { + View refreshButton = findViewById(R.id.tv_try_again); + refreshButton.setVisibility(View.VISIBLE); + refreshButton.setOnClickListener(v -> onRefreshRetry()); + } } + /** + * 隐藏空页面 + */ protected void hideEmptyView() { if (emptyView != null) { emptyView.setVisibility(View.GONE); @@ -144,69 +206,72 @@ protected void hideEmptyView() { } /** - * 空页面被点击 + * 刷新重试 */ - protected void onPageClick() { - + protected void onRefreshRetry() { } - //***************************************空页面方法********************************* + //***************************************空页面方法 end********************************* - - @Override - public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { - super.onRequestPermissionsResult(requestCode, permissions, grantResults); - Logger.e("permissions:" + Arrays.toString(permissions) + " grantResults:" + Arrays.toString(grantResults)); - - //如果有未授权权限则跳转设置页面 - if (!requestPermissionsResult(grantResults)) { - Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); - intent.setData(Uri.parse("package:" + getPackageName())); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - startActivity(intent); + /** + * 停止刷新和加载更多 + * + * @param layout 刷新layout + */ + protected void stopRefresh(SmartRefreshLayout layout) { + if (layout == null) { + return; } - - + layout.finishLoadMore(); + layout.finishRefresh(); } /** - * 判断授权结果 + * 是否布局伸入状态栏类型Activity + * + * @return boolean */ - private boolean requestPermissionsResult(int[] grantResults) { - for (int code : grantResults) { - if (code == -1) { - return false; - } - } - return true; + protected boolean isFullScreenLayout() { + return false; } - /** - * 子类接受事件 重写该方法 + * 切换页面是否需要过渡动画 + * + * @return boolean */ - @Subscribe(threadMode = ThreadMode.MAIN) - public void onEventBus(Event event) { + protected boolean isAnimate() { + return true; } - /** - * 是否需要ActionBar - * TODO 暂时用此方法 后续优化 + * 需要接收事件 重写该方法 并返回true + * + * @return boolean */ - protected boolean isActionBar() { + protected boolean registerEventBus() { return false; } /** - * 需要接收事件 重写该方法 并返回true + * 子类接受事件 重写该方法 + * + * @param event 事件 */ - protected boolean regEvent() { - return false; + @Subscribe(threadMode = ThreadMode.MAIN) + public void onEventBus(Event event) { } + /** + * 返回页面layout + * + * @return layout + */ protected abstract int getLayoutId(); + /** + * 初始化View + */ protected abstract void initView(); } diff --git a/common_base/src/main/java/com/wss/common/base/BaseApplication.java b/common_base/src/main/java/com/wss/common/base/BaseApplication.java index c6992a3..2e64d20 100644 --- a/common_base/src/main/java/com/wss/common/base/BaseApplication.java +++ b/common_base/src/main/java/com/wss/common/base/BaseApplication.java @@ -2,7 +2,7 @@ import android.app.Application; import android.content.Context; -import android.support.multidex.MultiDex; +import android.widget.Toast; import com.alibaba.android.arouter.launcher.ARouter; import com.orhanobut.logger.AndroidLogAdapter; @@ -10,26 +10,67 @@ import com.orhanobut.logger.LogcatLogStrategy; import com.orhanobut.logger.Logger; import com.orhanobut.logger.PrettyFormatStrategy; +import com.scwang.smartrefresh.layout.SmartRefreshLayout; +import com.scwang.smartrefresh.layout.footer.ClassicsFooter; +import com.scwang.smartrefresh.layout.header.ClassicsHeader; +import com.wss.common.bean.User; +import com.wss.common.constants.Constants; +import com.wss.common.constants.Dic; import com.wss.common.manage.ActivityManage; -import com.wss.common.manage.CrashHandlerManage; +import com.wss.common.utils.CacheUtils; +import com.wss.common.utils.ToastUtils; +import com.wss.common.utils.ValidUtils; +import com.wss.common.utils.toast.ToastInterceptor; +import com.wss.common.utils.toast.style.ToastBlackStyle; + +import org.jetbrains.annotations.Contract; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.X509TrustManager; + +import androidx.multidex.MultiDex; +import io.reactivex.disposables.Disposable; +import io.reactivex.plugins.RxJavaPlugins; +import okhttp3.ConnectionSpec; +import okhttp3.OkHttpClient; +import rxhttp.HttpSender; +import rxhttp.wrapper.ssl.SSLSocketFactoryImpl; +import rxhttp.wrapper.ssl.X509TrustManagerImpl; /** * Describe:基础Application所有需要模块化开发的module都需要继承自BaseApplication * Created by 吴天强 on 2018/10/12. */ public class BaseApplication extends Application { - - //全局唯一的context + /** + * 全局上下文 + */ private static BaseApplication application; - - //Activity管理器 + /** + * Activity管理器 + */ private ActivityManage activityManage; + /** + * 保存所有网络请求 + */ + private Map netDisposable; + + /** + * 登录用户 + */ + private User user; + @Override protected void attachBaseContext(Context base) { super.attachBaseContext(base); application = this; - //MultiDex分包方法 必须最先初始化 + //MultiDex分包方法 初始化 MultiDex.install(this); } @@ -37,37 +78,98 @@ protected void attachBaseContext(Context base) { public void onCreate() { super.onCreate(); activityManage = new ActivityManage(); - initARouter(); + //初始化日志框架 initLogger(); - initCrashManage(); + //初始化ARouter + initARouter(); + //初始化Toast + initToast(); + //初始化网络框架 + initRXHttp(); + //刷新框架 + initRefreshLayout(); } /** - * 初始化崩溃管理器 + * 初始化刷新框架 */ - private void initCrashManage() { - if (!BuildConfig.DEBUG) { - CrashHandlerManage.getInstance() - .init(getApplicationContext()); - } + private void initRefreshLayout() { + //设置全局的Header构建器 + SmartRefreshLayout.setDefaultRefreshHeaderCreator((context, layout) -> { + //指定为经典Footer,默认是 BezierRadarHeader + return new ClassicsHeader(context); + }); + //设置全局的Footer构建器 + SmartRefreshLayout.setDefaultRefreshFooterCreator((context, layout) -> { + //指定为经典Footer,默认是 BallPulseFooter + return new ClassicsFooter(context).setDrawableSize(20); + }); } + /** + * B + * 初始化Toast + */ + private void initToast() { + ToastUtils.setToastInterceptor(new ToastInterceptor() { + @Override + public boolean intercept(Toast toast, CharSequence text) { + boolean intercept = super.intercept(toast, text); + if (intercept) { + Logger.e("空 Toast"); + } else { + Logger.d(text.toString()); + } + return intercept; + } + }); + // 初始化吐司工具类 + ToastUtils.init(this, new ToastBlackStyle(this)); + } + + /** + * 初始化网络请求 + */ + private void initRXHttp() { + X509TrustManager trustManager = new X509TrustManagerImpl(); + SSLSocketFactory sslSocketFactory = new SSLSocketFactoryImpl(trustManager); + HttpSender.setDebug(BuildConfig.DEBUG); + HttpSender.init(new OkHttpClient.Builder() + .connectTimeout(Constants.Net.TIME_OUT, TimeUnit.SECONDS) + .readTimeout(Constants.Net.TIME_OUT, TimeUnit.SECONDS) + .writeTimeout(Constants.Net.TIME_OUT, TimeUnit.SECONDS) + .connectionSpecs(Arrays.asList(ConnectionSpec.COMPATIBLE_TLS, ConnectionSpec.CLEARTEXT)) + //添加信任证书 + .sslSocketFactory(sslSocketFactory, trustManager) + //忽略Host验证 + .hostnameVerifier(((hostname, session) -> true)) + .build()); + RxJavaPlugins.setErrorHandler(throwable -> { + //Rx全局异常处理 + }); + } /** * 初始化日志打印框架 */ private void initLogger() { FormatStrategy formatStrategy = PrettyFormatStrategy.newBuilder() - .showThreadInfo(false) //(可选)是否显示线程信息。 默认值为true - .methodCount(2) //(可选)要显示的方法行数。 默认2 - .methodOffset(7) //(可选)设置调用堆栈的函数偏移值,0的话则从打印该Log的函数开始输出堆栈信息,默认是0 - .logStrategy(new LogcatLogStrategy()) //(可选)更改要打印的日志策略。 默认LogCat - .tag("AMD") //(可选)每个日志的全局标记。 默认PRETTY_LOGGER + //(可选)是否显示线程信息。 默认值为true + .showThreadInfo(false) + //(可选)要显示的方法行数。 默认2 + .methodCount(0) + //(可选)设置调用堆栈的函数偏移值,0的话则从打印该Log的函数开始输出堆栈信息,默认是0 + .methodOffset(7) + //(可选)更改要打印的日志策略。 默认LogCat + .logStrategy(new LogcatLogStrategy()) + //(可选)每个日志的全局标记。 默认PRETTY_LOGGER + .tag("APP_LOG") .build(); + Logger.addLogAdapter(new AndroidLogAdapter(formatStrategy) { @Override public boolean isLoggable(int priority, String tag) { - //DEBUG模式下不打印LOG + //非DEBUG模式下不打印LOG return BuildConfig.DEBUG; } }); @@ -78,10 +180,12 @@ public boolean isLoggable(int priority, String tag) { */ private void initARouter() { if (BuildConfig.DEBUG) { - ARouter.openLog(); // 打印日志 - ARouter.openDebug(); // 开启调试模式(如果在InstantRun模式下运行,必须开启调试模式!线上版本需要关闭,否则有安全风险) + // 打印日志 + ARouter.openLog(); + // 开启调试模式(如果在InstantRun模式下运行,必须开启调试模式!线上版本需要关闭,否则有安全风险) + ARouter.openDebug(); } - ARouter.init(application);// 尽可能早,推荐在Application中初始化 + ARouter.init(application); } /** @@ -98,7 +202,8 @@ public void onTerminate() { * * @return BaseApplication */ - public static BaseApplication getApplication() { + @Contract(pure = true) + public static BaseApplication i() { return application; } @@ -113,7 +218,9 @@ public void exitApp() { } /** - * 返回Activity管理器 + * 获取Activity管理器 + * + * @return ActivityManage */ public ActivityManage getActivityManage() { if (activityManage == null) { @@ -122,5 +229,90 @@ public ActivityManage getActivityManage() { return activityManage; } + /** + * 获取存放的请求对象 + * + * @return Map + */ + public Map getNetDisposables() { + if (netDisposable == null) { + return new HashMap<>(16); + } + return netDisposable; + } + + /** + * 退出登录清除换群 + */ + public void loginOutClean() { + + } + + /** + * 添加请求对象 + * + * @param requestId 请求ID + * @param disposable 对象 + */ + public void addNetDisposable(String requestId, Disposable disposable) { + if (netDisposable == null) { + netDisposable = new HashMap<>(16); + } + netDisposable.put(requestId, disposable); + } + + /** + * 根据请求ID移除该对象 + * + * @param requestId 请求ID + */ + public void removeNetDisposable(String requestId) { + netDisposable.remove(requestId); + } + + /** + * 保存用户信息 + * + * @param user 登录用户 + */ + public void setUser(User user) { + CacheUtils.get(this).put(Dic.LOGIN_USER_INFO, user); + this.user = user; + } + + /** + * 获取用户信息 + * + * @return User + */ + public User getUser() { + if (!ValidUtils.isValid(user) || !ValidUtils.isValid(user.getId())) { + //如果保存的user为空,则去本地缓存中取 + user = (User) CacheUtils.get(this).getAsObject(Dic.LOGIN_USER_INFO); + } + if (!ValidUtils.isValid(user)) { + //防止异常情况下getUser对象为null问题 + user = new User(); + } + return user; + } + /** + * 是否登录 + * + * @return boolean + */ + public boolean isLogged() { + User user = getUser(); + return ValidUtils.isValid(user) && ValidUtils.isValid(user.getId()); + } + + + public String getDeviceId() { + return ""; + } + + public String getLoginToken() { + return ""; + } } \ No newline at end of file diff --git a/common_base/src/main/java/com/wss/common/base/BaseFragment.java b/common_base/src/main/java/com/wss/common/base/BaseFragment.java index cbb55b4..e463b3a 100644 --- a/common_base/src/main/java/com/wss/common/base/BaseFragment.java +++ b/common_base/src/main/java/com/wss/common/base/BaseFragment.java @@ -2,23 +2,24 @@ import android.content.Context; import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.ViewStub; import android.widget.TextView; +import com.scwang.smartrefresh.layout.SmartRefreshLayout; import com.wss.common.bean.Event; import com.wss.common.bean.HorizontalTabTitle; -import com.wss.common.widget.dialog.LoadingDialog; +import com.wss.common.utils.ValidUtils; import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; import butterknife.ButterKnife; import butterknife.Unbinder; @@ -26,36 +27,36 @@ * Describe:所有Fragment的基类 * Created by 吴天强 on 2018/10/17. */ - public abstract class BaseFragment extends Fragment { + protected Context context; private ViewStub emptyView; private View rootView; private Unbinder unBinder; - protected Context mContext; - protected LoadingDialog loadingDialog; - protected HorizontalTabTitle tabTitle; - + private HorizontalTabTitle tabTitle; @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); - mContext = getActivity(); - loadingDialog = new LoadingDialog(mContext); + context = getActivity(); } + @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - rootView = inflater.inflate(R.layout.fragment_base, container, false); + rootView = inflater.inflate(R.layout.layout_base, container, false); ((ViewGroup) rootView.findViewById(R.id.fl_content)).addView(getLayoutInflater().inflate(getLayoutId(), null)); unBinder = ButterKnife.bind(this, rootView); - if (regEvent()) { - EventBus.getDefault().register(this); + if (registerEventBus()) { + if (!EventBus.getDefault().isRegistered(this)) { + EventBus.getDefault().register(this); + } } return rootView; } + @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); initView(); @@ -68,37 +69,73 @@ public void onDestroy() { if (unBinder != null) { unBinder.unbind(); } - if (regEvent()) { + if (registerEventBus()) { EventBus.getDefault().unregister(this); } } - //***************************************空页面方法************************************* + //***************************************空页面方法 start ************************************* + + /** + * 数据为空页面 + */ protected void showEmptyView() { - showEmptyOrErrorView(getString(R.string.no_data), R.drawable.bg_no_data); + showEmptyView(getString(R.string.no_data)); + } + + /** + * 数据为空页面 + * + * @param text 显示文案 + */ + protected void showEmptyView(String text) { + showEmptyOrErrorView(text, R.drawable.bg_no_data, false); } + /** + * 请求数据报错页面 + */ protected void showErrorView() { - showEmptyOrErrorView(getString(R.string.error_data), R.drawable.bg_no_net); + showErrorView(getString(R.string.network_error_server_error)); } - public void showEmptyOrErrorView(String text, int img) { + /** + * 请求数据报错页面 + * + * @param text 显示文案 + */ + protected void showErrorView(String text) { + showEmptyOrErrorView(text, R.drawable.bg_no_net, true); + } + + + /** + * 请求数据报错或者为空页面 + * + * @param text 提示文案 + * @param iconResId 显示的icon + */ + public void showEmptyOrErrorView(String text, int iconResId, boolean showRefreshButton) { if (emptyView == null) { emptyView = rootView.findViewById(R.id.vs_empty); } emptyView.setVisibility(View.VISIBLE); - rootView.findViewById(R.id.iv_empty).setBackgroundResource(img); + rootView.findViewById(R.id.iv_empty).setBackgroundResource(iconResId); ((TextView) rootView.findViewById(R.id.tv_empty)).setText(text); - rootView.findViewById(R.id.ll_empty).setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - onPageClick(); - } - }); + View refreshButton = rootView.findViewById(R.id.tv_try_again); + if (showRefreshButton) { + refreshButton.setVisibility(View.VISIBLE); + refreshButton.setOnClickListener(v -> onRefreshRetry()); + } else { + refreshButton.setVisibility(View.GONE); + } } + /** + * 隐藏空页面 + */ protected void hideEmptyView() { if (emptyView != null) { emptyView.setVisibility(View.GONE); @@ -106,22 +143,54 @@ protected void hideEmptyView() { } /** - * 空页面被点击 + * 刷新重试 */ - protected void onPageClick() { + protected void onRefreshRetry() { + } + + //***************************************空页面方法 end********************************* + /** + * 停止刷新和加载更多 + * + * @param layout 刷新layout + */ + protected void stopRefresh(SmartRefreshLayout layout) { + if (layout == null) { + return; + } + layout.finishLoadMore(); + layout.finishRefresh(); } - //***************************************空页面方法********************************* + /** + * 返回Fragment的根布局 + * + * @return View + */ + protected View getRootView() { + return rootView; + } /** - * 给Fragment设置数据 + * 给Fragment设置TabTile数据 + * + * @param data tabtitle */ - public void setFragmentData(HorizontalTabTitle data) { + public void setTabTitle(HorizontalTabTitle data) { this.tabTitle = data; } + /** + * 返回ViewPager+Fragment滑动 设置给子Fragment的Tab数据 + * + * @return HorizontalTabTitle + */ + public HorizontalTabTitle getTabTitle() { + return ValidUtils.isValid(tabTitle) ? tabTitle : new HorizontalTabTitle(""); + } + /** * 子类接受事件 重写该方法 */ @@ -132,13 +201,20 @@ public void onEventBus(Event event) { /** * 需要接收事件 重新该方法 并返回true */ - protected boolean regEvent() { + protected boolean registerEventBus() { return false; } - + /** + * 返回页面layout + * + * @return layout + */ protected abstract int getLayoutId(); + /** + * 初始化View + */ protected abstract void initView(); } diff --git a/common_base/src/main/java/com/wss/common/base/BaseFullScreenActivity.java b/common_base/src/main/java/com/wss/common/base/BaseFullScreenActivity.java new file mode 100644 index 0000000..b6df48f --- /dev/null +++ b/common_base/src/main/java/com/wss/common/base/BaseFullScreenActivity.java @@ -0,0 +1,34 @@ +package com.wss.common.base; + + +import com.gyf.immersionbar.ImmersionBar; +import com.wss.common.base.mvp.BasePresenter; + +/** + * Describe:布局需要伸入状态栏下面的Activity继承该类, + * 并通过setContentView来设置layout,重新注册ButterKnife + * Created by 吴天强 on 2020/4/28. + */ +public abstract class BaseFullScreenActivity

extends BaseMvpActivity

{ + + @Override + protected boolean isFullScreenLayout() { + return true; + } + + @Override + protected int getLayoutId() { + //该方法仅仅是为了实现父类的抽象方法,无任何意义,忽略即可 + return R.layout.layout_nothing; + } + + @Override + protected void initView() { + //布局可伸入状态栏 + ImmersionBar.with(this) + .statusBarColor(R.color.transparent) + .statusBarDarkFont(true) + .fullScreen(true) + .init(); + } +} diff --git a/common_base/src/main/java/com/wss/common/base/HorizontalTabActivity.java b/common_base/src/main/java/com/wss/common/base/BaseHorizontalTabActivity.java similarity index 71% rename from common_base/src/main/java/com/wss/common/base/HorizontalTabActivity.java rename to common_base/src/main/java/com/wss/common/base/BaseHorizontalTabActivity.java index e528b05..a1ab86f 100644 --- a/common_base/src/main/java/com/wss/common/base/HorizontalTabActivity.java +++ b/common_base/src/main/java/com/wss/common/base/BaseHorizontalTabActivity.java @@ -1,7 +1,5 @@ package com.wss.common.base; -import android.support.annotation.CallSuper; -import android.support.v4.view.ViewPager; import com.wss.common.adapter.FragmentPagerAdapter; import com.wss.common.base.mvp.BasePresenter; @@ -10,15 +8,15 @@ import java.util.List; +import androidx.annotation.CallSuper; +import androidx.viewpager.widget.ViewPager; import butterknife.BindView; /** * Describe:带水平选项卡的Activity * Created by 吴天强 on 2018/10/22. */ - -public abstract class HorizontalTabActivity

extends ActionBarActivity

{ - +public abstract class BaseHorizontalTabActivity

extends BaseActionBarActivity

{ @BindView(R2.id.pst_tab) PagerSlidingTabStrip tabStrip; @@ -38,15 +36,24 @@ protected void initView() { viewPager.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager(), getTabTitles()) { @Override public BaseFragment getTabFragment() { - return HorizontalTabActivity.this.getTabFragment(); + return BaseHorizontalTabActivity.this.getTabFragment(); } }); tabStrip.setViewPager(viewPager); } + /** + * 选项卡List + * + * @return List + */ protected abstract List getTabTitles(); + /** + * 滑动Fragment + * + * @return BaseFragment + */ protected abstract BaseFragment getTabFragment(); - } diff --git a/common_base/src/main/java/com/wss/common/base/BaseMvpActivity.java b/common_base/src/main/java/com/wss/common/base/BaseMvpActivity.java index 30e6ab6..bee6692 100644 --- a/common_base/src/main/java/com/wss/common/base/BaseMvpActivity.java +++ b/common_base/src/main/java/com/wss/common/base/BaseMvpActivity.java @@ -2,11 +2,14 @@ import android.content.Context; import android.os.Bundle; -import android.support.annotation.Nullable; import android.text.TextUtils; import com.wss.common.base.mvp.BasePresenter; import com.wss.common.base.mvp.IBaseView; +import com.wss.common.widget.dialog.LoadingDialog; + +import androidx.annotation.Nullable; +import androidx.lifecycle.LifecycleOwner; /** * Describe:所有需要Mvp开发的Activity的基类 @@ -15,12 +18,14 @@ @SuppressWarnings("unchecked") public abstract class BaseMvpActivity

extends BaseActivity implements IBaseView { - protected P presenter; - + private P presenter; + private LoadingDialog loadingDialog; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); + loadingDialog = new LoadingDialog(context); + loadingDialog.setCancelable(loadingCancelable()); //创建present presenter = createPresenter(); if (presenter != null) { @@ -35,16 +40,30 @@ protected void onDestroy() { presenter.detachView(); presenter = null; } + } + /** + * 返回Presenter + * + * @return P + */ + protected P getPresenter() { + return presenter; } - //***************************************IBaseView方法实现************************************* + //***************************************IBaseView方法实现 start************************************* + @Override public void showLoading() { showLoading(""); } + /** + * 显示加载框 + * + * @param msg 加载框文字 + */ public void showLoading(String msg) { if (loadingDialog != null && !loadingDialog.isShowing()) { if (!TextUtils.isEmpty(msg)) { @@ -52,6 +71,7 @@ public void showLoading(String msg) { } loadingDialog.show(); } + hideEmptyView(); } @Override @@ -61,24 +81,41 @@ public void dismissLoading() { } } + /** + * 加载框是否可以取消 + * + * @return boolean + */ + protected boolean loadingCancelable() { + return true; + } + + @Override public void onEmpty(Object tag) { - + dismissLoading(); } @Override public void onError(Object tag, String errorMsg) { + dismissLoading(); + } + @Override + public LifecycleOwner getLifecycleOwner() { + return this; } @Override public Context getContext() { - return mContext; + return context; } - //***************************************IBaseView方法实现************************************* + //***************************************IBaseView方法实现 end************************************* /** * 创建Presenter + * + * @return Presenter */ protected abstract P createPresenter(); } diff --git a/common_base/src/main/java/com/wss/common/base/BaseMvpFragment.java b/common_base/src/main/java/com/wss/common/base/BaseMvpFragment.java index 4d7ff26..dc4ec42 100644 --- a/common_base/src/main/java/com/wss/common/base/BaseMvpFragment.java +++ b/common_base/src/main/java/com/wss/common/base/BaseMvpFragment.java @@ -1,25 +1,30 @@ package com.wss.common.base; + import android.os.Bundle; -import android.support.annotation.Nullable; import com.wss.common.base.mvp.BasePresenter; import com.wss.common.base.mvp.IBaseView; +import com.wss.common.widget.dialog.LoadingDialog; + +import androidx.annotation.Nullable; +import androidx.lifecycle.LifecycleOwner; /** * Describe:所有需要Mvp开发的Fragment的基类 * Created by 吴天强 on 2018/10/17. */ - +@SuppressWarnings("unchecked") public abstract class BaseMvpFragment

extends BaseFragment implements IBaseView { - protected P presenter; - + private P presenter; + private LoadingDialog loadingDialog; - @SuppressWarnings("unchecked") @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); + loadingDialog = new LoadingDialog(context); + loadingDialog.setCancelable(loadingCancelable()); //创建present presenter = createPresenter(); if (presenter != null) { @@ -33,16 +38,26 @@ public void onDestroy() { if (presenter != null) { presenter.detachView(); } + } + /** + * 返回presenter + * + * @return P + */ + protected P getPresenter() { + return presenter; } + //***************************************IBaseView方法实现 start ************************************* + - //***************************************IBaseView方法实现************************************* @Override public void showLoading() { if (loadingDialog != null && !loadingDialog.isShowing()) { loadingDialog.show(); } + hideEmptyView(); } @Override @@ -52,19 +67,36 @@ public void dismissLoading() { } } + /** + * 加载框是否可以取消 + * + * @return boolean + */ + protected boolean loadingCancelable() { + return true; + } + @Override public void onEmpty(Object tag) { - + dismissLoading(); } @Override public void onError(Object tag, String errorMsg) { + dismissLoading(); + } + @Override + public LifecycleOwner getLifecycleOwner() { + return this; } - //***************************************IBaseView方法实现************************************* + + //***************************************IBaseView方法实现 end************************************* /** * 创建Presenter + * + * @return Presenter */ protected abstract P createPresenter(); } diff --git a/common_base/src/main/java/com/wss/common/base/BaseRefreshListActivity.java b/common_base/src/main/java/com/wss/common/base/BaseRefreshListActivity.java new file mode 100644 index 0000000..0769b17 --- /dev/null +++ b/common_base/src/main/java/com/wss/common/base/BaseRefreshListActivity.java @@ -0,0 +1,114 @@ +package com.wss.common.base; + +import com.scwang.smartrefresh.layout.SmartRefreshLayout; +import com.scwang.smartrefresh.layout.listener.OnRefreshLoadMoreListener; +import com.wss.common.base.mvp.BasePresenter; + +import androidx.annotation.CallSuper; +import androidx.recyclerview.widget.RecyclerView; +import butterknife.BindView; + +/** + * Describe:带下拉刷新 上拉加载更多的Activity + * 内部实现为刷新控件 SmartRefreshLayout + 列表控件 RecyclerView + * Created by 吴天强 on 2018/10/23. + */ +public abstract class BaseRefreshListActivity

extends BaseActionBarActivity

{ + + @BindView(R2.id.ptrl_list) + SmartRefreshLayout refreshLayout; + + @BindView(R2.id.recycle_view) + RecyclerView recyclerView; + + /** + * 适配器 + */ + private RecyclerView.Adapter adapter; + + @Override + protected int getLayoutId() { + return R.layout.layout_refresh; + } + + @CallSuper + @Override + protected void initView() { + adapter = createAdapter(); + refreshLayout.setOnRefreshLoadMoreListener(createRefreshListener()); + recyclerView.setLayoutManager(getLayoutManager()); + recyclerView.setAdapter(adapter); + + } + + @CallSuper + @Override + public void dismissLoading() { + super.dismissLoading(); + stopRefresh(); + } + + + @CallSuper + @Override + public void showLoading() { + super.showLoading(); + hideEmptyView(); + } + + /** + * 停止刷新 + */ + protected void stopRefresh() { + refreshLayout.finishRefresh(); + refreshLayout.finishLoadMore(); + } + + /** + * 获取刷新控件 + * + * @return PullToRefreshLayout + */ + protected SmartRefreshLayout getRefreshLayout() { + return refreshLayout; + } + + /** + * 获取加载数据列表控件 + * + * @return RecyclerView + */ + protected RecyclerView getRecyclerView() { + return recyclerView; + } + + /** + * 返回适配器 + * + * @return RecyclerView.Adapter + */ + protected RecyclerView.Adapter getAdapter() { + return adapter; + } + + /** + * 创建 RecyclerView LayoutManager + * + * @return RecyclerView.LayoutManager + */ + protected abstract RecyclerView.LayoutManager getLayoutManager(); + + /** + * 创建刷新监听器 + * + * @return OnPullRefreshListener + */ + protected abstract OnRefreshLoadMoreListener createRefreshListener(); + + /** + * 创建列表适配器 + * + * @return RecyclerView.Adapter + */ + protected abstract RecyclerView.Adapter createAdapter(); +} diff --git a/common_base/src/main/java/com/wss/common/base/BaseRefreshListFragment.java b/common_base/src/main/java/com/wss/common/base/BaseRefreshListFragment.java new file mode 100644 index 0000000..a7d45c0 --- /dev/null +++ b/common_base/src/main/java/com/wss/common/base/BaseRefreshListFragment.java @@ -0,0 +1,112 @@ +package com.wss.common.base; + + +import com.scwang.smartrefresh.layout.SmartRefreshLayout; +import com.scwang.smartrefresh.layout.listener.OnRefreshLoadMoreListener; +import com.wss.common.base.mvp.BasePresenter; + +import androidx.annotation.CallSuper; +import androidx.recyclerview.widget.RecyclerView; +import butterknife.BindView; + +/** + * Describe:带下拉刷新 上拉加载更多的Fragment + * 内部实现为刷新控件 SmartRefreshLayout + 列表控件 RecyclerView + * Created by 吴天强 on 2018/10/23. + */ +public abstract class BaseRefreshListFragment

extends BaseMvpFragment

{ + + @BindView(R2.id.ptrl_list) + SmartRefreshLayout refreshLayout; + + @BindView(R2.id.recycle_view) + RecyclerView recyclerView; + /** + * 适配器 + */ + private RecyclerView.Adapter adapter; + + @Override + protected int getLayoutId() { + return R.layout.layout_refresh; + } + + @CallSuper + @Override + protected void initView() { + adapter = createAdapter(); + refreshLayout.setOnRefreshLoadMoreListener(createRefreshListener()); + recyclerView.setLayoutManager(getLayoutManager()); + recyclerView.setAdapter(adapter); + } + + @CallSuper + @Override + public void dismissLoading() { + super.dismissLoading(); + stopRefresh(); + } + + @CallSuper + @Override + public void showLoading() { + super.showLoading(); + hideEmptyView(); + } + + /** + * 停止刷新 + */ + protected void stopRefresh() { + refreshLayout.finishRefresh(); + refreshLayout.finishLoadMore(); + } + + /** + * 获取刷新控件 + * + * @return PullToRefreshLayout + */ + protected SmartRefreshLayout getRefreshLayout() { + return refreshLayout; + } + + /** + * 获取加载数据列表控件 + * + * @return RecyclerView + */ + protected RecyclerView getRecyclerView() { + return recyclerView; + } + + /** + * 返回适配器 + * + * @return RecyclerView.Adapter + */ + protected RecyclerView.Adapter getAdapter() { + return adapter; + } + + /** + * 创建 RecyclerView LayoutManager + * + * @return RecyclerView.LayoutManager + */ + protected abstract RecyclerView.LayoutManager getLayoutManager(); + + /** + * 创建刷新监听器 + * + * @return OnPullRefreshListener + */ + protected abstract OnRefreshLoadMoreListener createRefreshListener(); + + /** + * 创建列表适配器 + * + * @return RecyclerView.Adapter + */ + protected abstract RecyclerView.Adapter createAdapter(); +} diff --git a/common_base/src/main/java/com/wss/common/base/RefreshListActivity.java b/common_base/src/main/java/com/wss/common/base/RefreshListActivity.java deleted file mode 100644 index eb896d4..0000000 --- a/common_base/src/main/java/com/wss/common/base/RefreshListActivity.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.wss.common.base; - -import android.support.annotation.CallSuper; -import android.support.v7.widget.RecyclerView; - -import com.wss.common.base.mvp.BasePresenter; -import com.wss.common.listener.OnListItemClickListener; -import com.wss.common.widget.pulltorefresh.OnPullRefreshListener; -import com.wss.common.widget.pulltorefresh.PullToRefreshLayout; - -import butterknife.BindView; - -/** - * Describe:带下拉刷新 上拉加载更多的Activity - * 内部实现为刷新控件 PullToRefreshLayout + 列表控件 RecyclerView - * Created by 吴天强 on 2018/10/23. - */ -public abstract class RefreshListActivity

extends ActionBarActivity

implements OnPullRefreshListener, OnListItemClickListener { - - @BindView(R2.id.ptrl_list) - PullToRefreshLayout refreshLayout; - - @BindView(R2.id.recycle_view) - RecyclerView recyclerView; - - protected RecyclerView.Adapter adapter; - - - @Override - protected int getLayoutId() { - return R.layout.layout_refresh; - } - - @CallSuper - @Override - protected void initView() { - refreshLayout.setOnPullRefreshListener(this); - recyclerView.setLayoutManager(getLayoutManager()); - adapter = createAdapter(); - recyclerView.setAdapter(adapter); - } - - @CallSuper - @Override - public void dismissLoading() { - super.dismissLoading(); - stopRefresh(); - } - - - @CallSuper - @Override - public void showLoading() { - super.showLoading(); - hideEmptyView(); - } - - /** - * 停止刷新 - */ - protected void stopRefresh() { - refreshLayout.finishRefresh(); - refreshLayout.finishLoadMore(); - } - - protected PullToRefreshLayout getRefreshLayout() { - return refreshLayout; - } - - protected RecyclerView getRecyclerView() { - return recyclerView; - } - - protected abstract RecyclerView.LayoutManager getLayoutManager(); - - protected abstract RecyclerView.Adapter createAdapter(); -} diff --git a/common_base/src/main/java/com/wss/common/base/RefreshListFragment.java b/common_base/src/main/java/com/wss/common/base/RefreshListFragment.java deleted file mode 100644 index 0193be3..0000000 --- a/common_base/src/main/java/com/wss/common/base/RefreshListFragment.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.wss.common.base; - -import android.support.annotation.CallSuper; -import android.support.v7.widget.RecyclerView; - -import com.wss.common.listener.OnListItemClickListener; -import com.wss.common.base.mvp.BasePresenter; -import com.wss.common.widget.pulltorefresh.OnPullRefreshListener; -import com.wss.common.widget.pulltorefresh.PullToRefreshLayout; - -import butterknife.BindView; - -/** - * Describe:带下拉刷新 上拉加载更多的Fragment - * 内部实现为刷新控件 PullToRefreshLayout + 列表控件 RecyclerView - * Created by 吴天强 on 2018/10/23. - */ -public abstract class RefreshListFragment

extends BaseMvpFragment

implements OnPullRefreshListener, OnListItemClickListener { - - - @BindView(R2.id.ptrl_list) - PullToRefreshLayout refreshLayout; - - @BindView(R2.id.recycle_view) - RecyclerView recyclerView; - - protected RecyclerView.Adapter adapter; - - @Override - protected int getLayoutId() { - return R.layout.layout_refresh; - } - - @CallSuper - @Override - protected void initView() { - adapter = createAdapter(); - refreshLayout.setOnPullRefreshListener(this); - recyclerView.setLayoutManager(getLayoutManager()); - recyclerView.setAdapter(adapter); - } - - @CallSuper - @Override - public void dismissLoading() { - super.dismissLoading(); - stopRefresh(); - } - - @CallSuper - @Override - public void showLoading() { - super.showLoading(); - hideEmptyView(); - } - - /** - * 停止刷新 - */ - protected void stopRefresh() { - refreshLayout.finishRefresh(); - refreshLayout.finishLoadMore(); - - } - - protected RecyclerView getRecyclerView() { - return recyclerView; - } - - protected PullToRefreshLayout getRefreshLayout() { - return refreshLayout; - } - - protected abstract RecyclerView.LayoutManager getLayoutManager(); - - protected abstract RecyclerView.Adapter createAdapter(); -} diff --git a/common_base/src/main/java/com/wss/common/base/adapter/BaseListAdapter.java b/common_base/src/main/java/com/wss/common/base/adapter/BaseListAdapter.java index 9d079af..77cce29 100644 --- a/common_base/src/main/java/com/wss/common/base/adapter/BaseListAdapter.java +++ b/common_base/src/main/java/com/wss/common/base/adapter/BaseListAdapter.java @@ -1,67 +1,71 @@ package com.wss.common.base.adapter; import android.content.Context; -import android.view.View; -import com.wss.common.listener.OnListItemClickListener; +import com.wss.common.base.adapter.listener.OnListItemClickListener; import org.byteam.superadapter.IMulItemViewType; import org.byteam.superadapter.SuperAdapter; import org.byteam.superadapter.SuperViewHolder; +import org.jetbrains.annotations.NotNull; import java.util.List; /** * Describe:万能适配器基类 适用于RecycleView ListView GridView等 - * 注意点:Item的最外层高度不能设置为 match_parent 否则滑动会出现混乱 目前还不知道原因、 + * 注意点:Item的最外层高度不能设置为 match_parent 否则滑动会出现混乱[TODO] * Created by 吴天强 on 2018/10/30. */ - public abstract class BaseListAdapter extends SuperAdapter { /** * Item点击监听 */ - protected OnListItemClickListener listener; + private OnListItemClickListener listener; /** * 常规列表重写该方法 + * + * @param context context + * @param mData 数据源 + * @param layoutResId 布局文件 + * @param listener Item点击回调 */ - public BaseListAdapter(Context context, List items, int layoutResId, OnListItemClickListener listener) { - super(context, items, layoutResId); + public BaseListAdapter(Context context, List mData, int layoutResId, OnListItemClickListener listener) { + super(context, mData, layoutResId); this.listener = listener; } /** * 多布局列表重写该方法 + * + * @param context context + * @param mData 数据源 + * @param multiItemViewType 多布局类型 */ - public BaseListAdapter(Context context, List items, IMulItemViewType multiItemViewType) { - super(context, items, multiItemViewType); + public BaseListAdapter(Context context, List mData, IMulItemViewType multiItemViewType) { + super(context, mData, multiItemViewType); } /** - * 添加点击事件监听 + * Item点击事件 + * + * @param listener listener */ - public void setOnListItemClickListener(OnListItemClickListener listener) { + public void setOnListItemClickListener(OnListItemClickListener listener) { this.listener = listener; } @Override - public void onBind(final SuperViewHolder viewHolder, int viewType, final int layoutPosition, T data) { - viewHolder.itemView.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - if (listener != null) { - listener.onItemClick((View) viewHolder.itemView.getParent(), layoutPosition); - } + public void onBind(@NotNull final SuperViewHolder viewHolder, int viewType, final int layoutPosition, T data) { + viewHolder.itemView.setOnClickListener(v -> { + if (listener != null) { + listener.onItemClick(data, layoutPosition); } }); onBindData(viewHolder, viewType, layoutPosition, data); } - /** - * 绑定数据 - */ - public abstract void onBindData(SuperViewHolder holder, int viewType, int layoutPosition, T data); + public abstract void onBindData(@NotNull SuperViewHolder holder, int viewType, int layoutPosition, @NotNull T data); } diff --git a/common_base/src/main/java/com/wss/common/base/adapter/listener/OnListItemClickListener.java b/common_base/src/main/java/com/wss/common/base/adapter/listener/OnListItemClickListener.java new file mode 100644 index 0000000..6e5aa16 --- /dev/null +++ b/common_base/src/main/java/com/wss/common/base/adapter/listener/OnListItemClickListener.java @@ -0,0 +1,16 @@ +package com.wss.common.base.adapter.listener; + +/** + * Describe:RecycleView 点击事件监听 + * Created by 吴天强 on 2018/10/18. + */ +public interface OnListItemClickListener { + + /** + * Item点击事件 + * + * @param data Data + * @param position position + */ + void onItemClick(T data, int position); +} diff --git a/common_base/src/main/java/com/wss/common/base/bean/BaseBean.java b/common_base/src/main/java/com/wss/common/base/bean/BaseBean.java index 5336724..2a1f161 100644 --- a/common_base/src/main/java/com/wss/common/base/bean/BaseBean.java +++ b/common_base/src/main/java/com/wss/common/base/bean/BaseBean.java @@ -2,10 +2,11 @@ import java.io.Serializable; + /** * Describe:Bean基类 * Created by 吴天强 on 2018/10/17. */ - public class BaseBean implements Serializable { + } diff --git a/common_base/src/main/java/com/wss/common/base/mvp/BaseModel.java b/common_base/src/main/java/com/wss/common/base/mvp/BaseModel.java new file mode 100644 index 0000000..3ca9b7e --- /dev/null +++ b/common_base/src/main/java/com/wss/common/base/mvp/BaseModel.java @@ -0,0 +1,27 @@ +package com.wss.common.base.mvp; + + +import androidx.lifecycle.LifecycleOwner; + +/** + * Describe:网络请求基类 + * Created by 吴天强 on 2019/7/11. + */ +public class BaseModel { + + private LifecycleOwner lifecycleOwner; + + public BaseModel(LifecycleOwner lifecycleOwner) { + this.lifecycleOwner = lifecycleOwner; + } + + /** + * 返回生命周期所有者 + * + * @return LifecycleOwner + */ + protected LifecycleOwner getLifecycleOwner() { + return lifecycleOwner; + } + +} diff --git a/common_base/src/main/java/com/wss/common/base/mvp/BasePresenter.java b/common_base/src/main/java/com/wss/common/base/mvp/BasePresenter.java index 58f4358..ed3fccc 100644 --- a/common_base/src/main/java/com/wss/common/base/mvp/BasePresenter.java +++ b/common_base/src/main/java/com/wss/common/base/mvp/BasePresenter.java @@ -7,20 +7,23 @@ import java.lang.reflect.Method; import java.lang.reflect.Proxy; +import androidx.lifecycle.LifecycleOwner; + /** * Describe:Presenter基类 * Created by 吴天强 on 2018/10/17. */ - @SuppressWarnings("unchecked") -public abstract class BasePresenter { +public abstract class BasePresenter { private V mProxyView; - private M module; + private M model; private WeakReference weakReference; /** * 绑定View + * + * @param view view */ public void attachView(V view) { weakReference = new WeakReference<>(view); @@ -28,8 +31,8 @@ public void attachView(V view) { view.getClass().getClassLoader(), view.getClass().getInterfaces(), new MvpViewHandler(weakReference.get())); - if (this.module == null) { - this.module = createModule(); + if (this.model == null) { + this.model = createModule(); } } @@ -37,41 +40,70 @@ public void attachView(V view) { * 解绑View */ public void detachView() { - this.module = null; - if (isViewAttached()) { + this.model = null; + if (!isViewDetached()) { weakReference.clear(); weakReference = null; } } /** - * 是否与View建立连接 + * 是否与View断开连接 */ - protected boolean isViewAttached() { - return weakReference != null && weakReference.get() != null; + protected boolean isViewDetached() { + return weakReference == null || weakReference.get() == null; } + /** + * 返回View + * + * @return view + */ protected V getView() { return mProxyView; } - protected M getModule() { - return module; + /** + * 返回Model + * + * @return model + */ + protected M getModel() { + return model; } + /** + * 返回Context + * + * @return context + */ protected Context getContext() { return getView().getContext(); } + /** + * 返回持有View的生命周期所有者 + * + * @return LifecycleOwner + */ + protected LifecycleOwner getLifecycleOwner() { + return getView().getLifecycleOwner(); + } + + /** + * 显示加载框 + */ protected void showLoading() { getView().showLoading(); } + /** + * 隐藏加载框 + */ protected void dismissLoading() { getView().dismissLoading(); } - /** * 通过该方法创建Module */ @@ -97,7 +129,7 @@ private class MvpViewHandler implements InvocationHandler { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //如果V层没被销毁, 执行V层的方法. - if (isViewAttached()) { + if (!isViewDetached()) { return method.invoke(mvpView, args); } //P层不需要关注V层的返回值 return null; diff --git a/common_base/src/main/java/com/wss/common/base/mvp/IBaseModel.java b/common_base/src/main/java/com/wss/common/base/mvp/IBaseModel.java deleted file mode 100644 index e1f07d2..0000000 --- a/common_base/src/main/java/com/wss/common/base/mvp/IBaseModel.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.wss.common.base.mvp; - -/** - * Describe:所有Module的基类 - * Created by 吴天强 on 2018/10/17. - */ - -public interface IBaseModel { - -} diff --git a/common_base/src/main/java/com/wss/common/base/mvp/IBaseView.java b/common_base/src/main/java/com/wss/common/base/mvp/IBaseView.java index 31bd479..5b6f526 100644 --- a/common_base/src/main/java/com/wss/common/base/mvp/IBaseView.java +++ b/common_base/src/main/java/com/wss/common/base/mvp/IBaseView.java @@ -2,11 +2,12 @@ import android.content.Context; +import androidx.lifecycle.LifecycleOwner; + /** * Describe:所有View基类 * Created by 吴天强 on 2018/10/17. */ - public interface IBaseView { /** @@ -40,4 +41,12 @@ public interface IBaseView { * @return context */ Context getContext(); + + /** + * 返回页面生命周期 + * + * @return LifecycleOwner + */ + LifecycleOwner getLifecycleOwner(); + } diff --git a/common_base/src/main/java/com/wss/common/bean/AppInfo.java b/common_base/src/main/java/com/wss/common/bean/AppInfo.java deleted file mode 100644 index 37a7941..0000000 --- a/common_base/src/main/java/com/wss/common/bean/AppInfo.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.wss.common.bean; - -import com.wss.common.base.bean.BaseBean; - -import lombok.Getter; -import lombok.Setter; - -/** - * Describe: - * Created by 吴天强 on 2018/11/20. - */ - -@Getter -@Setter -public class AppInfo extends BaseBean { - - private int id; - private int versionCode; - private String versionName; - private String describe; - private String path; - - @Override - public String toString() { - return "AppInfo{" + - "id=" + id + - ", versionCode=" + versionCode + - ", versionName='" + versionName + '\'' + - ", describe='" + describe + '\'' + - ", path='" + path + '\'' + - '}'; - } -} diff --git a/common_base/src/main/java/com/wss/common/bean/Banner.java b/common_base/src/main/java/com/wss/common/bean/Banner.java new file mode 100644 index 0000000..265a5a0 --- /dev/null +++ b/common_base/src/main/java/com/wss/common/bean/Banner.java @@ -0,0 +1,35 @@ +package com.wss.common.bean; + + +import com.wss.common.base.bean.BaseBean; + +import lombok.Getter; +import lombok.Setter; + +/** + * description: 房源首页Banner实体 + * + * @author 杨伟-tony + * create by 2020/5/21 20:40 + */ +@Getter +@Setter +public class Banner extends BaseBean { + /** + * 图片链接 + */ + private String imageUrl; + /** + * 跳转链接 + */ + private String redirectUrl; + + public Banner(String imageUrl) { + this.imageUrl = imageUrl; + } + + public Banner(String imageUrl, String redirectUrl) { + this.imageUrl = imageUrl; + this.redirectUrl = redirectUrl; + } +} diff --git a/common_base/src/main/java/com/wss/common/bean/Event.java b/common_base/src/main/java/com/wss/common/bean/Event.java index 51f1dcc..554e1cb 100644 --- a/common_base/src/main/java/com/wss/common/bean/Event.java +++ b/common_base/src/main/java/com/wss/common/bean/Event.java @@ -1,22 +1,28 @@ package com.wss.common.bean; + +import com.wss.common.base.bean.BaseBean; + import lombok.Getter; import lombok.Setter; - /** * Describe:EventBus事件类 * Created by 吴天强 on 2018/10/22. */ - @Getter @Setter -public class Event { +public class Event extends BaseBean { + /** + * 事件 + */ private String action; + /** + * 事件附带数据 + */ private T data; - public Event(String action) { this.action = action; } @@ -26,5 +32,4 @@ public Event(String action, T data) { this.data = data; } - } diff --git a/common_base/src/main/java/com/wss/common/bean/HorizontalTabTitle.java b/common_base/src/main/java/com/wss/common/bean/HorizontalTabTitle.java index a002a91..2892986 100644 --- a/common_base/src/main/java/com/wss/common/bean/HorizontalTabTitle.java +++ b/common_base/src/main/java/com/wss/common/bean/HorizontalTabTitle.java @@ -1,18 +1,25 @@ package com.wss.common.bean; + import com.wss.common.base.bean.BaseBean; import lombok.Getter; import lombok.Setter; /** - * Describe:水平选项卡Title + * Describe:水平选项卡标题 * Created by 吴天强 on 2018/10/22. */ @Getter @Setter public class HorizontalTabTitle extends BaseBean { + /** + * 显示标题文字 + */ private String title; + /** + * 标题其他附带数据 + */ private T data; public HorizontalTabTitle(String title) { @@ -22,6 +29,7 @@ public HorizontalTabTitle(String title) { public HorizontalTabTitle(String title, T data) { this.title = title; this.data = data; + } } diff --git a/common_base/src/main/java/com/wss/common/bean/SelectorData.java b/common_base/src/main/java/com/wss/common/bean/SelectorData.java new file mode 100644 index 0000000..85ec54c --- /dev/null +++ b/common_base/src/main/java/com/wss/common/bean/SelectorData.java @@ -0,0 +1,29 @@ +package com.wss.common.bean; + +import com.contrarywind.interfaces.IPickerViewData; +import com.wss.common.base.bean.BaseBean; +import com.wss.common.utils.ValidUtils; + +import lombok.Getter; +import lombok.Setter; + +/** + * Describe:弹窗选择器数据Bean + * Created by 吴天强 on 2020/4/21. + */ +@Getter +@Setter +public class SelectorData extends BaseBean implements IPickerViewData { + private String name; + private T data; + + public SelectorData(String name, T data) { + this.name = name; + this.data = data; + } + + @Override + public String getPickerViewText() { + return ValidUtils.isValid(name) ? name : ""; + } +} diff --git a/common_base/src/main/java/com/wss/common/bean/Template.java b/common_base/src/main/java/com/wss/common/bean/Template.java index 7a25167..ecfaff6 100644 --- a/common_base/src/main/java/com/wss/common/bean/Template.java +++ b/common_base/src/main/java/com/wss/common/bean/Template.java @@ -1,8 +1,7 @@ package com.wss.common.bean; -import android.app.Activity; - import com.wss.common.base.bean.BaseBean; +import com.wss.common.constants.Constants; import java.util.Map; @@ -21,27 +20,36 @@ public class Template extends BaseBean { private int res; private String describe; private Class clazz; - private String url;//模块外跳转链接 - private int type;//0.本模块内Activity跳转 1.业务模块跳转 2.应用外跳转[WebView] - private Map params;//其他附加参数 - - public Template(String title, int res, String url, int type, String describe) { + /** + * 模块外跳转链接 + */ + private String url; + /** + * 页面跳转类型 + */ + private int type; + /** + * 其他附加参数 + */ + private Map params; + + public Template(String title, String url, int type, String describe) { this.title = title; - this.res = res; this.url = url; this.type = type; this.describe = describe; } - public Template(String title, int res, Class clazz) { - this(title, res, clazz, ""); + public Template(String title, Class clazz, String describe) { + this.title = title; + this.clazz = clazz; + this.type = Constants.TemplateType.ACTIVITY; + this.describe = describe; } - public Template(String title, int res, Class clazz, String describe) { + public Template(String title, int res, Class clazz) { this.title = title; this.res = res; this.clazz = clazz; - this.describe = describe; } - } diff --git a/common_base/src/main/java/com/wss/common/bean/User.java b/common_base/src/main/java/com/wss/common/bean/User.java index c5ceaaa..7f058ba 100644 --- a/common_base/src/main/java/com/wss/common/bean/User.java +++ b/common_base/src/main/java/com/wss/common/bean/User.java @@ -6,11 +6,11 @@ import lombok.Setter; /** - * Describe:用户信息 - * Created by 吴天强 on 2018/11/13. + * Describe:置业顾问信息 + * Created by 吴天强 on 2020/5/6. */ -@Setter @Getter +@Setter public class User extends BaseBean { /** @@ -23,7 +23,7 @@ public class User extends BaseBean { * username : 于慢慢家的吴蜀黍 */ - private int id; + private Integer id; private String username; private String email; private String icon; @@ -38,4 +38,5 @@ public User(String username, String password) { this.username = username; this.password = password; } -} + +} \ No newline at end of file diff --git a/common_base/src/main/java/com/wss/common/constants/ARouterConfig.java b/common_base/src/main/java/com/wss/common/constants/ARouterConfig.java index c5ea445..11e1eb7 100644 --- a/common_base/src/main/java/com/wss/common/constants/ARouterConfig.java +++ b/common_base/src/main/java/com/wss/common/constants/ARouterConfig.java @@ -4,7 +4,6 @@ * Describe:路由页面常量配置 注意:路径至少需要两级 {/xx/xx} * Created by 吴天强 on 2018/10/16. */ - public interface ARouterConfig { //************************************Main模块*****************************************/ diff --git a/common_base/src/main/java/com/wss/common/constants/CacheKey.java b/common_base/src/main/java/com/wss/common/constants/CacheKey.java deleted file mode 100644 index 66dca42..0000000 --- a/common_base/src/main/java/com/wss/common/constants/CacheKey.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.wss.common.constants; - -import com.wss.common.base.BaseApplication; - -/** - * Describe:缓存key - * Created by 吴天强 on 2018/11/13. - */ - -public interface CacheKey { - - /** - * 保存用户信息 - */ - String USER_INFO = BaseApplication.getApplication().getPackageName() + ".UserInfo"; - - /** - * 保存登录状态 - */ - String USER_LOGGED = BaseApplication.getApplication().getPackageName() + ".UserLogged"; -} diff --git a/common_base/src/main/java/com/wss/common/constants/Constants.java b/common_base/src/main/java/com/wss/common/constants/Constants.java index 6292a56..96ee255 100644 --- a/common_base/src/main/java/com/wss/common/constants/Constants.java +++ b/common_base/src/main/java/com/wss/common/constants/Constants.java @@ -1,46 +1,158 @@ package com.wss.common.constants; +import android.content.Context; + +import com.wss.common.base.BaseApplication; + /** * Describe:常量存放 * Created by 吴天强 on 2017/10/9. */ +public interface Constants { + /** + * 无法分类的散装常量 + */ + interface Common { + /** + * android + */ + int PLATFORM_ANDROID = 1; + + /** + * 渠道名称 + */ + String CHANEL = "android"; + /** + * API 版本 + */ + String API_VERSION = "1.0"; + } -public class Constants { /** - * 服务器类型 - * SERVER_DEVELOP 开发环境 - * SERVER_TEST 测试环境 - * SERVER_PRODUCTION 生产环境 + * WebView相关配置 */ - public static final int SERVER_TYPE = ServerType.SERVER_DEVELOP; + interface WebView { + String CACHE_DIR = BaseApplication.i().getDir("cache", Context.MODE_PRIVATE).getPath(); + } + /** - * 服务器类型 + * 网络请求相关 */ - public class ServerType { - public static final int SERVER_DEVELOP = 0;//开发环境 - public static final int SERVER_TEST = 1;//测试环境 - public static final int SERVER_PRODUCTION = 2;//生产环境 - } + interface Net { + //response + String STATE = "errorCode"; + String MESSAGE = "errorMsg"; + String DATA = "data"; + //request + String HEADER_CHANNEL = "channel"; + String HEADER_API_VERSION = "apiVersion"; + String HEADER_DEVICE_ID = "deviceid"; + String HEADER_TOKEN = "token"; + String HEADER_APP_VERSION = "appVersion"; + String HEADER_IP = "ip"; + String REQUEST_ID = "requestId"; + /** + * 超时时间 单位:秒 + */ + int TIME_OUT = 30; + + /** + * 接口响应码 + */ + interface Status { + /** + * 处理成功 + */ + String CODE_SUCCESS = "0"; + /** + * 该用户已经被禁用 + */ + String CODE_ACCOUNT_DISABLE = "1111"; + /** + * 该用户已经离职 + */ + String CODE_ACCOUNT_QUIT = "1112"; + /** + * 账号被锁定 + */ + String CODE_ACCOUNT_LOCKED = "1113"; + /** + * 此账户没有操作权限 + */ + String CODE_ACCOUNT_NO_AUTHORITY = "1114"; + /** + * 此账户没有归属团队 + */ + String CODE_ACCOUNT_NO_TEAM = "1118"; + /** + * 此账户同一项目归属多个团队 + */ + String CODE_ACCOUNT_MULTIPLE_TEAM = "1119"; + /** + * Token过期 + */ + String CODE_TOKEN_EXPIRED = "1120"; + /** + * 该用户的岗位信息有误 + */ + String CODE_ACCOUNT_POSITION_ERROR = "1128"; + + /** + * 参数异常 + */ + String INVALID_PARAMETER_ERROR = "403"; + } + } /** - * 模块类型 + * 选择文件的文件类型 */ - public static final int MODULE_TYPE_SHUTTLE = 0; - public static final int MODULE_TYPE_CHART = 1; - public static final int MODULE_TYPE_DEALS = 2; + interface FileType { + /** + * 图片 + */ + int IMAGE = 0; + /** + * 视频 + */ + int VIDEO = 1; + /** + * 音频 + */ + int AUDIO = 2; + /** + * 文档 + */ + int DOC = 3; + /** + * 压缩包 + */ + int PACKAGE = 4; + /** + * 其他 + */ + int OTHER = 5; + } + /** + * 数据库配置 + */ + interface DBConfig { + String DB_NAME = "AMD.db"; + } /** - * 默认日期格式 + * 页面跳转类型 */ - public static final String DATE_FORMAT_SLASH = "yyyy/MM/dd"; - public static final String DATE_FORMAT_LINE = "yyyy-MM-dd"; - public static final String DATE_FORMAT_DEFAULT = DATE_FORMAT_SLASH + " HH:mm:ss"; + interface TemplateType { - public static final String ERROR_MESSAGE = "网络连接失败"; - public static final int SUCCESS_CODE = 0; + int ACTIVITY = 0; + int AROUTER = 1; + int WEB_VIEW = 2; + int SYS_BROWSER = 3; + } } diff --git a/common_base/src/main/java/com/wss/common/constants/DBConfig.java b/common_base/src/main/java/com/wss/common/constants/DBConfig.java deleted file mode 100644 index 6a94bef..0000000 --- a/common_base/src/main/java/com/wss/common/constants/DBConfig.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.wss.common.constants; - -import com.wss.common.base.BaseApplication; -import com.wss.common.base.R; - -/** - * Describe:数据库配置文件 - * Created by 吴天强 on 2018/11/5. - */ - -public interface DBConfig { - String DB_NAME = BaseApplication.getApplication().getString(R.string.app_name) + ".db"; -} diff --git a/common_base/src/main/java/com/wss/common/constants/Dic.java b/common_base/src/main/java/com/wss/common/constants/Dic.java new file mode 100644 index 0000000..32b480f --- /dev/null +++ b/common_base/src/main/java/com/wss/common/constants/Dic.java @@ -0,0 +1,76 @@ +package com.wss.common.constants; + +/** + * Describe:字典 存放Activity跳转传参key、缓存数据到SP中key等。 + * Created by 吴天强 on 2018/11/13. + */ +public interface Dic { + + /** + * 跳转画廊参数-图片集合 + */ + String IMAGE_LIST = "image_list"; + /** + * 跳转画廊参数-图片起始位置 + */ + String IMAGE_POSITION = "image_position"; + /** + * 跳转画廊参数-是否本地图片 + */ + String IMAGE_LOCAL = "image_local"; + /** + * 跳转画廊参数-是否全屏显示 + */ + String FULL_SCREEN = "full_screen"; + + /** + * 通过路由跳转的Fragment的路径 + */ + String TARGET_FRAGMENT_PATH = "target_fragment_path"; + + /** + * 进入类型 + */ + String FROM_TYPE = "from_type"; + + /** + * 链接 + */ + String URL = "url"; + + /** + * 需要actionBar + */ + String IS_ACTION_BAR = "is_action_bar"; + /** + * actionBar 文字 + */ + String TITLE_TEXT = "title_text"; + /** + * bundle带入的数据 + */ + String BUNDLE_DATA = "bundle_data"; + + /** + * 可选文件的最大值 + */ + String MAX_SELECT_FILE = "max_select_file"; + /** + * 选择的文件路径列表 + */ + String SELECT_FILE_PATHS = "select_file_paths"; + /** + * 商品信息 + */ + String GOODS_INFO = "goods_info"; + /** + * 登录用户 + */ + String LOGIN_USER_INFO = "login_user_info"; + /** + * 系列子类 + */ + String CLASSIFICATION_CHILD = "classification_child"; + + +} diff --git a/common_base/src/main/java/com/wss/common/constants/EventAction.java b/common_base/src/main/java/com/wss/common/constants/EventAction.java index b6c2fe9..267af44 100644 --- a/common_base/src/main/java/com/wss/common/constants/EventAction.java +++ b/common_base/src/main/java/com/wss/common/constants/EventAction.java @@ -4,9 +4,19 @@ * Describe:EventBus事件 * Created by 吴天强 on 2018/10/19. */ - public interface EventAction { + //************************************Common模块****************************************/ + /** + * 删除画廊的图片, Action Data = 删除图片的position + */ + String IMAGE_GALLERY_DELETE = "image_gallery_delete"; + /** + * 二维码扫描结果 Action Data = String + */ + String SCAN_QR_CODE_RESULT = "scan_qr_code_result"; + + //************************************Market模块*****************************************/ /** @@ -22,10 +32,10 @@ public interface EventAction { /** * 登录成功 */ - String EVENT_LOGIN_SUCCESS = "EVENT_LOGIN_SUCCESS"; + String EVENT_LOGIN_SUCCESS = "event_login_success"; /** * 注册成功 */ - String EVENT_REGISTER_SUCCESS = "EVENT_REGISTER_SUCCESS"; + String EVENT_REGISTER_SUCCESS = "event_register_success"; } diff --git a/common_base/src/main/java/com/wss/common/dao/BaseDBManager.java b/common_base/src/main/java/com/wss/common/dao/BaseDBManager.java index fc50a9a..5dfc8cb 100644 --- a/common_base/src/main/java/com/wss/common/dao/BaseDBManager.java +++ b/common_base/src/main/java/com/wss/common/dao/BaseDBManager.java @@ -9,7 +9,6 @@ * Describe:所有的数据库操作类都继承自此 * Created by 吴天强 on 2018/11/5. */ - public class BaseDBManager { private AbstractDao mDao; diff --git a/common_base/src/main/java/com/wss/common/dao/DBMigrationHelper.java b/common_base/src/main/java/com/wss/common/dao/DBMigrationHelper.java index 1fa0ed0..b46cac6 100644 --- a/common_base/src/main/java/com/wss/common/dao/DBMigrationHelper.java +++ b/common_base/src/main/java/com/wss/common/dao/DBMigrationHelper.java @@ -2,20 +2,21 @@ import android.database.Cursor; +import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; -import android.support.annotation.NonNull; import android.text.TextUtils; -import android.util.Log; + +import com.orhanobut.logger.Logger; import org.greenrobot.greendao.AbstractDao; import org.greenrobot.greendao.database.Database; import org.greenrobot.greendao.database.StandardDatabase; import org.greenrobot.greendao.internal.DaoConfig; +import org.jetbrains.annotations.Contract; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; +import java.util.Date; import java.util.List; @@ -24,167 +25,216 @@ * Created by 吴天强 on 2018/11/5. */ public class DBMigrationHelper { - private static final String CONVERSION_CLASS_NOT_FOUND_EXCEPTION = "MIGRATION HELPER - CLASS DOESN'IDatabase MATCH WITH THE CURRENT PARAMETERS"; - public void onUpgrade(SQLiteDatabase db, Class>... daoClasses) { + private static final String SQLITE_MASTER = "sqlite_master"; + private static final String SQLITE_TEMP_MASTER = "sqlite_temp_master"; + + static void migrate(SQLiteDatabase db, Class>... daoClasses) { + Logger.e("【The Old Database Version】" + db.getVersion()); Database database = new StandardDatabase(db); - generateTempTables(database, daoClasses); //备份数据(表结构改变的表) - dropAllTables(database, true, daoClasses); //删除旧表(结构修改/新增) - createAllTables(database, false, daoClasses); //创建 新表(结构修改/新增) - restoreData(database, daoClasses); //恢复数据(结构修改) + migrate(database, daoClasses); } - private void dropAllTables(Database db, boolean b, Class>... daoClasses) { - if (daoClasses != null) { - reflectMethod(db, "dropTable", b, daoClasses); + + @SafeVarargs + static void migrate(Database database, Class>... daoClasses) { + Logger.e("【Generate temp table】start"); + generateTempTables(database, daoClasses); + Logger.e("【Generate temp table】complete"); + + Logger.e("【Drop all table and recreate all table】"); + for (Class> daoClass : daoClasses) { + DaoConfig daoConfig = new DaoConfig(database, daoClass); + dropTable(database, true, daoConfig); + createTable(database, false, daoConfig); } + + Logger.e("【Restore data】start"); + restoreData(database, daoClasses); + Logger.e("【Restore data】complete"); } - private void createAllTables(Database db, boolean b, Class>... daoClasses) { - if (daoClasses != null) { - reflectMethod(db, "createTable", b, daoClasses); + private static void dropTable(Database database, boolean ifExists, DaoConfig daoConfig) { + String sql = String.format("DROP TABLE %s\"%s\"", ifExists ? "IF EXISTS " : "", daoConfig.tablename); + database.execSQL(sql); + } + + @SafeVarargs + private static void generateTempTables(Database db, Class>... daoClasses) { + for (Class> daoClass : daoClasses) { + String tempTableName = null; + + DaoConfig daoConfig = new DaoConfig(db, daoClass); + String tableName = daoConfig.tablename; + if (!isTableExists(db, false, tableName)) { + Logger.e("【New Table】" + tableName); + continue; + } + try { + tempTableName = daoConfig.tablename.concat("_TEMP"); + StringBuilder dropTableStringBuilder = new StringBuilder(); + dropTableStringBuilder.append("DROP TABLE IF EXISTS ").append(tempTableName).append(";"); + Logger.e("【Generate temp table】 dropTableStringBuilder:" + dropTableStringBuilder); + db.execSQL(dropTableStringBuilder.toString()); + + StringBuilder insertTableStringBuilder = new StringBuilder(); + insertTableStringBuilder.append("CREATE TEMPORARY TABLE ").append(tempTableName); + insertTableStringBuilder.append(" AS SELECT * FROM ").append(tableName).append(";"); + Logger.e("【Generate temp table】 insertTableStringBuilder:" + insertTableStringBuilder); + db.execSQL(insertTableStringBuilder.toString()); + Logger.e("【Table】" + tableName + "\n ---Columns-->" + getColumnsStr(daoConfig)); + Logger.e("【Generate temp table】" + tempTableName); + } catch (SQLException e) { + Logger.e("【Failed to generate temp table】" + tempTableName, e); + } } } - /** - * 反射出方法执行 - */ - private static void reflectMethod(Database db, String methodName, boolean isExists, @NonNull Class>... daoClasses) { - if (daoClasses.length < 1) { - return; + @Contract("null, _, _ -> false") + private static boolean isTableExists(Database db, boolean isTemp, String tableName) { + if (db == null || TextUtils.isEmpty(tableName)) { + return false; } + String dbName = isTemp ? SQLITE_TEMP_MASTER : SQLITE_MASTER; + String sql = "SELECT COUNT(*) FROM " + dbName + " WHERE type = ? AND name = ?"; + Cursor cursor = null; + int count = 0; try { - for (Class cls : daoClasses) { - // Method method = cls.getDeclaredMethod(methodName, cls); - Method method = cls.getDeclaredMethod(methodName, Database.class, boolean.class);//update by wragony on 2017-06-27 - method.invoke(null, db, isExists); + cursor = db.rawQuery(sql, new String[]{"table", tableName}); + if (cursor == null || !cursor.moveToFirst()) { + return false; } - } catch (NoSuchMethodException e) { - e.printStackTrace(); - } catch (InvocationTargetException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { + count = cursor.getInt(0); + } catch (Exception e) { e.printStackTrace(); + } finally { + if (cursor != null) { + cursor.close(); + } } + return count > 0; } - /** - * 备份数据 - * - * @param db - * @param daoClasses(表结构改变的表) - */ - private void generateTempTables(Database db, Class>... daoClasses) { - for (int i = 0; i < daoClasses.length; i++) { - DaoConfig daoConfig = new DaoConfig(db, daoClasses[i]); - String divider = ""; - String tableName = daoConfig.tablename; - String tempTableName = daoConfig.tablename.concat("_TEMP"); - ArrayList properties = new ArrayList<>(); - StringBuilder createTableStringBuilder = new StringBuilder(); - createTableStringBuilder.append("CREATE TABLE ").append(tempTableName).append(" ("); - - for (int j = 0; j < daoConfig.properties.length; j++) { - String columnName = daoConfig.properties[j].columnName; - if (getColumns(db, tableName).contains(columnName)) { - properties.add(columnName); - String type = null; - try { - type = getTypeByClass(daoConfig.properties[j].type); - } catch (Exception exception) { -// Crashlytics.logException(exception); - } - createTableStringBuilder.append(divider).append(columnName).append(" ").append(type); - if (daoConfig.properties[j].primaryKey) { - createTableStringBuilder.append(" PRIMARY KEY"); - } - divider = ","; - } - } - createTableStringBuilder.append(");"); - db.execSQL(createTableStringBuilder.toString()); - StringBuilder insertTableStringBuilder = new StringBuilder(); - insertTableStringBuilder.append("INSERT INTO ").append(tempTableName).append(" ("); - insertTableStringBuilder.append(TextUtils.join(",", properties)); - insertTableStringBuilder.append(") SELECT "); - insertTableStringBuilder.append(TextUtils.join(",", properties)); - insertTableStringBuilder.append(" FROM ").append(tableName).append(";"); - db.execSQL(insertTableStringBuilder.toString()); + + private static String getColumnsStr(DaoConfig daoConfig) { + if (daoConfig == null) { + return "no columns"; + } + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < daoConfig.allColumns.length; i++) { + builder.append(daoConfig.allColumns[i]); + builder.append(","); } + if (builder.length() > 0) { + builder.deleteCharAt(builder.length() - 1); + } + return builder.toString(); } - /** - * 恢复数据 - * - * @param db - * @param daoClasses(结构修改的表) - */ - private void restoreData(Database db, Class>... daoClasses) { - for (int i = 0; i < daoClasses.length; i++) { - DaoConfig daoConfig = new DaoConfig(db, daoClasses[i]); + @SafeVarargs + private static void restoreData(Database db, Class>... daoClasses) { + for (Class> daoClass : daoClasses) { + DaoConfig daoConfig = new DaoConfig(db, daoClass); String tableName = daoConfig.tablename; String tempTableName = daoConfig.tablename.concat("_TEMP"); - ArrayList properties = new ArrayList(); - - for (int j = 0; j < daoConfig.properties.length; j++) { - String columnName = daoConfig.properties[j].columnName; - - if (getColumns(db, tempTableName).contains(columnName)) { - properties.add(columnName); + isTableExists(db, true, tempTableName); + try { + // get all columns from tempTable, take careful to use the columns list + List columns = getColumns(db, tempTableName); + ArrayList properties = new ArrayList<>(columns.size()); + for (int j = 0; j < daoConfig.properties.length; j++) { + String columnName = daoConfig.properties[j].columnName; + if (columns.contains(columnName)) { + properties.add(columnName); + } } + if (properties.size() > 0) { + final String columnSQL = TextUtils.join(",", properties); + + StringBuilder insertTableStringBuilder = new StringBuilder(); + insertTableStringBuilder.append("INSERT INTO ").append(tableName).append(" ("); + insertTableStringBuilder.append(columnSQL); + insertTableStringBuilder.append(") SELECT "); + insertTableStringBuilder.append(columnSQL); + insertTableStringBuilder.append(" FROM ").append(tempTableName).append(";"); + Logger.e("【Restore data】 db sql: " + insertTableStringBuilder); + db.execSQL(insertTableStringBuilder.toString()); + Logger.e("【Restore data】 to " + tableName); + } + StringBuilder dropTableStringBuilder = new StringBuilder(); + dropTableStringBuilder.append("DROP TABLE ").append(tempTableName); + db.execSQL(dropTableStringBuilder.toString()); + Logger.e("【Drop temp table】" + tempTableName); + } catch (SQLException e) { + Logger.e("【Failed to restore data from temp table 】" + tempTableName, e); } - - StringBuilder insertTableStringBuilder = new StringBuilder(); - - insertTableStringBuilder.append("INSERT INTO ").append(tableName).append(" ("); - insertTableStringBuilder.append(TextUtils.join(",", properties)); - insertTableStringBuilder.append(") SELECT "); - insertTableStringBuilder.append(TextUtils.join(",", properties)); - insertTableStringBuilder.append(" FROM ").append(tempTableName).append(";"); - - StringBuilder dropTableStringBuilder = new StringBuilder(); - - //dropTableStringBuilder.append("DROP TABLE ").append(tempTableName); - dropTableStringBuilder.append("DROP TABLE IF EXISTS ").append(tempTableName).append(";");// update by wragony on 2017-06-27 - - db.execSQL(insertTableStringBuilder.toString()); - db.execSQL(dropTableStringBuilder.toString()); - } - } - - private String getTypeByClass(Class type) throws Exception { - if (type.equals(String.class)) { - return "TEXT"; - } - if (type.equals(Long.class) || type.equals(Integer.class) || type.equals(long.class)) { - return "INTEGER"; } - if (type.equals(Boolean.class)) { - return "BOOLEAN"; - } - - Exception exception = new Exception(CONVERSION_CLASS_NOT_FOUND_EXCEPTION.concat(" - Class: ").concat(type.toString())); -// Crashlytics.logException(exception); - throw exception; } private static List getColumns(Database db, String tableName) { - List columns = new ArrayList<>(); - Cursor cursor = null; - try { - cursor = db.rawQuery("SELECT * FROM " + tableName + " limit 1", null); - if (cursor != null) { - columns = new ArrayList<>(Arrays.asList(cursor.getColumnNames())); + List columns = null; + try (Cursor cursor = db.rawQuery("SELECT * FROM " + tableName + " limit 0", null)) { + if (null != cursor && cursor.getColumnCount() > 0) { + columns = Arrays.asList(cursor.getColumnNames()); } } catch (Exception e) { - Log.v(tableName, e.getMessage(), e); e.printStackTrace(); } finally { - if (cursor != null) - cursor.close(); + if (null == columns) { + columns = new ArrayList<>(); + } } return columns; } + private static void createTable(Database db, boolean ifNotExists, DaoConfig daoConfig) { + String tableName = daoConfig.tablename; + StringBuilder builder = new StringBuilder(); + builder.append("CREATE TABLE "); + builder.append(ifNotExists ? "IF NOT EXISTS " : ""); + builder.append(tableName); + builder.append(getColumnsSql(daoConfig)); + Logger.e("【createTable】 sql:" + builder.toString()); + db.execSQL(builder.toString()); // 6: Description + } + + private static String getColumnsSql(DaoConfig daoConfig) { + if (daoConfig == null) { + return ""; + } + StringBuilder builder = new StringBuilder(" ("); + for (int i = 0; i < daoConfig.properties.length; i++) { + builder.append(String.format("\"%s\" %s,", daoConfig.properties[i].columnName, + getPropertyType(daoConfig.properties[i].type))); + } + if (daoConfig.properties.length > 0 && builder.length() > 0) { + builder.deleteCharAt(builder.length() - 1); + } + builder.append("); "); + return builder.toString(); + } + + /** + * 根据字段类型返回对应的数据库字段语句 + * + * @param type + * @return + */ + private static String getPropertyType(Class type) { + if (type.equals(byte[].class)) { + return "BLOB"; + } else if (type.equals(String.class)) { + return "TEXT DEFAULT ''"; + } else if (type.equals(boolean.class) || type.equals(Boolean.class) + || type.equals(int.class) || type.equals(Integer.class) + || type.equals(long.class) || type.equals(Long.class) + || type.equals(Date.class) || type.equals(Byte.class)) { + return "INTEGER DEFAULT (0)"; + } else if (type.equals(float.class) || type.equals(Float.class) + || type.equals(double.class) || type.equals(Double.class)) { + return "REAL DEFAULT (0)"; + } + return "TEXT DEFAULT ''"; + } } diff --git a/common_base/src/main/java/com/wss/common/exception/NetErrorException.java b/common_base/src/main/java/com/wss/common/exception/NetErrorException.java new file mode 100644 index 0000000..deb20d6 --- /dev/null +++ b/common_base/src/main/java/com/wss/common/exception/NetErrorException.java @@ -0,0 +1,53 @@ +package com.wss.common.exception; + +/** + * Describe:网络请求异常类 + * Created by 吴天强 on 2019/6/15. + */ +public class NetErrorException extends Exception { + + /** + * 网络请求错误码 + */ + private String errorCode; + /** + * 响应的Data + */ + private String responseData; + + public NetErrorException() { + } + + public NetErrorException(String message) { + this("", message); + } + + public NetErrorException(String errorCode, String message) { + this(errorCode, message, ""); + + } + + public NetErrorException(String errorCode, String message, String responseData) { + super(message); + this.errorCode = errorCode; + this.responseData = responseData; + } + + /** + * 返回网络请求错误码 + * + * @return errorCode + */ + public String getNetErrorCode() { + return errorCode; + } + + /** + * 返回网路响应的DATA + * + * @return responseData + */ + public String getNetResponseData() { + return responseData; + } +} diff --git a/common_base/src/main/java/com/wss/common/listener/OnListItemClickListener.java b/common_base/src/main/java/com/wss/common/listener/OnListItemClickListener.java deleted file mode 100644 index 00db6e5..0000000 --- a/common_base/src/main/java/com/wss/common/listener/OnListItemClickListener.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.wss.common.listener; - -import android.view.View; - -/** - * Describe:RecycleView 点击事件监听 - * Created by 吴天强 on 2018/10/18. - */ - -public interface OnListItemClickListener { - - void onItemClick(View view, int position); -} diff --git a/common_base/src/main/java/com/wss/common/manage/ActivityManage.java b/common_base/src/main/java/com/wss/common/manage/ActivityManage.java index 80b29d0..992ab1d 100644 --- a/common_base/src/main/java/com/wss/common/manage/ActivityManage.java +++ b/common_base/src/main/java/com/wss/common/manage/ActivityManage.java @@ -9,10 +9,11 @@ * Describe:管理所有的Activity * Created by 吴天强 on 2018/10/15. */ - public class ActivityManage { - //保存所有创建的Activity + /** + * 保存所有创建的Activity + */ private Set allActivities = new HashSet<>(); /** @@ -45,7 +46,5 @@ public void finishAll() { for (Activity activity : allActivities) { activity.finish(); } - } - } diff --git a/common_base/src/main/java/com/wss/common/manage/ActivityToActivity.java b/common_base/src/main/java/com/wss/common/manage/ActivityToActivity.java new file mode 100644 index 0000000..1b5bbb7 --- /dev/null +++ b/common_base/src/main/java/com/wss/common/manage/ActivityToActivity.java @@ -0,0 +1,304 @@ +package com.wss.common.manage; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.text.TextUtils; + +import com.alibaba.android.arouter.core.LogisticsCenter; +import com.alibaba.android.arouter.facade.Postcard; +import com.alibaba.android.arouter.launcher.ARouter; +import com.wss.common.base.R; +import com.wss.common.base.bean.BaseBean; +import com.wss.common.bean.Template; +import com.wss.common.constants.Constants; +import com.wss.common.constants.Dic; +import com.wss.common.utils.NetworkUtil; +import com.wss.common.utils.ToastUtils; +import com.wss.common.utils.Utils; +import com.wss.common.view.browser.BrowserActivity; + +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +import androidx.core.app.ActivityOptionsCompat; +import androidx.fragment.app.Fragment; + +/** + * Describe:Activity跳转 + * Created by 吴天强 on 2018/10/22. + */ +public class ActivityToActivity { + + + ////////////////////////////////////////普通Activity跳转//////////////////////////////////////// + + /** + * 普通Activity之间跳转 + * + * @param activity activity + * @param clazz 目标activity + */ + public static void toActivity(Context activity, Class clazz) { + toActivityForResult(activity, clazz, null, 0); + } + + /** + * 普通Activity之间跳转 + * + * @param activity activity + * @param clazz 目标activity + * @param params 携带参数 + */ + public static void toActivity(Context activity, Class clazz, Map params) { + toActivityForResult(activity, clazz, params, 0); + } + + /** + * 普通Activity之间跳转 + * + * @param activity activity + * @param clazz 目标activity + * @param requestCode 请求码 需大于0 + */ + public static void toActivityForResult(Context activity, Class clazz, int requestCode) { + toActivityForResult(activity, clazz, null, requestCode); + } + + /** + * 普通Activity之间跳转 + * ps:兼容从Fragment中使用ActivityForResult。传统方式Fragment中的onActivityResult中无法收到回调 + * + * @param fragment 当前fragment + * @param activity activity + * @param clazz 目标activity + * @param requestCode 请求码 需大于0 + */ + public static void toActivityForResult(Fragment fragment, Context activity, Class clazz, int requestCode) { + toActivityForResult(fragment, activity, clazz, null, requestCode); + } + + /** + * 普通Activity之间跳转 + * + * @param activity activity + * @param clazz 目标activity + * @param params 参数 + * @param requestCode 请求码 需大于0 + */ + public static void toActivityForResult(Context activity, Class clazz, Map params, int requestCode) { + Intent intent = new Intent(); + intent.setClass(activity, clazz); + assembleParams(intent, params); + if (requestCode > 0) { + ((Activity) activity).startActivityForResult(intent, requestCode); + } else { + activity.startActivity(intent); + } + } + + /** + * 在Fragment中调用startActivityForResult + * + * @param fragment 跳转所在的Fragment + * @param activity activity + * @param clazz 目标activity + * @param params 参数 + * @param requestCode 请求码 需大于0 + */ + public static void toActivityForResult(@NotNull Fragment fragment, Context activity, Class clazz, Map params, int requestCode) { + Intent intent = new Intent(); + intent.setClass(activity, clazz); + assembleParams(intent, params); + fragment.startActivityForResult(intent, requestCode); + } + + private static void assembleParams(Intent intent, Map params) { + if (params != null) { + for (Map.Entry entry : params.entrySet()) { + String key = entry.getKey(); + Object value = params.get(key); + if (value instanceof String) { + intent.putExtra(key, (String) value); + } else if (value instanceof Boolean) { + intent.putExtra(key, (boolean) value); + } else if (value instanceof Integer) { + intent.putExtra(key, (int) value); + } else if (value instanceof Float) { + intent.putExtra(key, (float) value); + } else if (value instanceof Double) { + intent.putExtra(key, (double) value); + } else if (value instanceof Long) { + intent.putExtra(key, (long) value); + } else if (value instanceof Short) { + intent.putExtra(key, (short) value); + } else if (value instanceof Bundle) { + intent.putExtra(key, (Bundle) value); + } else if (value instanceof BaseBean) { + intent.putExtra(key, (BaseBean) value); + } else if (value instanceof ArrayList) { + intent.putExtra(key, (ArrayList) value); + } else if (value instanceof HashMap) { + intent.putExtra(key, (HashMap) value); + } + } + } + } + //////////////////////////////////////WebView跳转////////////////////////////////////// + + /** + * 跳转WebView url 不可为空 + * + * @param context context + * @param url 链接 + * @param title 标题 + */ + public static void toWebView(Context context, String url, String title) { + if (!NetworkUtil.isLink(url)) { + return; + } + Map param = new HashMap<>(); + param.put(Dic.URL, url); + param.put(Dic.TITLE_TEXT, title); + toActivity(context, BrowserActivity.class, param); + } + + /** + * 跳转WebView url 不可为空 + * + * @param context 链接 + * @param url 标题 + */ + public static void toWebView(Context context, String url) { + toWebView(context, url, ""); + } + + //////////////////////////////////////ARouter跳转////////////////////////////////////// + + /** + * ARouter跳转Activity + * + * @param activity Activity + * @param url 目标Activity Url + */ + public static void toActivity(Activity activity, String url) { + toActivityForResult(activity, url, null, 0); + } + + /** + * ARouter跳转Activity + * + * @param activity Activity + * @param url 目标Activity Url + */ + public static void toActivity(Activity activity, String url, Map params) { + toActivityForResult(activity, url, params, 0); + } + + /** + * ARouter跳转Activity + * + * @param activity Activity + * @param url 目标Activity Url + * @param requestCode 请求码 需大于0 + */ + public static void toActivityForResult(Activity activity, String url, int requestCode) { + toActivityForResult(activity, url, null, requestCode); + } + + /** + * ARouter跳转Activity + * + * @param activity Activity + * @param url 目标Activity Url + * @param params 参数 + * @param requestCode 请求码 需大于0 + */ + public static void toActivityForResult(Activity activity, String url, Map params, int requestCode) { + if (TextUtils.isEmpty(url)) { + return; + } + Postcard postcard = ARouter.getInstance() + .build(url) + .withOptionsCompat(ActivityOptionsCompat.makeCustomAnimation(activity, R.anim.anim_right_in, R.anim.anim_right_out)); + if (params != null) { + for (Map.Entry entry : params.entrySet()) { + String key = entry.getKey(); + Object value = params.get(key); + if (value instanceof String) { + postcard.withString(key, (String) value); + } else if (value instanceof Boolean) { + postcard.withBoolean(key, (boolean) value); + } else if (value instanceof Integer) { + postcard.withInt(key, (int) value); + } else if (value instanceof Float) { + postcard.withFloat(key, (float) value); + } else if (value instanceof Double) { + postcard.withDouble(key, (double) value); + } else if (value instanceof Long) { + postcard.withLong(key, (long) value); + } else if (value instanceof Short) { + postcard.withShort(key, (short) value); + } else if (value instanceof Bundle) { + postcard.withBundle(key, (Bundle) value); + } else if (value instanceof BaseBean) { + postcard.withSerializable(key, (BaseBean) value); + } else if (value instanceof ArrayList) { + postcard.withSerializable(key, (ArrayList) value); + } else if (value instanceof HashMap) { + postcard.withSerializable(key, (HashMap) value); + } + } + } + if (requestCode > 0) { + LogisticsCenter.completion(postcard); + activity.startActivityForResult(new Intent(activity, postcard.getDestination()), requestCode); + } else { + postcard.navigation(); + } + } + + + /** + * 通过模板跳转Activity + * + * @param activity activity + * @param template 模板信息 + */ + @SuppressWarnings("unchecked") + public static void toActivity(Activity activity, Template template) { + switch (template.getType()) { + case Constants.TemplateType.ACTIVITY: + //跳转Activity + toActivity(activity, template.getClazz(), template.getParams()); + break; + case Constants.TemplateType.AROUTER: + //跳转Arouter + toActivity(activity, template.getUrl(), template.getParams()); + break; + case Constants.TemplateType.WEB_VIEW: + //跳转WebView + toWebView(activity, template.getUrl()); + break; + case Constants.TemplateType.SYS_BROWSER: + //跳转手机浏览器 + Utils.toSystemBrowser(activity, template.getUrl()); + break; + default: + + } + } + + /** + * 跳转登录页 + * + * @param context ctx + */ + public static void toLoginActivity(Context context) { + ToastUtils.show("跳转登录页"); + } +} \ No newline at end of file diff --git a/common_base/src/main/java/com/wss/common/manage/BlurTransformation.java b/common_base/src/main/java/com/wss/common/manage/BlurTransformation.java index 6005e9b..027edee 100644 --- a/common_base/src/main/java/com/wss/common/manage/BlurTransformation.java +++ b/common_base/src/main/java/com/wss/common/manage/BlurTransformation.java @@ -8,21 +8,24 @@ import android.renderscript.Element; import android.renderscript.RenderScript; import android.renderscript.ScriptIntrinsicBlur; -import android.support.annotation.NonNull; import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool; import com.bumptech.glide.load.resource.bitmap.BitmapTransformation; import java.security.MessageDigest; +import androidx.annotation.NonNull; + /** - * Describe:glide 加载图片转换器之模糊转换器 + * Describe:加载图片转换器之模糊转换器 * Created by 吴天强 on 2018/11/8. */ - public class BlurTransformation extends BitmapTransformation { private Context context; - private int blurRadius = 20;//模糊度 0=< blurRadius >=25 + /** + * 模糊度 0=< blurRadius<=25 + */ + private float blurRadius = 15; public BlurTransformation(Context context) { this.context = context; @@ -32,7 +35,7 @@ public BlurTransformation(Context context) { * @param context context * @param blurRadius 模糊度 最大25 */ - public BlurTransformation(Context context, int blurRadius) { + public BlurTransformation(Context context, float blurRadius) { this.context = context; this.blurRadius = blurRadius; } @@ -69,13 +72,11 @@ private Bitmap blurBitmap(Context context, Bitmap image, int outWidth, int outHe Allocation tmpIn = Allocation.createFromBitmap(rs, inputBitmap); Allocation tmpOut = Allocation.createFromBitmap(rs, outputBitmap); // 设置渲染的模糊程度, 25f是最大模糊度 - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { - //模糊度最大到25 - if (blurRadius < 0 || blurRadius > 25) { - blurRadius = 20; - } - blurScript.setRadius(blurRadius); + //模糊度最大到25 + if (blurRadius < 0 || blurRadius > 25) { + blurRadius = 20; } + blurScript.setRadius(blurRadius); // 设置blurScript对象的输入内存 blurScript.setInput(tmpIn); // 将输出数据保存到输出内存中 diff --git a/common_base/src/main/java/com/wss/common/manage/CrashHandlerManage.java b/common_base/src/main/java/com/wss/common/manage/CrashHandlerManage.java deleted file mode 100644 index 164b98b..0000000 --- a/common_base/src/main/java/com/wss/common/manage/CrashHandlerManage.java +++ /dev/null @@ -1,188 +0,0 @@ -package com.wss.common.manage; - -import android.annotation.SuppressLint; -import android.content.Context; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; -import android.os.Build; -import android.os.Environment; -import android.support.annotation.Nullable; - -import com.orhanobut.logger.Logger; -import com.wss.common.base.BaseApplication; -import com.wss.common.utils.DateUtils; -import com.wss.common.utils.FileUtils; -import com.wss.common.utils.ZipUtils; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.io.Writer; -import java.lang.Thread.UncaughtExceptionHandler; -import java.lang.reflect.Field; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.Map; - - -/** - * UncaughtException处理类,当程序发生Uncaught异常的时候,由该类来接管程序,并记录发送错误报告. - * Created by wtq on 2016/7/22. - */ -@SuppressLint("StaticFieldLeak") -public class CrashHandlerManage implements UncaughtExceptionHandler { - private static final String TAG = "CrashHandlerManage"; - private UncaughtExceptionHandler mDefaultHandler;// 系统默认的UncaughtException处理类 - private static CrashHandlerManage INSTANCE; - private Context mContext;// 程序的Context对象 - private Map info = new HashMap<>();// 用来存储设备信息和异常信息 - - /** - * 保证只有一个CrashHandler实例 - */ - private CrashHandlerManage() { - } - - public synchronized static CrashHandlerManage getInstance() { - if (INSTANCE == null) { - INSTANCE = new CrashHandlerManage(); - } - return INSTANCE; - } - - - /** - * 初始化 - */ - public void init(Context context) { - mContext = context; - mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();// 获取系统默认的UncaughtException处理器 - Thread.setDefaultUncaughtExceptionHandler(this);// 设置该CrashHandler为程序的默认处理器 - } - - /** - * 当UncaughtException发生时会转入该重写的方法来处理 - */ - public void uncaughtException(Thread thread, Throwable ex) { - if (!handleException(ex) && mDefaultHandler != null) { - // 如果自定义的没有处理则让系统默认的异常处理器来处理 - mDefaultHandler.uncaughtException(thread, ex); - } else { - try { - Thread.sleep(3000);// 如果处理了,让程序继续运行3秒再退出,保证文件保存并上传到服务器 - } catch (InterruptedException e) { - e.printStackTrace(); - } - ((BaseApplication) mContext.getApplicationContext()).exitApp(); - // 退出程序 - } - } - - - /** - * 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成. - * - * @param ex 异常信息 - * @return true 如果处理了该异常信息;否则返回false. - */ - public boolean handleException(Throwable ex) { - if (ex == null) - return false; - // 收集设备参数信息 - collectDeviceInfo(mContext); - // 保存日志文件 - saveCrashInfo2File(ex); - return true; - } - - /** - * 收集设备参数信息 - */ - public void collectDeviceInfo(Context context) { - try { - PackageManager pm = context.getPackageManager();// 获得包管理器 - PackageInfo pi = pm.getPackageInfo(context.getPackageName(), - PackageManager.GET_ACTIVITIES);// 得到该应用的信息,即主Activity - if (pi != null) { - String versionName = pi.versionName == null ? "null" - : pi.versionName; - String versionCode = pi.versionCode + ""; - info.put("versionName", versionName); - info.put("versionCode", versionCode); - } - } catch (NameNotFoundException e) { - e.printStackTrace(); - Logger.e("获取设置信息失败"); - } - - Field[] fields = Build.class.getDeclaredFields();// 反射机制 - for (Field field : fields) { - try { - field.setAccessible(true); - info.put(field.getName(), field.get("").toString()); - Logger.e(field.getName() + ":" + field.get("")); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - } - } - - @Nullable - private String saveCrashInfo2File(Throwable ex) { - StringBuilder sb = new StringBuilder(); - for (Map.Entry entry : info.entrySet()) { - String key = entry.getKey(); - String value = entry.getValue(); - sb.append(key).append("=").append(value).append("\r\n"); - } - Writer writer = new StringWriter(); - PrintWriter pw = new PrintWriter(writer); - ex.printStackTrace(pw); - Throwable cause = ex.getCause(); - // 循环着把所有的异常信息写入writer中 - while (cause != null) { - cause.printStackTrace(pw); - cause = cause.getCause(); - } - pw.close();// 记得关闭 - String result = writer.toString(); - sb.append(result); - // 保存文件 - String fileName = "crash-" + DateUtils.getCurrentDateStr() + "-" + DateUtils.getCurrentTimeStamp() + ".log"; - if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { - try { - File file = new File(FileUtils.getAppCrashPath(), fileName); - FileOutputStream fos = new FileOutputStream(file); - fos.write(sb.toString().getBytes()); - fos.close(); - return fileName; - } catch (IOException e) { - e.printStackTrace(); - } - } - return null; - } - - /** - * 上传日志文件 - */ - public static void uploadCrashFiles() { - final File outFile = FileUtils.getAppCrashPath(); - LinkedList files = FileUtils.listLinkedFiles(FileUtils.getAppCrashPath().getPath()); - if (files == null || files.size() == 0) { - return; - } - try { - ZipUtils.zipFiles(files, outFile); - } catch (IOException e) { - e.printStackTrace(); - } - if (!outFile.exists()) {//如果这个zip文件不存在的话,则不执行如下的操作 - return; - } - //TODO 做上传操作 - } -} diff --git a/common_base/src/main/java/com/wss/common/manage/GlideRoundTransform.java b/common_base/src/main/java/com/wss/common/manage/GlideRoundTransform.java new file mode 100644 index 0000000..dcd825c --- /dev/null +++ b/common_base/src/main/java/com/wss/common/manage/GlideRoundTransform.java @@ -0,0 +1,60 @@ +package com.wss.common.manage; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapShader; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.RectF; + +import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool; +import com.bumptech.glide.load.resource.bitmap.BitmapTransformation; +import com.bumptech.glide.load.resource.bitmap.TransformationUtils; +import com.wss.common.utils.PxUtils; + +import org.jetbrains.annotations.Contract; + +import java.security.MessageDigest; + +import androidx.annotation.NonNull; + +/** + * Describe:加载图片转换器之圆角转换器 + * Created by 吴天强 on 2019/7/2. + */ +public class GlideRoundTransform extends BitmapTransformation { + + private float radius = 0f; + + public GlideRoundTransform(Context context, int dp) { + super(); + radius = PxUtils.dp2px(dp); + } + + @Override + protected Bitmap transform(@NonNull BitmapPool pool, @NonNull Bitmap toTransform, int outWidth, int outHeight) { + Bitmap bitmap = TransformationUtils.centerCrop(pool, toTransform, outWidth, outHeight); + return roundCrop(pool, bitmap); + } + + @Contract("_, null -> null") + private Bitmap roundCrop(BitmapPool pool, Bitmap source) { + if (source == null){ return null;} + Bitmap result = pool.get(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(result); + Paint paint = new Paint(); + paint.setShader(new BitmapShader(source, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP)); + paint.setAntiAlias(true); + RectF rectF = new RectF(0f, 0f, source.getWidth(), source.getHeight()); + canvas.drawRoundRect(rectF, radius, radius, paint); + return result; + } + + public String getId() { + return getClass().getName() + Math.round(radius); + } + + @Override + public void updateDiskCacheKey(@NonNull MessageDigest messageDigest) { + } +} diff --git a/common_base/src/main/java/com/wss/common/manage/UpdateManager.java b/common_base/src/main/java/com/wss/common/manage/UpdateManager.java deleted file mode 100644 index 59cc479..0000000 --- a/common_base/src/main/java/com/wss/common/manage/UpdateManager.java +++ /dev/null @@ -1,144 +0,0 @@ -package com.wss.common.manage; - -import android.annotation.SuppressLint; -import android.content.Context; -import android.content.Intent; -import android.net.Uri; -import android.os.Build; -import android.os.Handler; -import android.os.Message; -import android.text.TextUtils; -import android.view.View; - -import com.tamic.novate.Throwable; -import com.tamic.novate.callback.RxFileCallBack; -import com.wss.common.base.R; -import com.wss.common.net.HttpUtils; -import com.wss.common.net.NetConfig; -import com.wss.common.utils.FileUtils; -import com.wss.common.utils.ToastUtils; -import com.wss.common.widget.NumberProgressBar; -import com.wss.common.widget.dialog.AppDialog; - -import java.io.File; - - -/** - * 更新下载APK - * Created by wtq on 2016/7/22. - */ -@SuppressLint("StaticFieldLeak") -public class UpdateManager { - - private static final int DOWNLOADING = 0x00; - private static final int DOWNLOAD_SUCCESS = 0x02; - private static final int DOWNLOAD_FAILED = 0x03; - private static final int DOWNLOAD_CANCEL = 0x04; - private Context mContext; - private NumberProgressBar progressBar; - private AppDialog progressDialog; - private static UpdateManager manager; - private File tempFile;//下载后存文件路径 - - private UpdateManager(Context context) { - this.mContext = context; - View progressView = View.inflate(mContext, R.layout.update_progress_layout, null); - progressBar = progressView.findViewById(R.id.number_progress); - progressBar.setProgress(0); - progressDialog = new AppDialog(mContext); - progressDialog.setTitle("版本更新中···") - .addDialogView(progressView) - .show(); - } - - public static synchronized UpdateManager getInstance(Context context) { - if (manager == null) { - manager = new UpdateManager(context); - } - return manager; - } - - /** - * 弹出下载框 - */ - public void download(String url) { - if (TextUtils.isEmpty(url)) { - ToastUtils.show(mContext, "请设置下载Url"); - return; - } - progressDialog.show(); - HttpUtils.getInstance() - .setBaseUrl(NetConfig.Url.MY_SERVICE_URL) - .downloadFile(url, new RxFileCallBack("temp.apk") { - - @Override - public void onNext(Object tag, File file) { - tempFile = file; - updateHandler.sendEmptyMessage(DOWNLOAD_SUCCESS); - } - - @Override - public void onProgress(Object tag, float progress, long downloaded, long total) { - Message message = updateHandler.obtainMessage(); - message.what = DOWNLOADING; - message.obj = (int) progress; - updateHandler.sendMessage(message); - } - - @Override - public void onError(Object tag, Throwable e) { - updateHandler.sendEmptyMessage(DOWNLOAD_FAILED); - } - - @Override - public void onCancel(Object tag, Throwable e) { - updateHandler.sendEmptyMessage(DOWNLOAD_CANCEL); - } - }); - } - - - @SuppressLint("HandlerLeak") - private Handler updateHandler = new Handler() { - public void handleMessage(Message msg) { - switch (msg.what) { - case DOWNLOADING: - progressBar.setProgress((Integer) msg.obj); - break; - case DOWNLOAD_SUCCESS: - progressDialog.dismiss(); - ToastUtils.show(mContext, "下载完成"); - installApk(); - break; - case DOWNLOAD_FAILED: - progressDialog.dismiss(); - ToastUtils.show(mContext, "下载失败"); - break; - case DOWNLOAD_CANCEL: - progressDialog.dismiss(); - ToastUtils.show(mContext, "已取消下载"); - break; - default: - break; - } - } - - }; - - /** - * 安装apk - */ - private void installApk() { - // 安装,如果签名不一致,可能出现程序未安装提示 - Intent intent = new Intent(Intent.ACTION_VIEW); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - Uri uriForFile = FileUtils.getUriForFile(mContext, tempFile); - intent.setDataAndType(uriForFile, "application/vnd.android.package-archive"); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - //7.0需要临时授权文件 - intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - } - mContext.startActivity(intent); - } -} diff --git a/common_base/src/main/java/com/wss/common/net/Api.java b/common_base/src/main/java/com/wss/common/net/Api.java index d841f8d..48eab85 100644 --- a/common_base/src/main/java/com/wss/common/net/Api.java +++ b/common_base/src/main/java/com/wss/common/net/Api.java @@ -1,11 +1,20 @@ package com.wss.common.net; + +import com.wss.common.profile.ProfileManager; + +import rxhttp.wrapper.annotation.DefaultDomain; + /** - * Describe:接口 + * Describe:接口名称 * Created by 吴天强 on 2018/10/17. */ - public interface Api { + /** + * 网络请求BaseUrl + */ + @DefaultDomain + String BASE_URL = ProfileManager.profile().getServiceBase(); //**********************************************鸿洋开放接口************************************** /** @@ -84,4 +93,5 @@ public interface Api { //**********************************************自己服务器接口************************************ + } diff --git a/common_base/src/main/java/com/wss/common/net/HttpUtils.java b/common_base/src/main/java/com/wss/common/net/HttpUtils.java deleted file mode 100644 index 7097fca..0000000 --- a/common_base/src/main/java/com/wss/common/net/HttpUtils.java +++ /dev/null @@ -1,310 +0,0 @@ -package com.wss.common.net; - -import android.text.TextUtils; - -import com.orhanobut.logger.Logger; -import com.tamic.novate.Novate; -import com.tamic.novate.callback.ResponseCallback; -import com.tamic.novate.callback.RxFileCallBack; -import com.wss.common.base.BaseApplication; -import com.wss.common.net.callback.OnResultCallBack; - -import java.io.File; -import java.util.List; - -/** - * Describe:网络请求帮助类 - * Created by 吴天强 on 2017/9/19. - */ - -public class HttpUtils { - - private static final int REQUEST_GET = 0; - private static final int REQUEST_POST = 1; - private static final int REQUEST_JSON = 2; - private Novate.Builder builder; - private static HttpUtils httpUtils; - private String baseUrl; - - private HttpUtils() { - builder = new Novate.Builder(BaseApplication.getApplication()); - builder.addCookie(true); //是否同步cooike 默认不同步 - - //https配置 xxx.cer放在asset目录下 -// builder.skipSSLSocketFactory(true);//信任所有证书 -// builder.addSSLSocketFactory(NovateHttpsFactroy.creatSSLSocketFactory( -// BaseApplication.getApplication().getBaseContext(), "xxx.cer")); - -// builder.addHeader(headers); //添加公共请求头 -// builder.addParameters(parameters);//公共参数 -// builder.connectTimeout(10); //连接时间 可以忽略 -// builder.addCache(true); //是否缓存 默认缓存 -// builder.addCache(cache, cacheTime); //自定义缓存 -// builder.addLog(true);//是否开启log -// builder.cookieManager(new NovateCookieManager()); // 自定义cooike,可以忽略 -// builder.addInterceptor(); // 自定义Interceptor -// builder.addNetworkInterceptor(); // 自定义NetworkInterceptor -// builder.proxy(proxy); //代理 -// builder.client(client); //clent 默认不需要 - } - - public static synchronized HttpUtils getInstance() { - if (httpUtils == null) { - httpUtils = new HttpUtils(); - } - return new HttpUtils(); - } - - public HttpUtils setBaseUrl(String baseUrl) { - this.baseUrl = baseUrl; - return this; - } - - ////////////////////////////////////////// GET请求 ///////////////////////////////////////////// - - /** - * Get无参无Tag - * - * @param url 请求地址 - * @param callback 回调 - */ - public void getRequest(String url, OnResultCallBack callback) { - request(REQUEST_GET, url, new RequestParam(), null, callback); - } - - /** - * Get 无参有Tag - * - * @param url 请求地址 - * @param tag 标签 - * @param callback 回调 - */ - public void getRequest(String url, String tag, OnResultCallBack callback) { - request(REQUEST_GET, url, new RequestParam(), tag, callback); - } - - /** - * Get有参无Tag - * - * @param url 请求地址 - * @param params 请求参数 - * @param callback 回调 - */ - public void getRequest(String url, RequestParam params, OnResultCallBack callback) { - request(REQUEST_GET, url, params, null, callback); - } - - /** - * Get有参有Tag - * - * @param url 请求地址 - * @param params 请求参数 - * @param tag 标签 - * @param callback 回调 - */ - public void getRequest(String url, RequestParam params, String tag, OnResultCallBack callback) { - request(REQUEST_GET, url, params, tag, callback); - } - - - ////////////////////////////////////////// POST请求 ///////////////////////////////////////////// - - /** - * Post 无参无TAG - * - * @param url 请求地址 - * @param callback 回调 - */ - public void postRequest(String url, OnResultCallBack callback) { - request(REQUEST_POST, url, new RequestParam(), null, callback); - } - - /** - * Post 无参有TAG - * - * @param url 请求地址 - * @param tag 标签 - * @param callback 回调 - */ - public void postRequest(String url, String tag, OnResultCallBack callback) { - request(REQUEST_POST, url, new RequestParam(), tag, callback); - } - - /** - * Post 有参无TAG - * - * @param url 请求地址 - * @param params 请求参数 - * @param callback 回调 - */ - public void postRequest(String url, RequestParam params, OnResultCallBack callback) { - request(REQUEST_POST, url, params, null, callback); - } - - /** - * Post 有参有TAG - * - * @param url 请求地址 - * @param params 请求参数 - * @param tag 标签 - * @param callback 回调 - */ - public void postRequest(String url, RequestParam params, String tag, OnResultCallBack callback) { - request(REQUEST_POST, url, params, tag, callback); - } - - ////////////////////////////////////////// JSON格式请求 ///////////////////////////////////////// - - /** - * Post 无参无TAG - * - * @param url 请求地址 - * @param callback 回调 - */ - public void jsonRequest(String url, OnResultCallBack callback) { - request(REQUEST_JSON, url, new RequestParam(), null, callback); - } - - /** - * Post 无参有TAG - * - * @param url 请求地址 - * @param tag 标签 - * @param callback 回调 - */ - public void jsonRequest(String url, String tag, OnResultCallBack callback) { - request(REQUEST_JSON, url, new RequestParam(), tag, callback); - } - - /** - * Post 有参无TAG - * - * @param url 请求地址 - * @param params 请求参数 - * @param callback 回调 - */ - public void jsonRequest(String url, RequestParam params, OnResultCallBack callback) { - request(REQUEST_JSON, url, params, null, callback); - } - - /** - * Post 有参有TAG - * - * @param url 请求地址 - * @param params 请求参数 - * @param tag 标签 - * @param callback 回调 - */ - public void jsonRequest(String url, RequestParam params, String tag, OnResultCallBack callback) { - request(REQUEST_JSON, url, params, tag, callback); - } - - - /** - * 最终请求 - * - * @param methodType 请求类型 get post - * @param url 接口 - * @param params 参数 - * @param tag tag - * @param callback 请求回调 - */ - private void request(int methodType, String url, RequestParam params, String tag, ResponseCallback callback) { - checkBaseUrl(); - Logger.e(baseUrl + url + params.toJson()); - switch (methodType) { - case REQUEST_POST: - builder.build().rxPost(tag, url, params.getParameter(), callback); - break; - case REQUEST_GET: - builder.build().rxGet(tag, url, params.getParameter(), callback); - break; - case REQUEST_JSON: - builder.build().rxJson(tag, url, params.toJson(), callback); - break; - default: - builder.build().rxGet(tag, url, params.getParameter(), callback); - break; - } - } - - ////////////////////////////////////////// 上传文件 ///////////////////////////////////////////// - - /** - * 上传单个文件 - * - * @param url 接口 - * @param file 文件 - * @param callback 回调 - */ - public void upLoadFile(String url, File file, OnResultCallBack callback) { - upLoadFile(url, file, null, callback); - } - - /** - * 上传单个文件 - * - * @param url 接口 - * @param file 文件 - * @param tag 标签 - * @param callback 回调 - */ - public void upLoadFile(String url, File file, String tag, ResponseCallback callback) { - //使用Part 方式上传文件 - checkBaseUrl(); - Logger.e(NetConfig.Url.getBaseUrl() + url + file.getAbsolutePath()); - builder.build().rxUploadWithPart(tag, url, file, callback); - } - - /** - * 上传多个文件 - * - * @param url 接口 - * @param files 文件 - * @param callback 回调 - */ - public void upLoadFile(String url, List files, OnResultCallBack callback) { - upLoadFile(url, files, null, callback); - } - - - /** - * 上传多个文件 - * - * @param url 接口 - * @param files 文件 - * @param tag 标签 - * @param callback 回调 - */ - public void upLoadFile(String url, List files, String tag, ResponseCallback callback) { - checkBaseUrl(); - Logger.e(NetConfig.Url.getBaseUrl() + url + files.size()); - builder.build().rxUploadWithPartListByFile(tag, url, files, callback); - } - - ////////////////////////////////////////// 下载文件 ///////////////////////////////////////////// - - /** - * 文件下载 - * - * @param url 文件路径 - * @param callBack 回调 - */ - public void downloadFile(String url, RxFileCallBack callBack) { - checkBaseUrl(); - Logger.e(NetConfig.Url.getBaseUrl() + url); - builder.build().rxDownload(url, callBack); - } - - /** - * 检查是否设置BaseURL - */ - private void checkBaseUrl() { - //如果没有设置请求BaseUrl 则使用默认的BaseUrl - if (TextUtils.isEmpty(baseUrl)) { - baseUrl = NetConfig.Url.getBaseUrl(); - } - builder.baseUrl(baseUrl); - } - -} diff --git a/common_base/src/main/java/com/wss/common/net/NetConfig.java b/common_base/src/main/java/com/wss/common/net/NetConfig.java deleted file mode 100644 index 47e26f2..0000000 --- a/common_base/src/main/java/com/wss/common/net/NetConfig.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.wss.common.net; - -import com.wss.common.constants.Constants; - - -/** - * Describe:网络请求URL - * Created by 吴天强 on 2017/9/26. - */ - -public class NetConfig { - - - /** - * 响应的返回key - */ - public class Code { - public static final String SUCCESS = "success"; - public static final String MSG = "errorMsg"; - public static final String CODE = "errorCode"; - public static final String MODEL = "data"; - } - - /** - * H5界面 - */ - public class Html { - - } - - /** - * 网络请求Url - */ - public static class Url { - - //自己服务器IP - public static String MY_SERVICE_URL = "http://sdk.xiaoyuyu.com.cn"; - - //服务器地址 - interface BaseUrl { - String SERVER_DEVELOP = "http://www.wanandroid.com"; - String SERVER_TEST = ""; - String SERVER_PRODUCTION = ""; - } - - /** - * 返回服务器基础地址 - */ - static String getBaseUrl() { - switch (Constants.SERVER_TYPE) { - case Constants.ServerType.SERVER_DEVELOP: - return BaseUrl.SERVER_DEVELOP; - case Constants.ServerType.SERVER_TEST: - return BaseUrl.SERVER_TEST; - case Constants.ServerType.SERVER_PRODUCTION: - return BaseUrl.SERVER_PRODUCTION; - } - return BaseUrl.SERVER_PRODUCTION; - } - - - } - -} diff --git a/common_base/src/main/java/com/wss/common/net/NetworkManage.java b/common_base/src/main/java/com/wss/common/net/NetworkManage.java new file mode 100644 index 0000000..9bfa20a --- /dev/null +++ b/common_base/src/main/java/com/wss/common/net/NetworkManage.java @@ -0,0 +1,505 @@ +package com.wss.common.net; + +import android.os.Handler; +import android.text.TextUtils; + +import com.orhanobut.logger.Logger; +import com.rxjava.rxlife.RxLife; +import com.wss.common.base.BaseApplication; +import com.wss.common.base.R; +import com.wss.common.constants.Constants; +import com.wss.common.exception.NetErrorException; +import com.wss.common.manage.ActivityToActivity; +import com.wss.common.net.request.RequestParam; +import com.wss.common.net.response.BaseResponse; +import com.wss.common.utils.JsonUtils; +import com.wss.common.utils.NetworkUtil; +import com.wss.common.utils.ToastUtils; +import com.wss.common.utils.Utils; +import com.wss.common.utils.ValidUtils; + +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + +import java.io.File; +import java.net.SocketTimeoutException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import androidx.annotation.NonNull; +import androidx.lifecycle.LifecycleOwner; +import io.reactivex.Observable; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.schedulers.Schedulers; +import rxhttp.wrapper.exception.HttpStatusCodeException; +import rxhttp.wrapper.param.RxHttp; +import rxhttp.wrapper.param.RxHttpFormParam; +import rxhttp.wrapper.param.RxHttpJsonParam; +import rxhttp.wrapper.param.RxHttpNoBodyParam; + + +/** + * Describe:网络请求帮助类 + * Created by 吴天强 on 2020/1/3. + */ +@SuppressWarnings("unchecked") +public class NetworkManage { + /** + * 取第一个进来的跳转到登录页 + */ + public volatile static int count = 0; + private static final String GET = "GET"; + private static final String POST_FORM = "POST_FORM"; + private static final String POST_JSON = "POST_JSON"; + private static final String PUT_FORM = "PUT_FORM"; + private static final String PUT_JSON = "PUT_JSON"; + private static final String DELETE_FORM = "DELETE_FORM"; + private static final String DELETE_JSON = "DELETE_JSON"; + /** + * 账户相关的报错信息 + */ + private static final List ACCOUNT_ERROR_CODE = new ArrayList<>(); + + static { + ACCOUNT_ERROR_CODE.add(Constants.Net.Status.CODE_ACCOUNT_DISABLE); + ACCOUNT_ERROR_CODE.add(Constants.Net.Status.CODE_ACCOUNT_QUIT); + ACCOUNT_ERROR_CODE.add(Constants.Net.Status.CODE_ACCOUNT_LOCKED); + ACCOUNT_ERROR_CODE.add(Constants.Net.Status.CODE_ACCOUNT_NO_AUTHORITY); + ACCOUNT_ERROR_CODE.add(Constants.Net.Status.CODE_ACCOUNT_NO_TEAM); + ACCOUNT_ERROR_CODE.add(Constants.Net.Status.CODE_ACCOUNT_MULTIPLE_TEAM); + ACCOUNT_ERROR_CODE.add(Constants.Net.Status.CODE_TOKEN_EXPIRED); + ACCOUNT_ERROR_CODE.add(Constants.Net.Status.CODE_ACCOUNT_POSITION_ERROR); + } + + /** + * 构建Get请求 + */ + @NonNull + public static Request createGet() { + return create(GET); + } + + /** + * 构建PostFrom请求 + */ + @NonNull + public static Request createPostForm() { + return create(POST_FORM); + } + + /** + * 构建PostJson请求 + */ + @NonNull + public static Request createPostJson() { + return create(POST_JSON); + } + + /** + * 构建PutForm请求 + */ + @NonNull + public static Request createPutForm() { + return create(PUT_FORM); + } + + /** + * 构建PutJson请求 + */ + @NonNull + public static Request createPutJson() { + return create(PUT_JSON); + } + + /** + * 构建DeleteForm请求 + */ + @NonNull + public static Request createDeleteForm() { + return create(DELETE_FORM); + } + + /** + * 构建DeleteJson请求 + */ + @NonNull + public static Request createDeleteJson() { + return create(DELETE_JSON); + } + + + /** + * 构建请求类型 + */ + @Contract(value = "_ -> new", pure = true) + @NonNull + private static Request create(String method) { + return new Request(method); + } + + /** + * 网络请求主类 + */ + public static class Request { + private String method; + private String requestId; + + + Request(String method) { + this.method = method; + requestId = UUID.randomUUID().toString().replaceAll("-", ""); + } + + /** + * 无参请求返回String类型 + * + * @param life 声明周期实现类 + * @param url 请求URL + */ + public Observable request(LifecycleOwner life, String url) { + return request(life, url, null, (Class) String.class); + } + + /** + * 无参请求返回T类型 + * + * @param life 声明周期实现类 + * @param url 请求URL + * @param type 响应泛型类型 + */ + public Observable request(LifecycleOwner life, String url, Class type) { + return request(life, url, null, type); + } + + /** + * 有参请求返回String类型 + * + * @param life 声明周期实现类 + * @param url 请求URL + * @param param 请求参数 + */ + public Observable request(LifecycleOwner life, String url, RequestParam param) { + return request(life, url, param, (Class) String.class); + } + + /** + * 有参请求返回T类型 + * + * @param life 声明周期实现类 + * @param url 请求URLu + * @param param 请求参数 + * @param type 响应泛型类型 + */ + public Observable request(LifecycleOwner life, String url, RequestParam param, Class type) { + return Observable.create( + subscriber -> { + if (!NetworkUtil.isNetworkEnabled(BaseApplication.i())) { + //无可用网络 + subscriber.onError(new NetErrorException(BaseApplication.i().getString(R.string.network_error_no_net))); + return; + } + Disposable subscribe = checkRequest(url, param) + .as(RxLife.asOnMain(life)) //感知生命周期,并在主线程回调 + .subscribe(response -> + checkResponse(url, response).subscribe(baseResponse -> { + if (type == BaseResponse.class) { + subscriber.onNext((T) baseResponse); + } else if (type == String.class) { + subscriber.onNext((T) baseResponse.getData()); + } else { + //根据类型解析 + subscriber.onNext(JsonUtils.getObject(baseResponse.getData(), type)); + } + }, subscriber::onError), throwable -> subscriber.onError(handleError(throwable))); + BaseApplication.i().addNetDisposable(requestId, subscribe); + }) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()); + } + + /** + * 无参请求返回List类型 + * + * @param life 声明周期实现类 + * @param url 请求URL + * @param type 响应泛型类型 + */ + public Observable> requestList(LifecycleOwner life, String url, Class type) { + return requestList(life, url, null, type); + } + + /** + * 有参请求返回List类型 + * + * @param life 声明周期实现类 + * @param url 请求URL + * @param param 请求参数 + */ + public Observable> requestList(LifecycleOwner life, String url, RequestParam param) { + return requestList(life, url, param, (Class) String.class); + } + + /** + * 有参请求返回List类型 + * + * @param life 声明周期实现类 + * @param url 请求URL + * @param param 请求参数 + * @param type 响应泛型类型 + */ + public Observable> requestList(LifecycleOwner life, String url, RequestParam param, Class type) { + return Observable.>create( + subscriber -> { + if (!NetworkUtil.isNetworkEnabled(BaseApplication.i())) { + //无可用网络 + subscriber.onError(new NetErrorException(BaseApplication.i().getString(R.string.network_error_no_net))); + return; + } + Disposable subscribe = checkRequest(url, param) + .as(RxLife.asOnMain(life)) //感知生命周期,并在主线程回调 + .subscribe(response -> checkResponse(url, response).subscribe( + baseResponse -> subscriber.onNext(JsonUtils.getList(baseResponse.getData(), type)), + subscriber::onError), throwable -> subscriber.onError(handleError(throwable))); + BaseApplication.i().addNetDisposable(requestId, subscribe); + }) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()); + + } + + /** + * 检查响应 + * + * @param apiUrl 接口地址 + * @param response 响应数据 + * @return BaseResponse + */ + private Observable checkResponse(String apiUrl, String response) { + return Observable.create(subscriber -> { + BaseApplication.i().removeNetDisposable(requestId); + Logger.e(String.format("Request-Id:%s\n响应:%s", requestId, response)); + String state = JsonUtils.getString(response, Constants.Net.STATE); + String message = JsonUtils.getString(response, Constants.Net.MESSAGE); + String data; + try { + //防止返回的data为null导致解析json失败 + data = JsonUtils.getString(response, Constants.Net.DATA); + } catch (Exception e) { + data = ""; + } + if (Constants.Net.Status.CODE_SUCCESS.equals(state)) { + subscriber.onNext(new BaseResponse(state, message, data)); + } else { + if (!Api.LOGIN.equals(apiUrl) && ACCOUNT_ERROR_CODE.contains(state)) { + //如果是非登录接口且错误码为定义的这部分,则需要跳转到登录页面 + synchronized (NetworkManage.class) { + //防止多个线程一瞬间进来了,让需要进来的进行排队 + if (count <= 0) { + //Token 过期 跳转登录页面 + toLoginActivity(message); + } + count++; + } + } else { + //接口返回 false 把message、data扔出去 + subscriber.onError(new NetErrorException(state, message, data)); + } + } + }) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()); + } + + + /** + * 网络请求之前参数检查,组装公共请求参数,加密等操作 + * + * @param url 接口地址 + * @param param 请求参数 + * @return Observable + */ + @NotNull + private Observable checkRequest(String url, RequestParam param) { + if (!ValidUtils.isValid(param)) { + param = new RequestParam(); + } + //打印请求 + Logger.e(String.format("Request-Id:%s\n%s %s%s\n请求参数:%s", requestId, method, Api.BASE_URL, url, JsonUtils.toJson(param.getParameter()))); + RxHttp rxHttp = buildRequest(url, param); + //添加Header + for (Map.Entry entry : buildHeader().entrySet()) { + rxHttp.addHeader(entry.getKey(), entry.getValue()); + } + return rxHttp.asString(); + } + + /** + * 构建请求 + * + * @param url 接口地址 + * @param param 请求参数 + * @return RxHttp + */ + private RxHttp buildRequest(String url, @NotNull RequestParam param) { + Map fileMap = new HashMap<>(16); + Map paramMap = new HashMap<>(16); + + //分离请求参数中的文件 + for (Map.Entry entry : param.getParameter().entrySet()) { + if (entry.getValue() instanceof File) { + fileMap.put(entry.getKey(), entry.getValue()); + } else if (entry.getValue() instanceof String) { + //把null转成"" + String value = String.valueOf(entry.getValue()); + if (!ValidUtils.isValid(value) || "null".equalsIgnoreCase(value)) { + value = ""; + } + paramMap.put(entry.getKey(), value); + } else { + paramMap.put(entry.getKey(), entry.getValue()); + } + } + RxHttp rxHttp; + switch (method) { + case POST_JSON: + case PUT_JSON: + case DELETE_JSON: + //JSON格式请求 + if (TextUtils.equals(method, POST_JSON)) { + rxHttp = RxHttp.postJson(url); + } else if (TextUtils.equals(method, DELETE_JSON)) { + rxHttp = RxHttp.deleteJson(url); + } else { + rxHttp = RxHttp.putJson(url); + } + ((RxHttpJsonParam) rxHttp).addAll(paramMap); + //添加文件请求参数 + if (!fileMap.isEmpty()) { + for (Map.Entry entry : fileMap.entrySet()) { + ((RxHttpJsonParam) rxHttp).add(entry.getKey(), entry.getValue()); + } + } + break; + case POST_FORM: + case PUT_FORM: + case DELETE_FORM: + //POST格式请求 + if (TextUtils.equals(method, POST_FORM)) { + rxHttp = RxHttp.postForm(url); + } else if (TextUtils.equals(method, DELETE_FORM)) { + rxHttp = RxHttp.deleteForm(url); + } else { + rxHttp = RxHttp.putForm(url); + } + ((RxHttpFormParam) rxHttp).addAll(paramMap); + //添加文件请求参数 + if (!fileMap.isEmpty()) { + for (Map.Entry entry : fileMap.entrySet()) { + ((RxHttpFormParam) rxHttp).addFile(entry.getKey(), (File) entry.getValue()); + } + } + break; + case GET: + default: + rxHttp = RxHttp.get(url); + ((RxHttpNoBodyParam) rxHttp).addAll(paramMap); + //添加文件请求参数 + if (!fileMap.isEmpty()) { + for (Map.Entry entry : fileMap.entrySet()) { + ((RxHttpNoBodyParam) rxHttp).add(entry.getKey(), entry.getValue()); + } + } + break; + } + return rxHttp; + } + + /** + * 构建请求头 + * + * @return 请求头Map + */ + @NotNull + private Map buildHeader() { + String deviceId = BaseApplication.i().getDeviceId(); + String token = BaseApplication.i().getLoginToken(); + Map header = new HashMap<>(); + header.put(Constants.Net.HEADER_CHANNEL, Constants.Common.CHANEL); + header.put(Constants.Net.HEADER_API_VERSION, Constants.Common.API_VERSION); + header.put(Constants.Net.HEADER_DEVICE_ID, ValidUtils.isValid(deviceId) ? deviceId : ""); + header.put(Constants.Net.HEADER_TOKEN, ValidUtils.isValid(token) ? token : ""); + header.put(Constants.Net.HEADER_APP_VERSION, Utils.getVersionName()); + header.put(Constants.Net.HEADER_IP, NetworkUtil.getIpAddress()); + header.put(Constants.Net.REQUEST_ID, requestId); + Logger.i("请求Header:\n" + JsonUtils.toJson(header)); + return header; + } + + + /** + * 处理网络请求中的异常 + * + * @param t Throwable + * @return NetErrorException + */ + @Contract("_ -> new") + @NotNull + private NetErrorException handleError(@NotNull Throwable t) { + BaseApplication.i().removeNetDisposable(requestId); + String errorMessage = null; + String loggerMessage = ""; + if (t instanceof SocketTimeoutException) { + errorMessage = BaseApplication.i().getString(R.string.request_time_out); + loggerMessage = errorMessage; + } else if (t instanceof HttpStatusCodeException) { + HttpStatusCodeException codeException = (HttpStatusCodeException) t; + try { + errorMessage = JsonUtils.getString(codeException.getResult(), Constants.Net.MESSAGE); + } catch (Exception e) { + errorMessage = BaseApplication.i().getString(R.string.network_error_server_error); + } + loggerMessage = String.format("%s %s", codeException.getStatusCode(), errorMessage); + } else { + loggerMessage = t.getMessage(); + } + if (!ValidUtils.isValid(errorMessage)) { + errorMessage = BaseApplication.i().getString(R.string.network_error_server_error); + } + Logger.e(String.format("Request-Id:%s\n请求报错:%s", requestId, loggerMessage)); + return new NetErrorException(errorMessage); + } + + /** + * 跳转登录页 + * + * @param errorMessage 错误信息 + */ + private void toLoginActivity(String errorMessage) { + Observable.create( + subscriber -> { + //检查是否存在未完成的请求,有就取消 + for (Map.Entry entry : BaseApplication.i().getNetDisposables().entrySet()) { + if (!entry.getValue().isDisposed()) { + entry.getValue().dispose(); + } + } + ToastUtils.show(errorMessage); + //延时1秒跳转到登录页,最大限度的,避免由于网络延时,带来的token过期退出到登录页的异常 + new Handler().postDelayed(() -> { + ActivityToActivity.toLoginActivity(BaseApplication.i()); + BaseApplication.i().loginOutClean(); + }, 500); + + }) + .subscribeOn(AndroidSchedulers.mainThread()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(); + } + //--------------------------其他第三方服务请求-------------------------------------------- + + } +} diff --git a/common_base/src/main/java/com/wss/common/net/RequestParam.java b/common_base/src/main/java/com/wss/common/net/RequestParam.java deleted file mode 100644 index 6f2bf06..0000000 --- a/common_base/src/main/java/com/wss/common/net/RequestParam.java +++ /dev/null @@ -1,94 +0,0 @@ -package com.wss.common.net; - -import org.json.JSONException; -import org.json.JSONObject; - -import java.util.LinkedHashMap; -import java.util.Map; - - -/** - * Describe:请求参数封装类 - * Created by 吴天强 on 2017/9/19. - */ -public class RequestParam { - - private Map params; - - public RequestParam() { - params = new LinkedHashMap<>(); - } - - /** - * 普通文本参数 - * - * @param key key - * @param value 值 - */ - public void addParameter(String key, Object value) { - if (this.params == null) { - params = new LinkedHashMap<>(); - } - params.put(key, value); - } - - - public void addParameter(String key, int value) { - addParameter(key, String.valueOf(value)); - } - - public void addParameter(String key, long value) { - addParameter(key, String.valueOf(value)); - } - - public void addParameter(String key, float value) { - addParameter(key, String.valueOf(value)); - } - - public void addParameter(String key, double value) { - addParameter(key, String.valueOf(value)); - } - - /** - * 获取请求参数 - * - * @return Map - */ - public Map getParameter() { - if (null == params) { - params = new LinkedHashMap<>(); - } - return params; - } - - - /** - * 请求参数转Json - * - * @return String - */ - String toJson() { - JSONObject json = new JSONObject(); - for (Map.Entry entry : params.entrySet()) { - try { - json.put(entry.getKey(), entry.getValue()); - } catch (JSONException e) { - e.printStackTrace(); - } - } - return json.toString(); - } - - @Override - public String toString() { - StringBuilder stringBuffer = new StringBuilder(); - for (Map.Entry entry : params.entrySet()) { - stringBuffer.append(entry.getKey()); - stringBuffer.append(":"); - stringBuffer.append(entry.getValue()); - stringBuffer.append("\t"); - } - return stringBuffer.toString(); - } - -} diff --git a/common_base/src/main/java/com/wss/common/net/callback/OnResultCallBack.java b/common_base/src/main/java/com/wss/common/net/callback/OnResultCallBack.java deleted file mode 100644 index 622644a..0000000 --- a/common_base/src/main/java/com/wss/common/net/callback/OnResultCallBack.java +++ /dev/null @@ -1,98 +0,0 @@ -package com.wss.common.net.callback; - - -import com.alibaba.fastjson.JSON; -import com.google.gson.Gson; -import com.orhanobut.logger.Logger; -import com.tamic.novate.Throwable; -import com.tamic.novate.callback.RxGenericsCallback; -import com.wss.common.net.NetConfig; - -import org.json.JSONObject; - -import java.io.IOException; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; - -import okhttp3.Call; -import okhttp3.ResponseBody; - -/** - * Describe:网络返回基类 泛型为必传项 默认 传入String即可 - * Created by 吴天强 on 2017/9/26. - */ -@SuppressWarnings("unchecked") -public abstract class OnResultCallBack extends RxGenericsCallback { - protected boolean success; - - - @Override - public T onHandleResponse(ResponseBody response) throws Exception { - return transform(new String(response.bytes())); - } - - private T transform(String response) { - Logger.e(JSON.toJSONString(response)); - try { - JSONObject jsonObject = new JSONObject(response); - code = jsonObject.optInt(NetConfig.Code.CODE); - msg = jsonObject.optString(NetConfig.Code.MSG); - success = jsonObject.optBoolean(NetConfig.Code.SUCCESS); - dataStr = jsonObject.opt(NetConfig.Code.MODEL).toString(); - - if (dataStr.charAt(0) == 123) { - //获取泛型类型 - Class classOfT = (Class) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]; - if (classOfT == String.class) { - dataResponse = (T) dataStr; - } else { - //对象 - dataResponse = (new Gson()).fromJson(dataStr, classOfT); - } - } else if (dataStr.charAt(0) == 91) { - //数组 - Type collectionType = ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]; - dataResponse = new Gson().fromJson(dataStr, collectionType); - } - } catch (Exception e) { - e.printStackTrace(); - } - return dataResponse; - - } - - @Override - public void onError(Object tag, Throwable e) { - e.printStackTrace(); - onFailure(tag, e); - } - - - @Override - public void onCancel(Object tag, Throwable e) { - } - - @Override - public void onFailure(Call call, IOException e) { - onFailure(tag, e); - } - - @Override - public void onNext(Object tag, int code, String message, T response) { - onSuccess(success, code, msg, tag, response); - } - - @Override - public void onCompleted(Object tag) { - super.onCompleted(tag); - onCompleted(); - } - - - public abstract void onSuccess(boolean success, int code, String msg, Object tag, T response); - - public abstract void onFailure(Object tag, Exception e); - - public abstract void onCompleted(); - -} diff --git a/common_base/src/main/java/com/wss/common/net/request/RequestParam.java b/common_base/src/main/java/com/wss/common/net/request/RequestParam.java new file mode 100644 index 0000000..5d0e5b4 --- /dev/null +++ b/common_base/src/main/java/com/wss/common/net/request/RequestParam.java @@ -0,0 +1,133 @@ +package com.wss.common.net.request; + +import org.jetbrains.annotations.NotNull; + +import java.util.LinkedHashMap; +import java.util.Map; + + +/** + * Describe:请求参数封装类 + * Created by 吴天强 on 2017/9/19. + */ +public class RequestParam { + + /** + * 存放请求参数的Map + */ + private Map params; + + public RequestParam() { + params = new LinkedHashMap<>(); + } + + /** + * 添加请求参数 + * + * @param key key + * @param value 值 + */ + private void buildParameter(String key, Object value) { + if (this.params == null) { + params = new LinkedHashMap<>(); + } + params.put(key, value); + } + + /** + * 添加普通文本 + * + * @param key key + * @param value 值 + */ + public void addParameter(String key, String value) { + buildParameter(key, value); + } + + /** + * 添加int类型 + * + * @param key key + * @param value 值 + */ + public void addParameter(String key, Integer value) { + buildParameter(key, value); + } + + /** + * 添加long类型 + * + * @param key key + * @param value 值 + */ + public void addParameter(String key, Long value) { + buildParameter(key, value); + } + + /** + * 添加float类型 + * + * @param key key + * @param value 值 + */ + public void addParameter(String key, Float value) { + buildParameter(key, value); + } + + /** + * 添加double类型 + * + * @param key key + * @param value 值 + */ + public void addParameter(String key, Double value) { + buildParameter(key, value); + } + + /** + * 添加boolean类型 + * + * @param key key + * @param value 值 + */ + public void addParameter(String key, Boolean value) { + buildParameter(key, value); + } + + /** + * 添加Object类型 + * + * @param key key + * @param value 值 + */ + public void addParameter(String key, Object value) { + buildParameter(key, value); + } + + /** + * 获取请求参数 + * + * @return Map + */ + public Map getParameter() { + if (null == params) { + params = new LinkedHashMap<>(); + } + return params; + } + + + @NotNull + @Override + public String toString() { + StringBuilder stringBuffer = new StringBuilder(); + for (Map.Entry entry : params.entrySet()) { + stringBuffer.append(entry.getKey()); + stringBuffer.append(":"); + stringBuffer.append(entry.getValue()); + stringBuffer.append("\t"); + } + return stringBuffer.toString(); + } + +} diff --git a/common_base/src/main/java/com/wss/common/net/response/BaseResponse.java b/common_base/src/main/java/com/wss/common/net/response/BaseResponse.java new file mode 100644 index 0000000..08f2acd --- /dev/null +++ b/common_base/src/main/java/com/wss/common/net/response/BaseResponse.java @@ -0,0 +1,34 @@ +package com.wss.common.net.response; + + +import com.wss.common.base.bean.BaseBean; + +import lombok.Getter; +import lombok.Setter; + +/** + * Describe:响应基类 + * Created by 吴天强 on 2020/5/6. + */ +@Getter +@Setter +public class BaseResponse extends BaseBean { + /** + * 响应码 + */ + private String code; + /** + * 响应message + */ + private String msg; + /** + * 响应数据 + */ + private String data; + + public BaseResponse(String code, String msg, String data) { + this.code = code; + this.msg = msg; + this.data = data; + } +} diff --git a/common_base/src/main/java/com/wss/common/profile/IProfile.java b/common_base/src/main/java/com/wss/common/profile/IProfile.java new file mode 100644 index 0000000..6098aa6 --- /dev/null +++ b/common_base/src/main/java/com/wss/common/profile/IProfile.java @@ -0,0 +1,17 @@ +package com.wss.common.profile; + +/** + * Describe:编译环境相关的配置 + * 该类定义 由APP模块的具体实现类创建不同环境的配置 + * Created by 吴天强 on 2019/5/23. + */ +public interface IProfile { + + /** + * 服务地址 + * + * @return API地址 + */ + String getServiceBase(); + +} diff --git a/common_base/src/main/java/com/wss/common/profile/IProfileFactory.java b/common_base/src/main/java/com/wss/common/profile/IProfileFactory.java new file mode 100644 index 0000000..af8a080 --- /dev/null +++ b/common_base/src/main/java/com/wss/common/profile/IProfileFactory.java @@ -0,0 +1,15 @@ +package com.wss.common.profile; + +/** + * Describe:环境配置工厂接口 + * Created by 吴天强 on 2019/5/23. + */ +public interface IProfileFactory { + + /** + * 创建配置文件 + * + * @return 配置文件 + */ + IProfile createProfile(); +} diff --git a/common_base/src/main/java/com/wss/common/profile/ProfileManager.java b/common_base/src/main/java/com/wss/common/profile/ProfileManager.java new file mode 100644 index 0000000..65895bb --- /dev/null +++ b/common_base/src/main/java/com/wss/common/profile/ProfileManager.java @@ -0,0 +1,41 @@ +package com.wss.common.profile; + +/** + * Describe:编译环境相关的配置 管理类 + * Created by 吴天强 on 2019/5/23. + */ +public class ProfileManager { + + private IProfileFactory mFactory; + private IProfile mProfile; + public static final ProfileManager inst; + + public void factory(IProfileFactory factory) { + this.mFactory = factory; + } + + public static IProfile profile() { + return inst.getProfile(); + } + + private IProfile getProfile() { + if (this.mProfile == null) { + this.mProfile = this.mFactory.createProfile(); + } + return this.mProfile; + } + + private ProfileManager() { + } + + static { + inst = Holder.holder; + } + + private static final class Holder { + private static final ProfileManager holder = new ProfileManager(); + + private Holder() { + } + } +} diff --git a/common_base/src/main/java/com/wss/common/secret/AesUtils.java b/common_base/src/main/java/com/wss/common/secret/AesUtils.java new file mode 100644 index 0000000..9828e5f --- /dev/null +++ b/common_base/src/main/java/com/wss/common/secret/AesUtils.java @@ -0,0 +1,66 @@ +package com.wss.common.secret;//package com.xincheng.common.secret; +// +// +//import com.orhanobut.logger.Logger; +//import com.xincheng.common.constants.Constants; +// +// +//import java.security.Security; +//import java.security.spec.AlgorithmParameterSpec; +//import java.util.Objects; +// +//import javax.crypto.Cipher; +//import javax.crypto.spec.IvParameterSpec; +//import javax.crypto.spec.SecretKeySpec; +// +///** +// * Describe:AES 加解密操作 +// * Created by 吴天强 on 2018-08-03 17:47 +// **/ +//public class AesUtils { +// private static final String CHARSET_NAME = "UTF-8"; +// private static final String AES_NAME = "AES"; +// private static final String ALGORITHM = "AES/CBC/PKCS7Padding"; +// private static final String IV = Constants.AES.AES_IV; +// +// static { +// Security.addProvider(new BouncyCastleProvider()); +// } +// +// /** +// * 加密 +// */ +// public static String encrypt(String content) { +// try { +// Cipher cipher = Cipher.getInstance(ALGORITHM); +// SecretKeySpec keySpec = new SecretKeySpec(Constants.AES.AES_KEY.getBytes(CHARSET_NAME), AES_NAME); +// AlgorithmParameterSpec paramSpec = new IvParameterSpec(IV.getBytes()); +// cipher.init(Cipher.ENCRYPT_MODE, keySpec, paramSpec); +// return ParseSystemUtil.parseByte2HexStr(cipher.doFinal(content.getBytes(CHARSET_NAME))); +// } catch (Exception e) { +// e.printStackTrace(); +// Logger.e("加密失败"); +// } +// return ""; +// } +// +// /** +// * 解密 +// */ +// public static String decrypt(String content) { +// try { +// Cipher cipher = Cipher.getInstance(ALGORITHM); +// SecretKeySpec keySpec = new SecretKeySpec(Constants.AES.AES_KEY.getBytes(CHARSET_NAME), AES_NAME); +// AlgorithmParameterSpec paramSpec = new IvParameterSpec(IV.getBytes()); +// cipher.init(Cipher.DECRYPT_MODE, keySpec, paramSpec); +// return new String(cipher.doFinal(Objects.requireNonNull(ParseSystemUtil.parseHexStr2Byte(content))), CHARSET_NAME); +// } catch (Exception e) { +// e.printStackTrace(); +// Logger.e("解密失败"); +// } +// return ""; +// } +// +//} +// +// diff --git a/common_base/src/main/java/com/wss/common/secret/MD5.java b/common_base/src/main/java/com/wss/common/secret/MD5.java new file mode 100644 index 0000000..e8e9abf --- /dev/null +++ b/common_base/src/main/java/com/wss/common/secret/MD5.java @@ -0,0 +1,64 @@ +package com.wss.common.secret; + + +import org.jetbrains.annotations.NotNull; + +import java.security.MessageDigest; + +/** + * Describe:MD5加密 + * Created by 吴天强 on 2017/10/9. + */ +public class MD5 { + /** + * 生成md5 + * + * @param message 加密字段 + * @return String + */ + @NotNull + public static String getMD5(String message) { + String md5str = ""; + try { + // 1 创建一个提供信息摘要算法的对象,初始化为md5算法对象 + MessageDigest md = MessageDigest.getInstance("MD5"); + // 2 将消息变成byte数组 + byte[] input = message.getBytes(); + // 3 计算后获得字节数组,这就是那128位了 + byte[] buff = md.digest(input); + // 4 把数组每一字节(一个字节占八位)换成16进制连成md5字符串 + md5str = bytesToHex(buff); + + } catch (Exception e) { + e.printStackTrace(); + } + return md5str.toLowerCase(); + } + + /** + * 二进制转十六进制 + * + * @param bytes bytes + * @return String + */ + @NotNull + private static String bytesToHex(@NotNull byte[] bytes) { + StringBuilder md5str = new StringBuilder(); + // 把数组每一字节换成16进制连成md5字符串 + int digital; + for (byte aByte : bytes) { + digital = aByte; + + if (digital < 0) { + digital += 256; + } + if (digital < 16) { + md5str.append("0"); + } + md5str.append(Integer.toHexString(digital)); + } + return md5str.toString().toUpperCase(); + } + + +} diff --git a/common_base/src/main/java/com/wss/common/secret/ParseSystemUtil.java b/common_base/src/main/java/com/wss/common/secret/ParseSystemUtil.java new file mode 100644 index 0000000..bfc5d44 --- /dev/null +++ b/common_base/src/main/java/com/wss/common/secret/ParseSystemUtil.java @@ -0,0 +1,50 @@ +package com.wss.common.secret; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * Describe:16进制与二进制转换类 + * Created by 吴天强 on 2018-08-03 16:31 + **/ +public class ParseSystemUtil { + /** + * 将二进制转换成16进制 + * + * @param buf 数据 + * @return String + */ + @NotNull + public static String parseByte2HexStr(@NotNull byte[] buf) { + StringBuilder sb = new StringBuilder(); + for (byte b : buf) { + String hex = Integer.toHexString(b & 0xFF); + if (hex.length() == 1) { + hex = '0' + hex; + } + sb.append(hex.toUpperCase()); + } + return sb.toString(); + } + + /** + * 将16进制转换为二进制 + * + * @param hexStr 数据 + * @return byte[] + */ + @Nullable + public static byte[] parseHexStr2Byte(@NotNull String hexStr) { + if (hexStr.length() < 1) + return null; + byte[] result = new byte[hexStr.length() / 2]; + for (int i = 0; i < hexStr.length() / 2; i++) { + int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16); + int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16); + result[i] = (byte) (high * 16 + low); + } + return result; + } +} + + diff --git a/common_base/src/main/java/com/wss/common/utils/ARouterUtils.java b/common_base/src/main/java/com/wss/common/utils/ARouterUtils.java index eb0af33..ff5eebb 100644 --- a/common_base/src/main/java/com/wss/common/utils/ARouterUtils.java +++ b/common_base/src/main/java/com/wss/common/utils/ARouterUtils.java @@ -8,10 +8,8 @@ * Describe:ARouter帮助类 * Created by 吴天强 on 2018/11/13. */ - public class ARouterUtils { - /** * 根据path返回Fragment * diff --git a/common_base/src/main/java/com/wss/common/utils/ActivityToActivity.java b/common_base/src/main/java/com/wss/common/utils/ActivityToActivity.java deleted file mode 100644 index 1ceefed..0000000 --- a/common_base/src/main/java/com/wss/common/utils/ActivityToActivity.java +++ /dev/null @@ -1,162 +0,0 @@ -package com.wss.common.utils; - -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.text.TextUtils; - -import com.alibaba.android.arouter.facade.Postcard; -import com.alibaba.android.arouter.launcher.ARouter; -import com.wss.common.activity.WebViewActivity; -import com.wss.common.base.bean.BaseBean; -import com.wss.common.bean.Template; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; - -/** - * Describe:Activity跳转 - * Created by 吴天强 on 2018/10/22. - */ - -public class ActivityToActivity { - - - /** - * 通过模板跳转Activity - * - * @param activity activity - * @param template 模板信息 - */ - @SuppressWarnings("unchecked") - public static void toActivity(Context activity, Template template) { - switch (template.getType()) { - case 0: - //跳转Activity - toActivity(activity, template.getClazz(), template.getParams()); - break; - case 1: - //跳转其他业务模块 - toActivity(template.getUrl(), template.getParams()); - break; - case 2: - //跳转普通WebView - toWebView(activity, template.getUrl()); - break; - } - } - - /** - * 跳转普通WebView - * - * @param activity activity - * @param url 目标Url - */ - public static void toWebView(Context activity, String url) { - WebViewActivity.actionStart(activity, url); - } - - - /** - * 普通Activity之间跳转 - * - * @param activity activity - * @param clazz 目标activity - */ - public static void toActivity(Context activity, Class clazz) { - toActivity(activity, clazz, null); - } - - /** - * 普通Activity之间跳转 - * - * @param activity activity - * @param clazz 目标activity - * @param params 参数 - */ - public static void toActivity(Context activity, Class clazz, - Map params) { - Intent intent = new Intent(activity, clazz); - if (params != null) { - for (Map.Entry entry : params.entrySet()) { - String key = entry.getKey(); - Object value = params.get(key); - if (value instanceof String) { - intent.putExtra(key, (String) value); - } else if (value instanceof Boolean) { - intent.putExtra(key, (boolean) value); - } else if (value instanceof Integer) { - intent.putExtra(key, (int) value); - } else if (value instanceof Float) { - intent.putExtra(key, (float) value); - } else if (value instanceof Double) { - intent.putExtra(key, (double) value); - } else if (value instanceof Long) { - intent.putExtra(key, (long) value); - } else if (value instanceof Short) { - intent.putExtra(key, (short) value); - } else if (value instanceof BaseBean) { - intent.putExtra(key, (BaseBean) value); - } else if (value instanceof ArrayList) { - intent.putExtra(key, (ArrayList) value); - } else if (value instanceof HashMap) { - intent.putExtra(key, (HashMap) value); - } - } - } - activity.startActivity(intent); - } - - - /** - * ARouter跳转Activity - * - * @param url 目标Activity Url - */ - public static void toActivity(String url) { - toActivity(url, null); - } - - /** - * ARouter跳转Activity - * - * @param url 目标Activity Url - * @param params 参数 - */ - public static void toActivity(String url, Map params) { - if (TextUtils.isEmpty(url)) { - return; - } - Postcard postcard = ARouter.getInstance() - .build(url); - if (params != null) { - for (Map.Entry entry : params.entrySet()) { - String key = entry.getKey(); - Object value = params.get(key); - if (value instanceof String) { - postcard.withString(key, (String) value); - } else if (value instanceof Boolean) { - postcard.withBoolean(key, (boolean) value); - } else if (value instanceof Integer) { - postcard.withInt(key, (int) value); - } else if (value instanceof Float) { - postcard.withFloat(key, (float) value); - } else if (value instanceof Double) { - postcard.withDouble(key, (double) value); - } else if (value instanceof Long) { - postcard.withLong(key, (long) value); - } else if (value instanceof Short) { - postcard.withShort(key, (short) value); - } else if (value instanceof BaseBean) { - postcard.withSerializable(key, (BaseBean) value); - } else if (value instanceof ArrayList) { - postcard.withSerializable(key, (ArrayList) value); - } else if (value instanceof HashMap) { - postcard.withSerializable(key, (HashMap) value); - } - } - } - postcard.navigation(); - } -} diff --git a/common_base/src/main/java/com/wss/common/utils/BeanCopyUtils.java b/common_base/src/main/java/com/wss/common/utils/BeanCopyUtils.java index 8020fc7..7cbaf2f 100644 --- a/common_base/src/main/java/com/wss/common/utils/BeanCopyUtils.java +++ b/common_base/src/main/java/com/wss/common/utils/BeanCopyUtils.java @@ -42,4 +42,7 @@ public static T copy(T src) { } return dist; } + + + } \ No newline at end of file diff --git a/common_base/src/main/java/com/wss/common/utils/CacheUtils.java b/common_base/src/main/java/com/wss/common/utils/CacheUtils.java index 426841e..bfe02b3 100644 --- a/common_base/src/main/java/com/wss/common/utils/CacheUtils.java +++ b/common_base/src/main/java/com/wss/common/utils/CacheUtils.java @@ -8,6 +8,9 @@ import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.json.JSONArray; import org.json.JSONObject; @@ -40,35 +43,40 @@ * Describe:缓存工具类。。。能缓存普通的字符串、JsonObject、JsonArray、 Bitmap、Drawable、序列化的java对象,和 byte数据。 * Created by 吴天强 on 2017/10/9. */ - public class CacheUtils { - public static final int TIME_MINUTE = 60; - public static final int TIME_HOUR = 60 * 60; - public static final int TIME_DAY = TIME_HOUR * 24; + private static final int TIME_MINUTE = 60; + private static final int TIME_HOUR = 60 * TIME_MINUTE; + private static final int TIME_DAY = TIME_HOUR * 24; + private static final int MAX_TIME_OUT = 90 * TIME_DAY;//最大缓存90天 private static final int MAX_SIZE = 1000 * 1000 * 50; // 50 mb private static final int MAX_COUNT = Integer.MAX_VALUE; // 不限制存放数据的数量 private static Map mInstanceMap = new HashMap<>(); private ACacheManager mCache; + @NotNull public static CacheUtils get(Context ctx) { return get(ctx, CacheUtils.class.getSimpleName()); } - public static CacheUtils get(Context ctx, String cacheName) { + @NotNull + public static CacheUtils get(@NotNull Context ctx, String cacheName) { File f = new File(ctx.getCacheDir(), cacheName); return get(f, MAX_SIZE, MAX_COUNT); } + @NotNull public static CacheUtils get(File cacheDir) { return get(cacheDir, MAX_SIZE, MAX_COUNT); } - public static CacheUtils get(Context ctx, long max_zise, int max_count) { + @NotNull + public static CacheUtils get(@NotNull Context ctx, long max_zise, int max_count) { File f = new File(ctx.getCacheDir(), CacheUtils.class.getSimpleName()); return get(f, max_zise, max_count); } - public static CacheUtils get(File cacheDir, long max_zise, int max_count) { + @NotNull + public static CacheUtils get(@NotNull File cacheDir, long max_zise, int max_count) { CacheUtils manager = mInstanceMap.get(cacheDir.getAbsoluteFile() + myPid()); if (manager == null) { manager = new CacheUtils(cacheDir, max_zise, max_count); @@ -77,11 +85,12 @@ public static CacheUtils get(File cacheDir, long max_zise, int max_count) { return manager; } + @NotNull private static String myPid() { return "_" + android.os.Process.myPid(); } - private CacheUtils(File cacheDir, long max_size, int max_count) { + private CacheUtils(@NotNull File cacheDir, long max_size, int max_count) { if (!cacheDir.exists() && !cacheDir.mkdirs()) { throw new RuntimeException("can't make dirs in " + cacheDir.getAbsolutePath()); @@ -117,6 +126,16 @@ public void close() throws IOException { // ============ String数据 读写 ============== // ======================================= + /** + * 保存 String数据 到 缓存中 + * + * @param key 保存的key + * @param value 保存的String数据 + */ + public void put(String key, boolean value) { + put(key, String.valueOf(value)); + } + /** * 保存 String数据 到 缓存中 * @@ -124,11 +143,23 @@ public void close() throws IOException { * @param value 保存的String数据 */ public void put(String key, String value) { + put(key, value, MAX_TIME_OUT); + } + + /** + * 保存 String数据 到 缓存中 + * + * @param key 保存的key + * @param value 保存的String数据 + * @param saveTime 保存的时间,单位:秒 + */ + public void put(String key, String value, int saveTime) { + String values = Utils.newStringWithDateInfo(saveTime, value); File file = mCache.newFile(key); BufferedWriter out = null; try { out = new BufferedWriter(new FileWriter(file), 1024); - out.write(value); + out.write(values); } catch (IOException e) { e.printStackTrace(); } finally { @@ -144,17 +175,6 @@ public void put(String key, String value) { } } - /** - * 保存 String数据 到 缓存中 - * - * @param key 保存的key - * @param value 保存的String数据 - * @param saveTime 保存的时间,单位:秒 - */ - public void put(String key, String value, int saveTime) { - put(key, Utils.newStringWithDateInfo(saveTime, value)); - } - /** * 读取 String数据 * @@ -196,6 +216,9 @@ public String getAsString(String key) { } } + public boolean getAsBoolean(String key) { + return Boolean.parseBoolean(getAsString(key)); + } // ======================================= // ============= JSONObject 数据 读写 ============== // ======================================= @@ -206,7 +229,7 @@ public String getAsString(String key) { * @param key 保存的key * @param value 保存的JSON数据 */ - public void put(String key, JSONObject value) { + public void put(String key, @NotNull JSONObject value) { put(key, value.toString()); } @@ -217,7 +240,7 @@ public void put(String key, JSONObject value) { * @param value 保存的JSONObject数据 * @param saveTime 保存的时间,单位:秒 */ - public void put(String key, JSONObject value, int saveTime) { + public void put(String key, @NotNull JSONObject value, int saveTime) { put(key, value.toString(), saveTime); } @@ -248,7 +271,7 @@ public JSONObject getAsJSONObject(String key) { * @param key 保存的key * @param value 保存的JSONArray数据 */ - public void put(String key, JSONArray value) { + public void put(String key, @NotNull JSONArray value) { put(key, value.toString()); } @@ -259,7 +282,7 @@ public void put(String key, JSONArray value) { * @param value 保存的JSONArray数据 * @param saveTime 保存的时间,单位:秒 */ - public void put(String key, JSONArray value, int saveTime) { + public void put(String key, @NotNull JSONArray value, int saveTime) { put(key, value.toString(), saveTime); } @@ -388,13 +411,13 @@ public byte[] getAsBinary(String key) { // ======================================= /** - * 保存 Serializable数据 到 缓存中 + * 保存 Serializable数据 到 缓存中 默认保存90天 * * @param key 保存的key * @param value 保存的value */ public void put(String key, Serializable value) { - put(key, value, -1); + put(key, value, MAX_TIME_OUT); } /** @@ -581,8 +604,7 @@ public class ACacheManager { private final AtomicInteger cacheCount; private final long sizeLimit; private final int countLimit; - private final Map lastUsageDates = Collections - .synchronizedMap(new HashMap()); + private final Map lastUsageDates = Collections.synchronizedMap(new HashMap<>()); protected File cacheDir; private ACacheManager(File cacheDir, long sizeLimit, int countLimit) { @@ -598,22 +620,19 @@ private ACacheManager(File cacheDir, long sizeLimit, int countLimit) { * 计算 cacheSize和cacheCount */ private void calculateCacheSizeAndCacheCount() { - new Thread(new Runnable() { - @Override - public void run() { - int size = 0; - int count = 0; - File[] cachedFiles = cacheDir.listFiles(); - if (cachedFiles != null) { - for (File cachedFile : cachedFiles) { - size += calculateSize(cachedFile); - count += 1; - lastUsageDates.put(cachedFile, - cachedFile.lastModified()); - } - cacheSize.set(size); - cacheCount.set(count); + new Thread(() -> { + int size = 0; + int count = 0; + File[] cachedFiles = cacheDir.listFiles(); + if (cachedFiles != null) { + for (File cachedFile : cachedFiles) { + size += calculateSize(cachedFile); + count += 1; + lastUsageDates.put(cachedFile, + cachedFile.lastModified()); } + cacheSize.set(size); + cacheCount.set(count); } }).start(); } @@ -636,21 +655,24 @@ private void put(File file) { } cacheSize.addAndGet(valueSize); - Long currentTime = System.currentTimeMillis(); + long currentTime = System.currentTimeMillis(); file.setLastModified(currentTime); lastUsageDates.put(file, currentTime); } + @NotNull private File get(String key) { File file = newFile(key); - Long currentTime = System.currentTimeMillis(); + long currentTime = System.currentTimeMillis(); file.setLastModified(currentTime); lastUsageDates.put(file, currentTime); return file; } - private File newFile(String key) { + @NotNull + @Contract("_ -> new") + private File newFile(@NotNull String key) { return new File(cacheDir, key.hashCode() + ""); } @@ -705,7 +727,7 @@ private long removeNext() { return fileSize; } - private long calculateSize(File file) { + private long calculateSize(@NotNull File file) { return file.length(); } } @@ -723,7 +745,7 @@ private static class Utils { * @param str * @return true:到期了 false:还没有到期 */ - private static boolean isDue(String str) { + private static boolean isDue(@NotNull String str) { return isDue(str.getBytes()); } @@ -750,11 +772,13 @@ private static boolean isDue(byte[] data) { return false; } + @NotNull private static String newStringWithDateInfo(int second, String strInfo) { return createDateInfo(second) + strInfo; } - private static byte[] newByteArrayWithDateInfo(int second, byte[] data2) { + @NotNull + private static byte[] newByteArrayWithDateInfo(int second, @NotNull byte[] data2) { byte[] data1 = createDateInfo(second).getBytes(); byte[] retdata = new byte[data1.length + data2.length]; System.arraycopy(data1, 0, retdata, 0, data1.length); @@ -762,6 +786,7 @@ private static byte[] newByteArrayWithDateInfo(int second, byte[] data2) { return retdata; } + @Contract("null -> null") private static String clearDateInfo(String strInfo) { if (strInfo != null && hasDateInfo(strInfo.getBytes())) { strInfo = strInfo.substring(strInfo.indexOf(mSeparator) + 1, @@ -778,11 +803,13 @@ private static byte[] clearDateInfo(byte[] data) { return data; } + @Contract(value = "null -> false", pure = true) private static boolean hasDateInfo(byte[] data) { return data != null && data.length > 15 && data[13] == '-' && indexOf(data, mSeparator) > 14; } + @Nullable private static String[] getDateInfoFromDate(byte[] data) { if (hasDateInfo(data)) { String saveDate = new String(copyOfRange(data, 0, 13)); @@ -793,6 +820,7 @@ private static String[] getDateInfoFromDate(byte[] data) { return null; } + @Contract(pure = true) private static int indexOf(byte[] data, char c) { for (int i = 0; i < data.length; i++) { if (data[i] == c) { @@ -802,6 +830,7 @@ private static int indexOf(byte[] data, char c) { return -1; } + @NotNull private static byte[] copyOfRange(byte[] original, int from, int to) { int newLength = to - from; if (newLength < 0) @@ -815,9 +844,9 @@ private static byte[] copyOfRange(byte[] original, int from, int to) { private static final char mSeparator = ' '; private static String createDateInfo(int second) { - String currentTime = System.currentTimeMillis() + ""; + StringBuilder currentTime = new StringBuilder(System.currentTimeMillis() + ""); while (currentTime.length() < 13) { - currentTime = "0" + currentTime; + currentTime.insert(0, "0"); } return currentTime + "-" + second + mSeparator; } @@ -825,6 +854,7 @@ private static String createDateInfo(int second) { /* * Bitmap → byte[] */ + @Contract("null -> null") private static byte[] Bitmap2Bytes(Bitmap bm) { if (bm == null) { return null; @@ -837,7 +867,8 @@ private static byte[] Bitmap2Bytes(Bitmap bm) { /* * byte[] → Bitmap */ - private static Bitmap Bytes2Bimap(byte[] b) { + @Nullable + private static Bitmap Bytes2Bimap(@NotNull byte[] b) { if (b.length == 0) { return null; } @@ -847,6 +878,7 @@ private static Bitmap Bytes2Bimap(byte[] b) { /* * Drawable → Bitmap */ + @Contract("null -> null") private static Bitmap drawable2Bitmap(Drawable drawable) { if (drawable == null) { return null; @@ -870,6 +902,7 @@ private static Bitmap drawable2Bitmap(Drawable drawable) { /* * Bitmap → Drawable */ + @Contract("null -> null") @SuppressWarnings("deprecation") private static Drawable bitmap2Drawable(Bitmap bm) { if (bm == null) { diff --git a/common_base/src/main/java/com/wss/common/utils/DateUtils.java b/common_base/src/main/java/com/wss/common/utils/DateUtils.java index 73e5c6d..fca8271 100644 --- a/common_base/src/main/java/com/wss/common/utils/DateUtils.java +++ b/common_base/src/main/java/com/wss/common/utils/DateUtils.java @@ -2,8 +2,11 @@ import android.annotation.SuppressLint; import android.text.TextUtils; +import android.util.Log; -import com.wss.common.constants.Constants; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.text.ParseException; import java.text.SimpleDateFormat; @@ -18,6 +21,15 @@ @SuppressLint("SimpleDateFormat") public class DateUtils { + public static final String DATE_FORMAT = "yyyyMMddHH"; + public static final String DATE_FORMAT_SLASH = "yyyy/MM/dd"; + public static final String DATE_FORMAT_LINE = "yyyy-MM-dd"; + public static final String DATE_FORMAT_DEFAULT = DATE_FORMAT_SLASH + " HH:mm:ss"; + private static final int SECOND = 60; + private static final int DAY = 60; + private static final int MOUTH = 60; + + /** * 获取当前时间戳 * @@ -33,9 +45,35 @@ public static long getCurrentTimeStamp() { * @return String */ public static String getCurrentDateStr() { - return getFormatDate(getCurrentTimeStamp(), Constants.DATE_FORMAT_LINE); + return getFormatDate(getCurrentTimeStamp(), DATE_FORMAT_LINE); } + /** + * 获取格式化的当前系统时间 + * + * @return String + */ + public static String getCurrentDateStr(String pattern) { + return getFormatDate(getCurrentTimeStamp(), pattern); + } + + /** + * 获取格式化时间 + * + * @param date date + * @param pattern 格式化格式(默认yyyy-MM-dd HH:mm:ss) + */ + @NotNull + public static String getFormatDate(Date date, String pattern) { + if (date == null) { + return ""; + } + if (!ValidUtils.isValid(pattern)) { + pattern = DATE_FORMAT_DEFAULT; + } + SimpleDateFormat format = new SimpleDateFormat(pattern); + return format.format(date); + } /** * 获取格式化时间 @@ -49,7 +87,7 @@ public static String getFormatDate(long timeStamp, String pattern) { timeStamp *= 1000; } if (TextUtils.isEmpty(pattern)) { - pattern = Constants.DATE_FORMAT_DEFAULT; + pattern = DATE_FORMAT_DEFAULT; } SimpleDateFormat format = new SimpleDateFormat(pattern); format.setTimeZone(TimeZone.getDefault()); @@ -69,12 +107,18 @@ public static String getFormatDate(String stringDate, String pattern) { return ""; } String parentPattern; - if (stringDate.length() == 16) { - parentPattern = "yyyy-MM-dd HH:mm"; - } else if (stringDate.length() == 19) { - parentPattern = "yyyy-MM-dd HH:mm:ss"; - } else { - return stringDate; + switch (stringDate.length()) { + case 10: + parentPattern = "yyyy-MM-dd"; + break; + case 16: + parentPattern = "yyyy-MM-dd HH:mm"; + break; + case 19: + parentPattern = "yyyy-MM-dd HH:mm:ss"; + break; + default: + return stringDate; } SimpleDateFormat sdf1 = new SimpleDateFormat(pattern); try { @@ -85,40 +129,26 @@ public static String getFormatDate(String stringDate, String pattern) { return stringDate; } - /** - * 获取系统的时间 - * - * @return String - */ - public static String getCurrentTimeStr() { - SimpleDateFormat fort = new SimpleDateFormat("HH:mm:ss"); - fort.setTimeZone(TimeZone.getTimeZone("GMT+8:00")); - return fort.format(getCurrentTimeStamp()); - } /** - * 获取当前时间的下一天/ 前一天时间 - * - * @param time time - * @param day 正数为以后 负数为以前 - * @return + * 日期转日历 */ - public static long getNextDayTimeStamp(long time, int day) { - long timeStamp = 0; - Calendar cal = Calendar.getInstance(); - Date date = new Date(time); - SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); + @NotNull + public static Calendar getFormatDate(String stringDate) { + SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT_LINE); + Calendar calendar = Calendar.getInstance(); try { - cal.setTime(date); - cal.add(Calendar.DATE, 1); - timeStamp = getStringToTimeStamp(sdf.format(cal.getTime())); - } catch (Exception e) { + Date date = sdf.parse(stringDate); + if (date != null) { + calendar.setTime(date); + } + } catch (ParseException e) { e.printStackTrace(); - return timeStamp; } - return timeStamp; + return calendar; } + /** * 根据字符串时间获取时间戳 * @@ -134,43 +164,15 @@ public static long getStringToTimeStamp(String stringDate) { } try { date = simpleDateFormat.parse(stringDate); - timeStamp = date.getTime(); + if (date != null) { + timeStamp = date.getTime(); + } } catch (ParseException e) { return timeStamp; } return timeStamp; } - /** - * 根据当前时间获取问候语 - * - * @return 问候语 - */ - public static String getTimeTransformation() { - Calendar calendar = Calendar.getInstance(); - int hour = calendar.get(Calendar.HOUR_OF_DAY); - if (hour >= 0 && hour < 5) { - return "凌晨"; - } else if (hour >= 5 && hour < 7) { - return "清晨"; - } else if (hour >= 7 && hour < 9) { - return "早上"; - } else if (hour >= 9 && hour < 12) { - return "上午"; - } else if (hour >= 12 && hour < 14) { - return "中午"; - } else if (hour >= 14 && hour < 17) { - return "下午"; - } else if (hour >= 17 && hour < 19) { - return "傍晚"; - } else if (hour >= 19 && hour < 21) { - return "晚上"; - } else if (hour >= 21 && hour < 24) { - return "深夜"; - } - return ""; - } - /** * 时间转换 * @@ -179,19 +181,95 @@ public static String getTimeTransformation() { public static String dateTransformation(long date) { long difference = (getCurrentTimeStamp() / 1000) - (date / 1000); if (difference > 0) { - if (difference < 60 * 60) { + if (difference < SECOND * SECOND) { + long temp = difference / 60; + if (temp < 1) { + return "1分钟前"; + } return difference / 60 + "分钟前"; - } else if (difference < 24 * 60 * 60) { + } else if (difference < DAY * SECOND * SECOND) { return (int) (difference / 60 / 60) + "小时前"; - } else if (difference < 30 * 24 * 60 * 60) { + } else if (difference < MOUTH * DAY * SECOND * SECOND) { return (int) (difference / 60 / 60 / 24) + "日前"; } else { - return getFormatDate(date, Constants.DATE_FORMAT_SLASH); + return getFormatDate(date, DATE_FORMAT_SLASH); } } else { - return getFormatDate(date, Constants.DATE_FORMAT_SLASH); + return getFormatDate(date, DATE_FORMAT_SLASH); } } + + /** + * 格式化时间 + * + * @param dateStr 5月21日 17:00 + * @return String + */ + @Nullable + public static String getMessageDate(long dateStr) { + try { + Date date = new Date(); + date.setTime(dateStr); + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + return String.format("%s月%s日%s:%s", (calendar.get(Calendar.MONTH) + 1), + calendar.get(Calendar.DAY_OF_MONTH), calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE)); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + /** + * 根据月份返回中文 + * + * @param month 月份 + * @return 中文 + */ + @NotNull + @Contract(pure = true) + public static String getDateFormatMonth(int month) { + switch (month) { + case 1: + return "一月"; + case 2: + return "二月"; + case 3: + return "三月"; + case 4: + return "四月"; + case 5: + return "五月"; + case 6: + return "六月"; + case 7: + return "七月"; + case 8: + return "八月"; + case 9: + return "九月"; + case 10: + return "十月"; + case 11: + return "十一月"; + case 12: + return "十二月"; + default: + return ""; + } + } + + /** + * 计算两个时间的时间差 + * + * @param time 时间 + * @return 差值 + */ + public static long getTimeDifference(long time) { + long difference = System.currentTimeMillis() - time; + Log.e("时间差:", difference + "|" + difference / 1000); + return difference / 1000; + } } diff --git a/common_base/src/main/java/com/wss/common/utils/EventBusUtils.java b/common_base/src/main/java/com/wss/common/utils/EventBusUtils.java index 001b5ca..3a89779 100644 --- a/common_base/src/main/java/com/wss/common/utils/EventBusUtils.java +++ b/common_base/src/main/java/com/wss/common/utils/EventBusUtils.java @@ -1,14 +1,14 @@ package com.wss.common.utils; + import com.wss.common.bean.Event; import org.greenrobot.eventbus.EventBus; /** - * Describe:EventBusUtils + * Describe:EventBus帮助类 * Created by 吴天强 on 2018/10/22. */ - public class EventBusUtils { /** @@ -31,5 +31,18 @@ public static void unregister(Object subscriber) { public static void sendEvent(Event event) { EventBus.getDefault().post(event); } - //... + + /** + * 发送普通事件 + */ + public static void sendEvent(String action) { + sendEvent(new Event(action)); + } + + /** + * 发送普通事件 + */ + public static void sendEvent(String action, Object data) { + sendEvent(new Event<>(action, data)); + } } diff --git a/common_base/src/main/java/com/wss/common/utils/FileUtils.java b/common_base/src/main/java/com/wss/common/utils/FileUtils.java index 5b35a8d..ef23def 100644 --- a/common_base/src/main/java/com/wss/common/utils/FileUtils.java +++ b/common_base/src/main/java/com/wss/common/utils/FileUtils.java @@ -1,26 +1,36 @@ package com.wss.common.utils; +import android.annotation.SuppressLint; +import android.app.Activity; +import android.content.ContentUris; import android.content.Context; +import android.database.Cursor; import android.net.Uri; import android.os.Build; import android.os.Environment; -import android.support.annotation.Nullable; -import android.support.v4.content.FileProvider; +import android.provider.DocumentsContract; +import android.provider.MediaStore; import com.orhanobut.logger.Logger; import com.wss.common.base.BaseApplication; +import org.jetbrains.annotations.NotNull; + import java.io.File; +import java.text.SimpleDateFormat; +import java.util.Calendar; import java.util.Collections; import java.util.LinkedList; +import androidx.annotation.Nullable; +import androidx.core.content.FileProvider; + /** * Describe:文件帮助类 * Created by 吴天强 on 2018/10/25. */ - public class FileUtils { - public static final String APPS_ROOT_DIR = getExternalStorePath() + File.separator + BaseApplication.getApplication().getPackageName(); + public static final String APPS_ROOT_DIR = getExternalStorePath() + File.separator + BaseApplication.i().getPackageName(); public static final String IMAGE_PATH = APPS_ROOT_DIR + "/Image"; public static final String TEMP_PATH = APPS_ROOT_DIR + "/Temp"; public static final String APP_CRASH_PATH = APPS_ROOT_DIR + "/AppCrash"; @@ -49,6 +59,7 @@ public static boolean isExistExternalStore() { return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED); } + @org.jetbrains.annotations.Nullable private static File create(String path) { if (!isExistExternalStore()) { Logger.e("储存卡已拔出"); @@ -56,7 +67,7 @@ private static File create(String path) { } File directory = new File(path); if (!directory.exists()) { - directory.mkdir(); + directory.mkdirs(); } return directory; } @@ -67,8 +78,9 @@ private static File create(String path) { * @return File */ @Nullable - public static File getImagePath() { - return create(IMAGE_PATH); + public static String getImagePath() { + File file = create(IMAGE_PATH); + return ValidUtils.isValid(file) ? file.getAbsolutePath() : ""; } /** @@ -77,8 +89,9 @@ public static File getImagePath() { * @return File */ @Nullable - public static File getTempPath() { - return create(TEMP_PATH); + public static String getTempPath() { + File file = create(TEMP_PATH); + return ValidUtils.isValid(file) ? file.getAbsolutePath() : ""; } /** @@ -86,8 +99,10 @@ public static File getTempPath() { * * @return File */ - public static File getAppCrashPath() { - return create(APP_CRASH_PATH); + @NotNull + public static String getAppCrashPath() { + File file = create(APP_CRASH_PATH); + return ValidUtils.isValid(file) ? file.getAbsolutePath() : ""; } /** @@ -95,8 +110,10 @@ public static File getAppCrashPath() { * * @return File */ - public static File getFilePath() { - return create(FILE_PATH); + @NotNull + public static String getFilePath() { + File file = create(FILE_PATH); + return ValidUtils.isValid(file) ? file.getAbsolutePath() : ""; } /** @@ -116,6 +133,108 @@ public static Uri getUriForFile(Context context, File file) { return fileUri; } + /** + * URI转文件 + * + * @param context context + * @param uri uri + * @return File + */ + @org.jetbrains.annotations.Nullable + public static String uriToFile(@NotNull Activity context, @NotNull Uri uri) { + if ("content".equalsIgnoreCase(uri.getScheme())) { + String filePath = null; + if (DocumentsContract.isDocumentUri(context, uri)) { + // 如果是document类型的 uri, 则通过document id来进行处理 + String documentId = DocumentsContract.getDocumentId(uri); + if (isMediaDocument(uri)) { // MediaProvider + // 使用':'分割 + String type = documentId.split(":")[0]; + String id = documentId.split(":")[1]; + + String selection = MediaStore.Images.Media._ID + "=?"; + String[] selectionArgs = {id}; + Uri contentUri = null; + if ("image".equals(type)) { + contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; + } else if ("video".equals(type)) { + contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; + } else if ("audio".equals(type)) { + contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; + } + + filePath = getDataColumn(context, contentUri, selection, selectionArgs); + } else if (isDownloadsDocument(uri)) { // DownloadsProvider + Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.parseLong(documentId)); + filePath = getDataColumn(context, contentUri, null, null); + } else if (isExternalStorageDocument(uri)) { + // ExternalStorageProvider + final String docId = DocumentsContract.getDocumentId(uri); + final String[] split = docId.split(":"); + final String type = split[0]; + if ("primary".equalsIgnoreCase(type)) { + filePath = Environment.getExternalStorageDirectory() + "/" + split[1]; + } + } //Log.e("路径错误"); + + } else if ("content".equalsIgnoreCase(uri.getScheme())) { + // 如果是 content 类型的 Uri + filePath = getDataColumn(context, uri, null, null); + } else if ("file".equals(uri.getScheme())) { + // 如果是 file 类型的 Uri,直接获取图片对应的路径 + filePath = uri.getPath(); + } + return filePath; + } else if ("file".equalsIgnoreCase(uri.getScheme())) { + return uri.getPath(); + } + return ""; + } + + + /** + * 获取数据库表中的 _data 列,即返回Uri对应的文件路径 + * + * @return + */ + private static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) { + String path = null; + + String[] projection = new String[]{MediaStore.Images.Media.DATA}; + Cursor cursor = null; + try { + cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null); + if (cursor != null && cursor.moveToFirst()) { + int columnIndex = cursor.getColumnIndexOrThrow(projection[0]); + path = cursor.getString(columnIndex); + } + } catch (Exception e) { + if (cursor != null) { + cursor.close(); + } + } + return path; + } + + /** + * @param uri the Uri to check + * @return Whether the Uri authority is MediaProvider + */ + private static boolean isMediaDocument(@NotNull Uri uri) { + return "com.android.providers.media.documents".equals(uri.getAuthority()); + } + + private static boolean isExternalStorageDocument(@NotNull Uri uri) { + return "com.android.externalstorage.documents".equals(uri.getAuthority()); + } + + /** + * @param uri the Uri to check + * @return Whether the Uri authority is DownloadsProvider + */ + private static boolean isDownloadsDocument(@NotNull Uri uri) { + return "com.android.providers.downloads.documents".equals(uri.getAuthority()); + } /** * 获取目录下的文件列表 @@ -159,4 +278,15 @@ public static void deleteFile(String filesName) { } } + /** + * 读取文件的最后修改时间的方法 + */ + public static String getFileLastModifiedTime(File f) { + Calendar cal = Calendar.getInstance(); + long time = f.lastModified(); + @SuppressLint("SimpleDateFormat") + SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + cal.setTimeInMillis(time); + return formatter.format(cal.getTime()); + } } diff --git a/common_base/src/main/java/com/wss/common/utils/GroupUtils.java b/common_base/src/main/java/com/wss/common/utils/GroupUtils.java index b8fc9de..4ad3bfc 100644 --- a/common_base/src/main/java/com/wss/common/utils/GroupUtils.java +++ b/common_base/src/main/java/com/wss/common/utils/GroupUtils.java @@ -1,6 +1,5 @@ package com.wss.common.utils; -import android.support.annotation.Nullable; import android.text.TextUtils; import android.util.Log; @@ -12,20 +11,32 @@ import java.util.List; import java.util.Map; +import androidx.annotation.Nullable; + /** * Describe:Lis分组 * Created by 吴天强 on 2018-05-31 08:45 **/ public class GroupUtils { - public static final String TAG = GroupUtils.class.getSimpleName(); + private static final String TAG = GroupUtils.class.getSimpleName(); /** * 分组依据接口,用于集合分组时,获取分组依据 + * + * @param */ public interface GroupBy { T groupBy(Object obj); } + /** + * 待分组的集合 + * 分组依据 + * + * @param + * @param + * @return 分组数据 + */ public static , D> Map> group(Collection colls, GroupBy gb) { if (colls == null || colls.isEmpty()) { Log.e(TAG, "分组集合不能为空"); diff --git a/common_base/src/main/java/com/wss/common/utils/ImageUtils.java b/common_base/src/main/java/com/wss/common/utils/ImageUtils.java index 22398f2..30e3178 100644 --- a/common_base/src/main/java/com/wss/common/utils/ImageUtils.java +++ b/common_base/src/main/java/com/wss/common/utils/ImageUtils.java @@ -1,72 +1,260 @@ package com.wss.common.utils; +import android.app.Activity; +import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; +import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Matrix; -import android.graphics.drawable.ColorDrawable; import android.media.ExifInterface; -import android.support.annotation.Nullable; -import android.text.TextUtils; +import android.net.Uri; +import android.os.Environment; +import android.provider.MediaStore; +import android.view.View; import android.widget.ImageView; +import android.widget.ScrollView; import com.bigkoo.convenientbanner.ConvenientBanner; import com.bigkoo.convenientbanner.listener.OnItemClickListener; import com.bumptech.glide.Glide; +import com.bumptech.glide.load.resource.bitmap.RoundedCorners; import com.bumptech.glide.request.RequestOptions; import com.wss.common.adapter.BannerImgAdapter; import com.wss.common.base.R; import com.wss.common.manage.BlurTransformation; +import com.wss.common.manage.GlideRoundTransform; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + +import java.io.ByteArrayOutputStream; import java.io.File; +import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.List; +import androidx.annotation.DrawableRes; +import androidx.annotation.Nullable; + /** * Describe:图片工具类 * Created by 吴天强 on 2018/10/17. */ - public class ImageUtils { + /** + * 加载手机图片 + * file + * + * @param imageView imageView + * @param file file + */ + public static void loadImage(@NotNull ImageView imageView, File file) { + loadImage(imageView, file, R.color.color_999999); + } + + /** + * 加载手机图片 + * + * @param imageView imageView + * @param file file + * @param error 加载失败占位图 + */ + public static void loadImage(@NotNull ImageView imageView, File file, @DrawableRes int error) { + Glide.with(imageView.getContext()) + .load(file) + .apply(new RequestOptions() + .placeholder(R.color.color_999999) + .error(error) + .fallback(error)) + .into(imageView); + } + + /** + * 加载本地图片 + * + * @param drawable drawable + * @param imageView imageView + */ + public static void loadImage(@NotNull ImageView imageView, @DrawableRes int drawable) { + loadImage(imageView, drawable, R.color.color_999999); + } + + /** + * 加载本地图片 + * + * @param drawable drawable + * @param imageView imageView + * @param error 加载失败占位图 + */ + public static void loadImage(@NotNull ImageView imageView, int drawable, @DrawableRes int error) { + Glide.with(imageView.getContext()) + .load(drawable) + .apply(new RequestOptions() + .placeholder(R.color.color_999999) + .error(error) + .fallback(error)) + .into(imageView); + } + /** * 加载网络图片 * * @param url url * @param imageView imageView - * @param imageView transformation 转换器 */ public static void loadImage(ImageView imageView, String url) { - if (TextUtils.isEmpty(url)) { - return; - } + loadImage(imageView, url, R.color.color_999999); + } + + /** + * 加载网络图片 + * + * @param url url + * @param imageView imageView + * @param error 加载失败占位图 + */ + public static void loadImage(@NotNull ImageView imageView, String url, @DrawableRes int error) { Glide.with(imageView.getContext()) .load(url) .apply(new RequestOptions() - .placeholder(R.drawable.ic_loading_image) - .error(new ColorDrawable(Color.WHITE)) - .fallback(new ColorDrawable(Color.RED))) + .placeholder(R.color.color_999999) + .error(error) + .fallback(error)) .into(imageView); } /** - * 加载圆形 + * 加载圆形图片 * * @param url url * @param imageView imageView */ public static void loadImageCircle(ImageView imageView, String url) { - if (TextUtils.isEmpty(url)) { - return; - } + loadImageCircle(imageView, url, R.color.color_999999, R.color.color_999999); + } + + /** + * 加载圆形图片 + * + * @param url url + * @param imageView imageView + * @param error 加载失败占位图 + */ + public static void loadImageCircle(@NotNull ImageView imageView, String url, @DrawableRes int placeholder, @DrawableRes int error) { Glide.with(imageView.getContext()) .load(url) .apply(RequestOptions.circleCropTransform() - .placeholder(R.drawable.ic_loading_image) - .error(new ColorDrawable(Color.WHITE)) - .fallback(new ColorDrawable(Color.RED))) + .placeholder(placeholder) + .error(error) + .fallback(error)) + .into(imageView); + } + + + /** + * 加载圆角图片 + * + * @param imageView ImageView + * @param url URL + * @param dp 圆角角度 + */ + public static void loadImageCircleBead(@NotNull ImageView imageView, String url, int dp) { + loadImageCircleBead(imageView, url, dp, R.color.color_999999); + } + + /** + * 加载圆角图片 + * + * @param imageView ImageView + * @param url URL + * @param dp 圆角角度 + * @param error 加载失败占位图 + */ + public static void loadImageCircleBead(@NotNull ImageView imageView, String url, int dp, @DrawableRes int error) { + Glide.with(imageView.getContext()) + .load(url) + .apply(new RequestOptions() + .placeholder(R.color.color_999999) + .error(error) + .transform(new GlideRoundTransform(imageView.getContext(), dp))) + .into(imageView); + } + + public static void loadImageTest(@NotNull ImageView imageView, String url, int dp) { + + //设置图片圆角角度 + RoundedCorners roundedCorners = new RoundedCorners(dp); + //通过RequestOptions扩展功能,override:采样率,因为ImageView就这么大,可以压缩图片,降低内存消耗 + // RequestOptions options = RequestOptions.bitmapTransform(roundedCorners).override(300, 300); + RequestOptions options = RequestOptions.bitmapTransform(roundedCorners); + options.placeholder(R.color.color_999999); + Glide.with(imageView.getContext()).load(url).apply(options).into(imageView); + + } + + /** + * 加载圆角图片 + * + * @param imageView ImageView + * @param file file + * @param dp 圆角角度 + */ + public static void loadImageCircleBead(@NotNull ImageView imageView, File file, int dp) { + loadImageCircleBead(imageView, file, dp, R.color.color_999999); + } + + /** + * 加载圆角图片 + * + * @param imageView ImageView + * @param file file + * @param dp 圆角角度 + * @param error 加载失败占位图 + */ + public static void loadImageCircleBead(@NotNull ImageView imageView, File file, int dp, @DrawableRes int error) { + Glide.with(imageView.getContext()) + .load(file) + .apply(new RequestOptions() + .placeholder(R.color.color_999999) + .error(error) + .transform(new GlideRoundTransform(imageView.getContext(), dp))) + .into(imageView); + } + + + /** + * 加载高斯模糊图 + * + * @param imageView imageView + * @param drawable drawable + */ + public static void loadImageBlur(ImageView imageView, int drawable) { + Glide.with(imageView) + .load(drawable) + .apply(RequestOptions.bitmapTransform( + new BlurTransformation(imageView.getContext(), 5f)) + .error(R.color.theme)) + .into(imageView); + } + + /** + * 加载高斯模糊图 + * + * @param imageView imageView + * @param drawable drawable + * @param error 加载失败占位图 + */ + public static void loadImageBlur(ImageView imageView, @DrawableRes int drawable, @DrawableRes int error) { + Glide.with(imageView) + .load(drawable) + .apply(RequestOptions.bitmapTransform( + new BlurTransformation(imageView.getContext(), 5f)) + .placeholder(R.color.color_999999) + .error(error)) .into(imageView); } @@ -80,18 +268,47 @@ public static void loadImageBlur(ImageView imageView, String url) { Glide.with(imageView) .load(url) .apply(RequestOptions.bitmapTransform( - new BlurTransformation(imageView.getContext()))) + new BlurTransformation(imageView.getContext())) + .error(R.color.theme)) .into(imageView); } + /** + * 加载高斯模糊图 + * + * @param imageView imageView + * @param url url + * @param error 加载失败占位图 + */ + public static void loadImageBlur(ImageView imageView, String url, @DrawableRes int error) { + Glide.with(imageView) + .load(url) + .apply(RequestOptions.bitmapTransform( + new BlurTransformation(imageView.getContext())) + .placeholder(R.color.color_999999) + .error(error)) + .into(imageView); + } + + + /** + * 加载圆形头像 + * + * @param imageView imageView + * @param url 图片链接 + */ + public static void loadCircleHeader(ImageView imageView, String url) { + loadImageCircle(imageView, url, R.drawable.header_load_default, R.drawable.header_load_default); + } + /** * 加载只有一张图的Banner * - * @param banner banner - * @param imgUrl imgUrl + * @param banner banner控件 + * @param imgUrl banner图片集合 * @param listener listener */ - public static void loadBanner(ConvenientBanner banner, List imgUrl, OnItemClickListener listener) { + public static void loadBanner(ConvenientBanner banner, List imgUrl, OnItemClickListener listener) { banner.setPages(new BannerImgAdapter(), imgUrl) .setPageIndicator(new int[]{R.drawable.shape_item_index_white, R.drawable.shape_item_index_red}) .setPageIndicatorAlign(ConvenientBanner.PageIndicatorAlign.ALIGN_PARENT_RIGHT) @@ -110,10 +327,12 @@ public static File compressImage(String filePath) { if (!FileUtils.isExistExternalStore()) { return null; } - int quality = 100; - Bitmap bm = getSmallBitmap(filePath);//获取一定尺寸的图片 - int degree = readPictureDegree(filePath);//获取相片拍摄角度 - if (degree != 0) {//旋转照片角度,防止头像横着显示 + int quality = 100;//获取一定尺寸的图片 + Bitmap bm = getSmallBitmap(filePath); + //获取相片拍摄角度 + int degree = readPictureDegree(filePath); + if (degree != 0) { + //旋转照片角度,防止头像横着显示 bm = rotateBitmap(bm, degree); } File outputFile = null; @@ -136,10 +355,14 @@ public static File compressImage(String filePath) { /** * 根据路径获得图片信息并按比例压缩,返回bitmap + * + * @param filePath 图片地址 + * @return Bitmap */ public static Bitmap getSmallBitmap(String filePath) { final BitmapFactory.Options options = new BitmapFactory.Options(); - options.inJustDecodeBounds = true;//只解析图片边沿,获取宽高 + //只解析图片边沿,获取宽高 + options.inJustDecodeBounds = true; BitmapFactory.decodeFile(filePath, options); // 计算缩放比 options.inSampleSize = calculateInSampleSize(options, 480, 800); @@ -148,15 +371,22 @@ public static Bitmap getSmallBitmap(String filePath) { return BitmapFactory.decodeFile(filePath, options); } - public static int calculateInSampleSize(BitmapFactory.Options options, - int reqWidth, int reqHeight) { + /** + * 计算缩放比 + * + * @param options options + * @param reqWidth 宽 + * @param reqHeight 高 + * @return 缩放比 + */ + public static int calculateInSampleSize(@NotNull BitmapFactory.Options options, int reqWidth, int reqHeight) { final int height = options.outHeight; final int width = options.outWidth; int inSampleSize = 1; if (height > reqHeight || width > reqWidth) { final int heightRatio = Math.round((float) height / (float) reqHeight); final int widthRatio = Math.round((float) width / (float) reqWidth); - inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio; + inSampleSize = Math.min(heightRatio, widthRatio); } return inSampleSize; } @@ -164,8 +394,8 @@ public static int calculateInSampleSize(BitmapFactory.Options options, /** * 获取照片角度 * - * @param path - * @return + * @param path 图片地址 + * @return int */ public static int readPictureDegree(String path) { int degree = 0; @@ -194,10 +424,11 @@ public static int readPictureDegree(String path) { /** * 旋转照片 * - * @param bitmap - * @param degress - * @return + * @param bitmap bitmap + * @param degress 旋转角度 + * @return Bitmap */ + @Contract("null, _ -> null") public static Bitmap rotateBitmap(Bitmap bitmap, int degress) { if (bitmap != null) { Matrix m = new Matrix(); @@ -206,7 +437,224 @@ public static Bitmap rotateBitmap(Bitmap bitmap, int degress) { bitmap.getHeight(), m, true); return bitmap; } - return bitmap; + return null; + } + + /** + * 把View转成Bitmap 注意:改view必须是已经显示到页面上的 + * + * @return Bitmap + */ + public static Bitmap viewConversionBitmap(@NotNull View view, String color) { + + int w = view.getWidth(); + int h = view.getHeight(); + + Bitmap bmp = Bitmap.createBitmap(w, w, Bitmap.Config.ARGB_8888); + Canvas c = new Canvas(bmp); + + c.drawColor(Color.parseColor(color)); + view.layout(0, 0, w, h); + view.draw(c); + return bmp; + + } + + /** + * 把View转成Bitmap 注意:改view必须是已经显示到页面上的 + * + * @return Bitmap + */ + public static Bitmap viewConversionBitmap(@NotNull ScrollView scrollView, String color) { + + int height = 20; + //正确获取ScrollView + for (int i = 0; i < scrollView.getChildCount(); i++) { + height += scrollView.getChildAt(i).getHeight(); + } + + int w = scrollView.getWidth(); + + Bitmap bmp = Bitmap.createBitmap(w, height, Bitmap.Config.ARGB_8888); + Canvas c = new Canvas(bmp); + + c.drawColor(Color.parseColor(color)); + scrollView.layout(0, 0, w, height); + scrollView.draw(c); + return bmp; + + } + + /** + * 把Bitmap转成图片 + * + * @param bitmap bitmap + * @param imageName 文件名称 + * @return 图片的本地地址 + */ + @org.jetbrains.annotations.Nullable + public static String bitmapSaveToImage(Bitmap bitmap, String imageName) { + FileOutputStream b = null; + String filePath = FileUtils.getImagePath() + File.separator + imageName + ".jpg"; + try { + b = new FileOutputStream(filePath); + // 把数据写入文件 + bitmap.compress(Bitmap.CompressFormat.JPEG, 100, b); + return filePath; + } catch (Exception e) { + e.printStackTrace(); + } finally { + try { + if (b != null) { + b.flush(); + b.close(); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + return null; + } + + + /** + * 添加图片到系统相册 + * + * @param activity activity + * @param filePath 图片路径 + * @param fileName 图片名称 + */ + public static boolean addImageToAlbum(@NotNull Activity activity, String filePath, String fileName) { + try { + MediaStore.Images.Media.insertImage(activity.getContentResolver(), filePath, fileName, null); + activity.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + Environment.getExternalStorageDirectory().getPath()))); + return true; + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + return false; + } + + /** + * 生成个人名片海报图片 + * + * @param activity activity + * @param scrollView ScrollView + */ + public static boolean generatePoster(Activity activity, ScrollView scrollView) { + String fileName = String.valueOf(DateUtils.getCurrentTimeStamp()); + String filePath = ImageUtils.bitmapSaveToImage(ImageUtils.viewConversionBitmap(scrollView, "#F5F5F5"), fileName); + if (ValidUtils.isValid(filePath)) { + return addImageToAlbum(activity, filePath, fileName); + } + return false; + } + + /** + * 生成个人名片海报图片 + * + * @param activity activity + * @param scrollView ScrollView + */ + public static String generatePosterPath(Activity activity, ScrollView scrollView) { + return ImageUtils.bitmapSaveToImage(ImageUtils.viewConversionBitmap(scrollView, "#F5F5F5"), String.valueOf(DateUtils.getCurrentTimeStamp())); + } + + /** + * Bitmap转二进制流 + * + * @param bitmap bitmap + * @return byte[] + */ + @NotNull + public static byte[] getBitmapByte(@NotNull Bitmap bitmap) { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out); + try { + out.flush(); + out.close(); + } catch (IOException e) { + e.printStackTrace(); + } + return out.toByteArray(); + } + + /** + * Bitmap转换成byte[]并且进行压缩,压缩到不大于maxkb + * + * @param bitmap bitmap + * @param maxKb 最大大小 + * @return 字节数组 + */ + @NotNull + public static byte[] bitmapBytes(@NotNull Bitmap bitmap, int maxKb) { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + bitmap.compress(Bitmap.CompressFormat.PNG, 100, output); + int options = 100; + while (output.toByteArray().length > maxKb && options != 10) { + output.reset(); //清空output + //这里压缩options%,把压缩后的数据存放到output中 + bitmap.compress(Bitmap.CompressFormat.JPEG, options, output); + options -= 10; + } + return output.toByteArray(); + } + + /** + * 获取海报的图片二进制流 + * + * @param layoutView 海报view + * @return byte[] + */ + @NotNull + public static byte[] getPosterByte(View layoutView) { + return getBitmapByte(ImageUtils.viewConversionBitmap(layoutView, "#F5F5F5")); + } + + /** + * 获取微信分享图片的缩略图 + * + * @param image 图片流 + * @return 图片流 + */ + @NotNull + public static byte[] getWXShareThumbImage(byte[] image) { + return bitmapBytes(getBitmapByBytes(image, 200, 300), 32); + } + + /** + * 根据图片生成缩略图 + * + * @param bytes 图片流 + * @param maxHeight 最大高度 + * @param maxWidth 最大宽度 + * @return Bitmap + */ + @NotNull + public static Bitmap getBitmapByBytes(byte[] bytes, int maxHeight, int maxWidth) { + //对于图片的二次采样,主要得到图片的宽与高 + int width = 0; + int height = 0; + //默认缩放为1 + int sampleSize = 1; + BitmapFactory.Options options = new BitmapFactory.Options(); + //仅仅解码边缘区域 + options.inJustDecodeBounds = true; + //如果指定了inJustDecodeBounds,decodeByteArray将返回为空 + BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options); + //得到宽与高 + height = options.outHeight; + width = options.outWidth; + + //图片实际的宽与高,根据默认最大大小值,得到图片实际的缩放比例 + while ((height / sampleSize > maxHeight) || (width / sampleSize > maxWidth)) { + sampleSize *= 2; + } + //不再只加载图片实际边缘 + options.inJustDecodeBounds = false; + //并且制定缩放比例 + options.inSampleSize = sampleSize; + return BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options); } } diff --git a/common_base/src/main/java/com/wss/common/utils/JsonUtils.java b/common_base/src/main/java/com/wss/common/utils/JsonUtils.java new file mode 100644 index 0000000..297a8fd --- /dev/null +++ b/common_base/src/main/java/com/wss/common/utils/JsonUtils.java @@ -0,0 +1,306 @@ +package com.wss.common.utils; + +import android.text.TextUtils; + +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.google.gson.JsonSyntaxException; +import com.google.gson.reflect.TypeToken; + +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; + +/** + * Describe:Gson 解析封装 + * Created by 吴天强 on 2018/12/12. + */ +public class JsonUtils { + + /** + * 对象转Json + * + * @param obj 对象 + * @return json String + */ + public static String toJson(Object obj) { + if (ValidUtils.isValid(obj)) { + return new Gson().toJson(obj); + } + return "{}"; + } + + /** + * 解析T对象 + * + * @param json json + * @param type 目标类型 + * @param 类型 + * @return T + */ + public static T getObject(String json, Class type) { + return new Gson().fromJson(json, type); + } + + /** + * 解析String + * + * @param json json + * @param key key + * @return String + */ + @Contract("null, _ -> !null") + public static String getString(JsonObject json, String key) { + if (json == null) { + return ""; + } + JsonElement jsonElement = json.get(key); + if (jsonElement == null) { + return ""; + } + return jsonElement.getAsString(); + } + + /** + * 解析String + * + * @param element json + * @return String + */ + @Contract("null, _ -> !null") + public static String getString(JsonElement element, String key) { + if (element == null) { + return ""; + } + return getString(element.getAsJsonObject(), key); + } + + /** + * 解析String + * + * @param json json + * @param key key + * @return String + */ + public static String getString(String json, String key) { + if (!isJsonObject(json)) { + return ""; + } + JsonElement jsonElement = getJsonObject(json).get(key); + if (jsonElement == null) { + return ""; + } + //判断json对象是否为Object + if (jsonElement.isJsonObject()) { + JsonObject asJsonObject = jsonElement.getAsJsonObject(); + return asJsonObject.toString(); + } + //判断json对象是否为数组 + if (jsonElement.isJsonArray()) { + JsonArray asJsonArray = jsonElement.getAsJsonArray(); + return asJsonArray.toString(); + } + return jsonElement.getAsString(); + } + + + /** + * 解析boolean + * + * @param json json + * @param key key + * @return boolean + */ + @Contract("null, _ -> false") + public static boolean getBoolean(String json, String key) { + if (json == null) { + return false; + } + JsonElement jsonElement = getJsonObject(json).get(key); + return jsonElement != null && jsonElement.getAsBoolean(); + } + + /** + * 解析int + * + * @param json json + * @param key key + * @return String + */ + public static int getInt(String json, String key) { + JsonElement jsonElement = getJsonObject(json).get(key); + if (jsonElement == null) { + return 0; + } + return jsonElement.getAsInt(); + } + + /** + * 解析int + * + * @param json json + * @param key key + * @return boolean + */ + public static int getInt(JsonObject json, String key) { + if (json == null) { + return 0; + } + JsonElement jsonElement = json.get(key); + if (jsonElement == null) { + return 0; + } + return jsonElement.getAsInt(); + } + + + /** + * 解析JsonObject + * + * @param json json + * @return JsonArray + */ + public static JsonObject getJsonObject(String json) { + if (TextUtils.isEmpty(json)) { + return new JsonObject(); + } + return new JsonParser().parse(json).getAsJsonObject(); + } + + /** + * 解析JsonArray + * + * @param json json + * @param key key + * @return JsonArray + */ + @Contract("null, _ -> new") + public static JsonArray getJsonArray(JsonObject json, String key) { + if (json == null) { + return new JsonArray(); + } + JsonElement jsonElement = json.get(key); + if (jsonElement == null) { + return new JsonArray(); + } + return jsonElement.getAsJsonArray(); + } + + + /** + * 解析Map + * + * @param json json + * @return List + */ + @NotNull + public static LinkedHashMap getMap(@NotNull String json) { + LinkedHashMap result = new LinkedHashMap<>(); + try { + JsonObject jsonObject = new JsonParser().parse(json).getAsJsonObject(); + result.putAll(new Gson().fromJson(jsonObject, new TypeToken>() { + }.getType())); + } catch (JsonSyntaxException e) { + e.printStackTrace(); + } + return result; + } + + /** + * 解析List + * + * @param json json + * @param clazz clazz + * @return List + */ + public static List getList(String json, Class clazz) { + if (!ValidUtils.isValid(json)) { + return new ArrayList<>(); + } + List list = null; + try { + list = new ArrayList<>(); + Type type = new TypeToken>() { + }.getType(); + List jsonObjects = new Gson().fromJson(json, type); + if (ValidUtils.isValid(jsonObjects)) { + for (JsonObject jsonObject : jsonObjects) { + list.add(new Gson().fromJson(jsonObject, clazz)); + } + } + } catch (JsonSyntaxException e) { + e.printStackTrace(); + } + return list; + } + + /** + * 解析List + * + * @param json json + * @return List + */ + public static List getList(String json) { + if (!isJsonArray(json)) { + return new ArrayList<>(); + } + return new Gson().fromJson(json, new TypeToken>() { + }.getType()); + } + + /** + * 判断是否JSON数组 + * + * @param json json + * @return boolean + */ + public static boolean isJsonArray(String json) { + JsonElement jsonElement = getJsonElement(json); + if (jsonElement == null) { + return false; + } + return jsonElement.isJsonArray(); + } + + /** + * 判断是否JSON对象 + * + * @param json json + * @return boolean + */ + public static boolean isJsonObject(String json) { + JsonElement jsonElement = getJsonElement(json); + if (jsonElement == null) { + return false; + } + return jsonElement.isJsonObject(); + } + + /** + * 获取JsonElement + * + * @param json json + * @return JsonElement + */ + @Nullable + private static JsonElement getJsonElement(String json) { + JsonElement jsonElement; + if (!ValidUtils.isValid(json)) { + return null; + } + try { + jsonElement = new JsonParser().parse(json); + } catch (Exception e) { + return null; + } + return jsonElement; + } +} diff --git a/common_base/src/main/java/com/wss/common/utils/KeyboardUtils.java b/common_base/src/main/java/com/wss/common/utils/KeyboardUtils.java index a4f2426..a6c3af4 100644 --- a/common_base/src/main/java/com/wss/common/utils/KeyboardUtils.java +++ b/common_base/src/main/java/com/wss/common/utils/KeyboardUtils.java @@ -4,13 +4,20 @@ import android.view.View; import android.view.inputmethod.InputMethodManager; +import org.jetbrains.annotations.NotNull; + /** * Describe:键盘辅助类 * Created by 吴天强 on 2017/11/2. */ public class KeyboardUtils { - public static void showKeyboard(View view) { + /** + * 显示键盘 + * + * @param view view + */ + public static void showKeyboard(@NotNull View view) { InputMethodManager imm = (InputMethodManager) view.getContext() .getSystemService(Context.INPUT_METHOD_SERVICE); if (imm != null) { @@ -19,19 +26,16 @@ public static void showKeyboard(View view) { } } - public static void hideKeyboard(View view) { + /** + * 隐藏键盘 + * + * @param view view + */ + public static void hideKeyboard(@NotNull View view) { InputMethodManager imm = (InputMethodManager) view.getContext() .getSystemService(Context.INPUT_METHOD_SERVICE); if (imm != null) { imm.hideSoftInputFromWindow(view.getWindowToken(), 0); } } - - public static void toggleSoftInput(View view) { - InputMethodManager imm = (InputMethodManager) view.getContext() - .getSystemService(Context.INPUT_METHOD_SERVICE); - if (imm != null) { - imm.toggleSoftInput(0, 0); - } - } } \ No newline at end of file diff --git a/common_base/src/main/java/com/wss/common/utils/MoneyUtils.java b/common_base/src/main/java/com/wss/common/utils/MoneyUtils.java index ebc2363..8768e44 100644 --- a/common_base/src/main/java/com/wss/common/utils/MoneyUtils.java +++ b/common_base/src/main/java/com/wss/common/utils/MoneyUtils.java @@ -10,7 +10,6 @@ * Describe:金钱工具类 * Created by 吴天强 on 2017/11/24. */ - public class MoneyUtils { /** * 计算类 @@ -20,32 +19,32 @@ public static class Algorithm { /** * 金钱加法 * - * @param v1 - * @param v2 - * @return + * @param value1 参数1 + * @param value2 参数2 + * @return 结果 */ - public static String add(Object v1, Object v2) { - BigDecimal b1 = new BigDecimal(String.valueOf(v1)); - BigDecimal b2 = new BigDecimal(String.valueOf(v2)); + public static String add(Object value1, Object value2) { + BigDecimal b1 = new BigDecimal(String.valueOf(value1)); + BigDecimal b2 = new BigDecimal(String.valueOf(value2)); return b1.add(b2).toString(); } /** * 金钱减法 * - * @param v1 - * @param v2 - * @return + * @param value1 参数1 + * @param value2 参数2 + * @return 结果 */ - public static String subtract(String v1, String v2) { - if (TextUtils.isEmpty(v1)) { - v1 = "0"; + public static String subtract(String value1, String value2) { + if (TextUtils.isEmpty(value1)) { + value1 = "0"; } - if (TextUtils.isEmpty(v2)) { - v2 = "0"; + if (TextUtils.isEmpty(value2)) { + value2 = "0"; } - BigDecimal b1 = new BigDecimal(v1); - BigDecimal b2 = new BigDecimal(v2); + BigDecimal b1 = new BigDecimal(value1); + BigDecimal b2 = new BigDecimal(value2); return b1.subtract(b2).toString(); } @@ -53,25 +52,25 @@ public static String subtract(String v1, String v2) { /** * 金钱乘法 * - * @param v1 - * @param v2 - * @return + * @param value1 参数1 + * @param value2 参数2 + * @return 结果 */ - public static String multiply(String v1, String v2) { - return multiply(v1, v2, 0); + public static String multiply(String value1, String value2) { + return multiply(value1, value2, 0); } /** * 金钱乘法 * - * @param v1 乘数 - * @param v2 被乘数 - * @param scale 小数点保留位数 - * @return + * @param value1 乘数 + * @param value2 被乘数 + * @param scale 小数点保留位数 + * @return 结果 */ - public static String multiply(String v1, String v2, int scale) { - BigDecimal b1 = new BigDecimal(v1); - BigDecimal b2 = new BigDecimal(v2); + public static String multiply(String value1, String value2, int scale) { + BigDecimal b1 = new BigDecimal(value1); + BigDecimal b2 = new BigDecimal(value2); BigDecimal result = b1.multiply(b2); result = result.setScale(scale, BigDecimal.ROUND_HALF_UP); return result.toString(); @@ -80,13 +79,13 @@ public static String multiply(String v1, String v2, int scale) { /** * 金钱除法 * - * @param v1 - * @param v2 - * @return + * @param value1 参数1 + * @param value2 参数2 + * @return 结果 */ - public static String divide(String v1, String v2) { - BigDecimal b1 = new BigDecimal(v1); - BigDecimal b2 = new BigDecimal(v2); + public static String divide(String value1, String value2) { + BigDecimal b1 = new BigDecimal(value1); + BigDecimal b2 = new BigDecimal(value2); return b1.divide(b2, BigDecimal.ROUND_HALF_UP).toString(); } } @@ -98,7 +97,7 @@ public static String divide(String v1, String v2) { * @return String */ public static String formatPrice(String textPrice) { - return formatPrice(Double.valueOf(textPrice) / 100); + return formatPrice(Double.parseDouble(textPrice) / 100); } /** @@ -108,13 +107,6 @@ public static String formatPrice(String textPrice) { * @return String */ public static String formatPrice(double price) { - if (price > 0 && price < 1) { - String temp = String.valueOf(price); - if (temp.contains(".") && temp.substring(temp.indexOf(".") + 1, temp.length()).length() <= 1) { - return String.format("%s%s", price, 0); - } - return String.format("%s", price); - } if (price <= 0) { return "0.00"; } @@ -123,4 +115,28 @@ public static String formatPrice(double price) { return String.format("%s", format.format(price)); } + /** + * 将金钱转成显示的格式¥xx.xx如此格式 + * + * @param price 单位为元的金额 + * @return String + */ + public static String formatPriceT(double price) { + if (price <= 0) { + return "0.00"; + } + DecimalFormat format = new DecimalFormat("0.00"); + format.setRoundingMode(RoundingMode.FLOOR); + return String.format("%s", format.format(price)); + } + /** + * 将金钱转成显示的格式¥xx.xx如此格式 + * + * @param textPrice 单位为分的金额 + * @return String + */ + public static String formatPriceT(String textPrice) { + return formatPriceT(Double.parseDouble(textPrice) / 10000); + } + } diff --git a/common_base/src/main/java/com/wss/common/utils/NetworkUtil.java b/common_base/src/main/java/com/wss/common/utils/NetworkUtil.java index d2fa331..047924f 100644 --- a/common_base/src/main/java/com/wss/common/utils/NetworkUtil.java +++ b/common_base/src/main/java/com/wss/common/utils/NetworkUtil.java @@ -6,8 +6,15 @@ import android.net.NetworkInfo; import android.telephony.TelephonyManager; +import java.net.Inet4Address; +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.util.Enumeration; import java.util.List; +import androidx.annotation.NonNull; + /** * Describe:网络状态工具类 * Created by 吴天强 on 2018/10/25. @@ -18,18 +25,15 @@ public class NetworkUtil { * 是否有可用网络 * * @param context context - * @return + * @return boolean */ - public static boolean isNetworkAvailable(Context context) { - ConnectivityManager connectivity = (ConnectivityManager) context - .getSystemService(Context.CONNECTIVITY_SERVICE); + public static boolean isNetworkEnabled(@NonNull Context context) { + ConnectivityManager connectivity = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); if (connectivity != null) { NetworkInfo[] info = connectivity.getAllNetworkInfo(); - if (info != null) { - for (int i = 0; i < info.length; i++) { - if (info[i].getState() == NetworkInfo.State.CONNECTED) { - return true; - } + for (NetworkInfo networkInfo : info) { + if (networkInfo.getState() == NetworkInfo.State.CONNECTED) { + return true; } } } @@ -37,60 +41,97 @@ public static boolean isNetworkAvailable(Context context) { } /** - * gps能用? + * gps能用 * - * @param context context - * @return + * @param context ctx + * @return boolean */ - public static boolean isGpsEnabled(Context context) { - LocationManager locationManager = ((LocationManager) context - .getSystemService(Context.LOCATION_SERVICE)); - List accessibleProviders = locationManager.getProviders(true); - return accessibleProviders != null && accessibleProviders.size() > 0; + public static boolean isGpsEnabled(@NonNull Context context) { + LocationManager locationManager = ((LocationManager) context.getSystemService(Context.LOCATION_SERVICE)); + if (locationManager != null) { + List accessibleProviders = locationManager.getProviders(true); + return accessibleProviders.size() > 0; + } + return false; } /** * Wifi是否可用 * * @param context context - * @return + * @return boolean */ - public static boolean isWifiEnabled(Context context) { - ConnectivityManager mgrConn = (ConnectivityManager) context - .getSystemService(Context.CONNECTIVITY_SERVICE); - TelephonyManager mgrTel = (TelephonyManager) context - .getSystemService(Context.TELEPHONY_SERVICE); - return ((mgrConn.getActiveNetworkInfo() != null && mgrConn - .getActiveNetworkInfo().getState() == NetworkInfo.State.CONNECTED) || mgrTel - .getNetworkType() == TelephonyManager.NETWORK_TYPE_UMTS); + public static boolean isWifiEnabled(@NonNull Context context) { + ConnectivityManager mgrConn = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); + if (mgrConn != null && mgrConn.getActiveNetworkInfo() != null && + mgrConn.getActiveNetworkInfo().getState() == NetworkInfo.State.CONNECTED) { + return true; + } + TelephonyManager mgrTel = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); + return mgrTel != null && mgrTel.getNetworkType() == TelephonyManager.NETWORK_TYPE_UMTS; } /** * 当前网络是否为Wifi * * @param context context - * @return + * @return boolean */ - public static boolean isWifi(Context context) { - ConnectivityManager connectivityManager = (ConnectivityManager) context - .getSystemService(Context.CONNECTIVITY_SERVICE); - NetworkInfo activeNetInfo = connectivityManager.getActiveNetworkInfo(); - return activeNetInfo != null - && activeNetInfo.getType() == ConnectivityManager.TYPE_WIFI; + public static boolean isWifi(@NonNull Context context) { + ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); + if (connectivityManager != null) { + NetworkInfo activeNetInfo = connectivityManager.getActiveNetworkInfo(); + return activeNetInfo != null && activeNetInfo.getType() == ConnectivityManager.TYPE_WIFI; + } + return false; } /** - * 当前网络是否为收集数据 + * 当前网络是否为移动数据 * * @param context context - * @return + * @return boolean + */ + public static boolean isMobile(@NonNull Context context) { + ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); + if (connectivityManager != null) { + NetworkInfo activeNetInfo = connectivityManager.getActiveNetworkInfo(); + return activeNetInfo != null && activeNetInfo.getType() == ConnectivityManager.TYPE_MOBILE; + } + return false; + } + + /** + * 获取当前网络IP + * + * @return 网络IP + */ + public static String getIpAddress() { + try { + for (Enumeration enNetI = NetworkInterface.getNetworkInterfaces(); enNetI + .hasMoreElements(); ) { + NetworkInterface netI = enNetI.nextElement(); + for (Enumeration enumIpAddr = netI.getInetAddresses(); enumIpAddr.hasMoreElements(); ) { + InetAddress inetAddress = enumIpAddr.nextElement(); + if (inetAddress instanceof Inet4Address && !inetAddress.isLoopbackAddress()) { + return inetAddress.getHostAddress(); + } + } + } + } catch (SocketException e) { + e.printStackTrace(); + } + return ""; + } + + /** + * 检查是否为连接 + * + * @param url url + * @return boolean */ - public static boolean is3G(Context context) { - ConnectivityManager connectivityManager = (ConnectivityManager) context - .getSystemService(Context.CONNECTIVITY_SERVICE); - NetworkInfo activeNetInfo = connectivityManager.getActiveNetworkInfo(); - return activeNetInfo != null - && activeNetInfo.getType() == ConnectivityManager.TYPE_MOBILE; + public static boolean isLink(String url) { + return ValidUtils.isValid(url) && (url.startsWith("http") || url.startsWith("https")); } } diff --git a/common_base/src/main/java/com/wss/common/utils/PermissionsUtils.java b/common_base/src/main/java/com/wss/common/utils/PermissionsUtils.java index 565412a..530900d 100644 --- a/common_base/src/main/java/com/wss/common/utils/PermissionsUtils.java +++ b/common_base/src/main/java/com/wss/common/utils/PermissionsUtils.java @@ -1,10 +1,12 @@ package com.wss.common.utils; +import android.Manifest; import android.app.Activity; import com.hjq.permissions.OnPermission; import com.hjq.permissions.Permission; import com.hjq.permissions.XXPermissions; +import com.wss.common.base.R; import java.util.List; @@ -13,10 +15,9 @@ import io.reactivex.schedulers.Schedulers; /** - * Describe:6.0动态权限管理帮助类 + * Describe:6.0 + 动态权限管理帮助类 * Created by 吴天强 on 2018/10/25. */ - public class PermissionsUtils { /** @@ -38,7 +39,11 @@ public void noPermission(List denied, boolean quick) { } /** - * 检查相机权限 + * 检查权限 + * + * @param activity activity + * @param permissions 权限组 + * @return Observable */ public static Observable checkPermissions(Activity activity, String... permissions) { return Observable.create( @@ -57,7 +62,7 @@ public void hasPermission(List granted, boolean isAll) { @Override public void noPermission(List denied, boolean quick) { subscriber.onNext(false); - ToastUtils.show(activity, "您必须授权必要权限才可使用该功能!"); + ToastUtils.show(activity, activity.getString(R.string.authorise_necessary_authorities)); } }); } @@ -69,23 +74,25 @@ public void noPermission(List denied, boolean quick) { /** * 检查相机权限 + * + * @param activity activity + * @return Observable */ public static Observable checkCamera(Activity activity) { - return checkPermissions(activity, Permission.CAMERA); + return checkPermissions(activity, Permission.CAMERA, Permission.WRITE_EXTERNAL_STORAGE); } /** - * 检查相机、文件读写权限 + * 检查文件读写权限 * * @param activity activity * @return boolean */ - public static Observable checkCameraAndStorage(Activity activity) { + public static Observable checkStorage(Activity activity) { String[] storage = { Permission.READ_EXTERNAL_STORAGE, - Permission.WRITE_EXTERNAL_STORAGE, - Permission.CAMERA}; + Permission.WRITE_EXTERNAL_STORAGE}; return checkPermissions(activity, storage); } @@ -94,11 +101,9 @@ public static Observable checkCameraAndStorage(Activity activity) { * 检查录音相关权限 */ public static Observable checkRecord(Activity activity) { - String[] storage = { - Permission.READ_EXTERNAL_STORAGE, + return checkPermissions(activity, Permission.READ_EXTERNAL_STORAGE, Permission.WRITE_EXTERNAL_STORAGE, - Permission.RECORD_AUDIO}; - return checkPermissions(activity, storage); + Permission.RECORD_AUDIO); } /** @@ -108,5 +113,25 @@ public static Observable checkCallPhone(Activity activity) { return checkPermissions(activity, Permission.CALL_PHONE); } + /** + * 检查定位权限 + * + * @param activity activity + * @return boolean + */ + public static Observable checkLocation(Activity activity) { + return checkPermissions(activity, Permission.ACCESS_FINE_LOCATION, + Permission.ACCESS_COARSE_LOCATION, Permission.RECORD_AUDIO); + } + + /** + * 允许锁屏状态下,app在后台运行 + * + * @param activity activity + * @return boolean + */ + public static Observable checkWakeLock(Activity activity) { + return checkPermissions(activity, Manifest.permission.WAKE_LOCK); + } } diff --git a/common_base/src/main/java/com/wss/common/utils/PhoneUtils.java b/common_base/src/main/java/com/wss/common/utils/PhoneUtils.java new file mode 100644 index 0000000..a47b278 --- /dev/null +++ b/common_base/src/main/java/com/wss/common/utils/PhoneUtils.java @@ -0,0 +1,46 @@ +package com.wss.common.utils; + +import android.annotation.SuppressLint; +import android.content.Intent; +import android.net.Uri; + +import com.wss.common.base.BaseApplication; + +/** + * description: 拨打电话工具类 + * + * @author 杨伟-tony + * create by 2020/5/22 11:26 + */ +public class PhoneUtils { + /** + * 拨打电话 + * ps:调起拨号盘 + * + * @param phoneNum 电话号码 + */ + public static void callPhoneWaitFor(String phoneNum) { + Intent intent = new Intent(Intent.ACTION_DIAL); + Uri data = Uri.parse("tel:" + phoneNum); + intent.setData(data); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + BaseApplication.i().startActivity(intent); + + } + + /** + * 拨打电话 + * 吊起拨号盘 直接拨打电话 + * + * @param phoneNum 电话号码 + */ + @SuppressLint("MissingPermission") + public static void callPhoneDirect(String phoneNum) { + Intent intent = new Intent(Intent.ACTION_CALL); + Uri data = Uri.parse("tel:" + phoneNum); + intent.setData(data); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + BaseApplication.i().startActivity(intent); + } + +} diff --git a/common_base/src/main/java/com/wss/common/utils/PxUtils.java b/common_base/src/main/java/com/wss/common/utils/PxUtils.java index 83a205e..340d4b9 100644 --- a/common_base/src/main/java/com/wss/common/utils/PxUtils.java +++ b/common_base/src/main/java/com/wss/common/utils/PxUtils.java @@ -4,28 +4,38 @@ import com.wss.common.base.BaseApplication; +import androidx.annotation.NonNull; + /** * Describe:尺寸工具类 * Created by 吴天强 on 2017/9/19. */ - public class PxUtils { /** * 得到设备屏幕的宽度 + * + * @param context ctx + * @return int */ - public static int getScreenWidth(Context context) { + public static int getScreenWidth(@NonNull Context context) { return context.getResources().getDisplayMetrics().widthPixels; } /** * 得到设备屏幕的高度 + * + * @param context ctx + * @return int */ - public static int getScreenHeight(Context context) { + public static int getScreenHeight(@NonNull Context context) { return context.getResources().getDisplayMetrics().heightPixels; } /** * 得到设备的密度 + * + * @param context ctx + * @return float */ public static float getScreenDensity(Context context) { return context.getResources().getDisplayMetrics().density; @@ -33,38 +43,34 @@ public static float getScreenDensity(Context context) { /** * 把密度转换为像素 + * + * @param dpValue dp值 + * @return int */ - public static int dp2px(Context context, float dipValue) { - final float scale = getScreenDensity(context); - return (int) (dipValue * scale + 0.5); - } - - public static int dp2px(float dipValue) { - final float scale = getScreenDensity(BaseApplication.getApplication()); - return (int) (dipValue * scale + 0.5); + public static int dp2px(float dpValue) { + float scale = getScreenDensity(BaseApplication.i()); + return (int) (dpValue * scale + 0.5); } /** * 将像素转换成dp * - * @param context - * @param pxValue - * @return + * @param pxValue px值 + * @return int */ - public static int px2dp(Context context, float pxValue) { - final float scale = context.getResources().getDisplayMetrics().density; + public static int px2dp(float pxValue) { + float scale = getScreenDensity(BaseApplication.i()); return (int) (pxValue / scale + 0.5f); } /** * 将sp值转换为px值,保证文字大小不变 * - * @param context context - * @param spValue - * @return + * @param spValue sp值 + * @return int */ - public static int sp2px(Context context, float spValue) { - final float fontScale = context.getResources().getDisplayMetrics().scaledDensity; + public static int sp2px(float spValue) { + float fontScale = getScreenDensity(BaseApplication.i()); return (int) (spValue * fontScale + 0.5f); } } diff --git a/common_base/src/main/java/com/wss/common/utils/RomUtil.java b/common_base/src/main/java/com/wss/common/utils/RomUtil.java new file mode 100644 index 0000000..ecc138b --- /dev/null +++ b/common_base/src/main/java/com/wss/common/utils/RomUtil.java @@ -0,0 +1,152 @@ +package com.wss.common.utils; + +import android.os.Build; +import android.text.TextUtils; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +/** + * Describe:判断手机ROM类型 + * Created by 吴天强 on 2020/6/24. + */ +public class RomUtil { + + public static final String ROM_MIUI = "MIUI"; + public static final String ROM_EMUI = "EMUI"; + public static final String ROM_FLYME = "FLYME"; + public static final String ROM_OPPO = "OPPO"; + public static final String ROM_SMARTISAN = "SMARTISAN"; + public static final String ROM_VIVO = "VIVO"; + public static final String ROM_QIKU = "QIKU"; + + private static final String KEY_VERSION_MIUI = "ro.miui.ui.version.name"; + private static final String KEY_VERSION_EMUI = "ro.build.version.emui"; + private static final String KEY_VERSION_OPPO = "ro.build.version.opporom"; + private static final String KEY_VERSION_SMARTISAN = "ro.smartisan.version"; + private static final String KEY_VERSION_VIVO = "ro.vivo.os.version"; + + private static String sName; + private static String sVersion; + + /** + * 华为 + * + * @return boolean + */ + public static boolean isEmui() { + return check(ROM_EMUI); + } + + /** + * 小米 + * + * @return boolean + */ + public static boolean isMiui() { + return check(ROM_MIUI); + } + + /** + * vivo + * + * @return boolean + */ + public static boolean isVivo() { + return check(ROM_VIVO); + } + + /** + * oppo + * + * @return boolean + */ + public static boolean isOppo() { + return check(ROM_OPPO); + } + + /** + * 魅族 + * + * @return boolean + */ + public static boolean isFlyme() { + return check(ROM_FLYME); + } + + /** + * 360手机 + * + * @return boolean + */ + public static boolean is360() { + return check(ROM_QIKU) || check("360"); + } + + public static boolean isSmartisan() { + return check(ROM_SMARTISAN); + } + + public static String getName() { + if (sName == null) { + check(""); + } + return sName; + } + + public static String getVersion() { + if (sVersion == null) { + check(""); + } + return sVersion; + } + + public static boolean check(String rom) { + if (sName != null) { + return sName.equals(rom); + } + if (!TextUtils.isEmpty(sVersion = getProp(KEY_VERSION_MIUI))) { + sName = ROM_MIUI; + } else if (!TextUtils.isEmpty(sVersion = getProp(KEY_VERSION_EMUI))) { + sName = ROM_EMUI; + } else if (!TextUtils.isEmpty(sVersion = getProp(KEY_VERSION_OPPO))) { + sName = ROM_OPPO; + } else if (!TextUtils.isEmpty(sVersion = getProp(KEY_VERSION_VIVO))) { + sName = ROM_VIVO; + } else if (!TextUtils.isEmpty(sVersion = getProp(KEY_VERSION_SMARTISAN))) { + sName = ROM_SMARTISAN; + } else { + sVersion = Build.DISPLAY; + if (sVersion.toUpperCase().contains(ROM_FLYME)) { + sName = ROM_FLYME; + } else { + sVersion = Build.UNKNOWN; + sName = Build.MANUFACTURER.toUpperCase(); + } + } + return sName.equals(rom); + } + + public static String getProp(String name) { + String line = null; + BufferedReader input = null; + try { + Process p = Runtime.getRuntime().exec("getprop " + name); + input = new BufferedReader(new InputStreamReader(p.getInputStream()), 1024); + line = input.readLine(); + input.close(); + } catch (IOException ex) { + return null; + } finally { + if (input != null) { + try { + input.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + return line; + } +} diff --git a/common_base/src/main/java/com/wss/common/utils/SelectorPopupWindow.java b/common_base/src/main/java/com/wss/common/utils/SelectorPopupWindow.java new file mode 100644 index 0000000..3cb335c --- /dev/null +++ b/common_base/src/main/java/com/wss/common/utils/SelectorPopupWindow.java @@ -0,0 +1,175 @@ +package com.wss.common.utils; + +import android.content.Context; +import android.graphics.Rect; +import android.graphics.drawable.ColorDrawable; +import android.os.Build; +import android.text.TextUtils; +import android.view.View; +import android.view.ViewGroup; +import android.widget.PopupWindow; +import android.widget.TextView; + +import com.wss.common.base.R; +import com.wss.common.base.adapter.BaseListAdapter; +import com.wss.common.base.adapter.listener.OnListItemClickListener; +import com.wss.common.bean.SelectorData; + +import org.byteam.superadapter.SuperViewHolder; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; + +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +/** + * Describe:弹窗选择器 + * Created by 吴天强 on 2020/4/21. + */ +public class SelectorPopupWindow extends PopupWindow { + + private Context context; + private View parent; + private OnItemClickListener itemClickListener; + private PopupWindow.OnDismissListener dismissListener; + private List dataList = new ArrayList<>(); + private String defaultChecked; + + /** + * @param context context + * @param parent 显示位置父控件 + */ + public SelectorPopupWindow(Context context, View parent, List dataList) { + this.context = context; + this.parent = parent; + this.dataList.addAll(dataList); + } + + + /** + * 弹窗消失监听 + * + * @param dismissListener 监听 + * @return SelectorPopupWindow + */ + public SelectorPopupWindow setDismissListener(PopupWindow.OnDismissListener dismissListener) { + this.dismissListener = dismissListener; + return this; + } + + /** + * Item点击事件 + * + * @param itemClickListener 事件 + */ + public SelectorPopupWindow setOnItemClickListener(OnItemClickListener itemClickListener) { + this.itemClickListener = itemClickListener; + return this; + } + + /** + * 默认选择项 + * + * @param defaultChecked 默认值 + * @return SelectorPopupWindow + */ + public SelectorPopupWindow setDefaultChecked(String defaultChecked) { + this.defaultChecked = defaultChecked; + return this; + } + + public void show() { + initView(ViewGroup.LayoutParams.MATCH_PARENT); + } + + /** + * 显示自定义宽度值 + * + * @param value 宽度值 + */ + public void showMonthPopup(int value) { + initView(PxUtils.dp2px(value)); + } + + private void initView(int width) { + View childView = View.inflate(context, R.layout.pop_selector, null); + childView.findViewById(R.id.close).setOnClickListener(v -> dismiss()); + initItems(childView); + setWidth(width); + setHeight(ViewGroup.LayoutParams.MATCH_PARENT); + ColorDrawable dw = new ColorDrawable(0); + setBackgroundDrawable(dw); + setFocusable(true); + setOutsideTouchable(true); + setContentView(childView); + showAsDropDown(parent); + update(); + setOnDismissListener(dismissListener); + } + + private void initItems(@NotNull View childView) { + RecyclerView recyclerView = childView.findViewById(R.id.recycle_view); + recyclerView.setLayoutManager(new LinearLayoutManager(context)); + recyclerView.setAdapter(new SelectorAdapter(context, dataList, R.layout.item_of_selector_pop, + (data, position) -> { + if (itemClickListener != null) { + itemClickListener.onItemClick(data); + } + dismiss(); + }, defaultChecked)); + } + + + @Override + public void showAsDropDown(View anchor) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + Rect visibleFrame = new Rect(); + anchor.getGlobalVisibleRect(visibleFrame); + int height; + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O_MR1 && !RomUtil.isVivo()) { + //9.0 + height = anchor.getResources().getDisplayMetrics().heightPixels - (visibleFrame.bottom - PxUtils.dp2px(30)); + } else { + height = anchor.getResources().getDisplayMetrics().heightPixels - visibleFrame.bottom; + } + setHeight(height); + } + super.showAsDropDown(anchor); + } + + /** + * 列表适配器 + */ + private static class SelectorAdapter extends BaseListAdapter { + + private String defaultChecked; + + SelectorAdapter(Context context, List mData, int layoutResId, OnListItemClickListener listener, String defaultChecked) { + super(context, mData, layoutResId, listener); + this.defaultChecked = defaultChecked; + } + + @Override + public void onBindData(@NotNull SuperViewHolder holder, int viewType, int layoutPosition, @NotNull SelectorData data) { + TextView tvName = holder.findViewById(R.id.tv_name); + tvName.setText(data.getName()); + tvName.setSelected(TextUtils.equals(defaultChecked, data.getName())); + } + } + + + /** + * Item点击事件监听 + */ + public interface OnItemClickListener { + + /** + * Item点击回调 + * + * @param data 选择数据 + */ + void onItemClick(SelectorData data); + } +} \ No newline at end of file diff --git a/common_base/src/main/java/com/wss/common/utils/SystemUtils.java b/common_base/src/main/java/com/wss/common/utils/SystemUtils.java new file mode 100644 index 0000000..54c55a1 --- /dev/null +++ b/common_base/src/main/java/com/wss/common/utils/SystemUtils.java @@ -0,0 +1,247 @@ +package com.wss.common.utils; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.os.Build; +import android.provider.Settings; + +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.security.MessageDigest; +import java.util.Locale; +import java.util.UUID; + +/** + * Describe:系统工具类 + * Created by 吴天强 on 2019/5/5. + */ +public class SystemUtils { + /** + * 获取当前手机系统语言。 + * + * @return 返回当前系统语言。例如:当前设置的是“中文-中国”,则返回“zh-CN” + */ + @NotNull + public static String getSystemLanguage() { + return Locale.getDefault().getLanguage(); + } + + /** + * 获取当前系统上的语言列表(Locale列表) + * + * @return 语言列表 + */ + @NotNull + public static Locale[] getSystemLanguageList() { + return Locale.getAvailableLocales(); + } + + /** + * 获取当前手机系统版本号 + * + * @return 系统版本号 + */ + @Contract(pure = true) + public static String getSystemVersion() { + return android.os.Build.VERSION.RELEASE; + } + + /** + * 获取手机型号 + * + * @return 手机型号 + */ + @Contract(pure = true) + public static String getSystemModel() { + return android.os.Build.MODEL; + } + + /** + * 获取手机厂商 + * + * @return 手机厂商 + */ + @Contract(pure = true) + public static String getDeviceBrand() { + return android.os.Build.BRAND; + } + + /** + * 获取手机IMEI(需要“android.permission.READ_PHONE_STATE”权限) + * + * @return 手机IMEI + */ + @Nullable + public static String getDeviceId(@NotNull Context context) { + StringBuilder sbDeviceId = new StringBuilder(); + + //获得设备默认IMEI(>=6.0 需要ReadPhoneState权限) + //获得AndroidId(无需权限) + String androidId = getAndroidId(context); + //获得设备序列号(无需权限) + String serial = getSerial(); + //获得硬件uuid(根据硬件相关属性,生成uuid)(无需权限) + String uuid = getDeviceUUID().replace("-", ""); + //追加androidId + if (androidId != null && androidId.length() > 0) { + sbDeviceId.append(androidId); + sbDeviceId.append("|"); + } + //追加serial + if (serial != null && serial.length() > 0) { + sbDeviceId.append(serial); + sbDeviceId.append("|"); + } + //追加硬件uuid + if (uuid.length() > 0) { + sbDeviceId.append(uuid); + } + + //生成SHA1,统一DeviceId长度 + if (sbDeviceId.length() > 0) { + try { + byte[] hash = getHashByString(sbDeviceId.toString()); + String sha1 = bytesToHex(hash); + if (sha1.length() > 0) { + //返回最终的DeviceId + return sha1; + } + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + //如果以上硬件标识数据均无法获得, + //则DeviceId默认使用系统随机数,这样保证DeviceId不为空 + return UUID.randomUUID().toString().replace("-", ""); + } + + + /** + * 获得设备的AndroidId + * + * @param context 上下文 + * @return 设备的AndroidId + */ + @SuppressLint("HardwareIds") + private static String getAndroidId(Context context) { + try { + return Settings.Secure.getString(context.getContentResolver(), + Settings.Secure.ANDROID_ID); + } catch (Exception ex) { + ex.printStackTrace(); + } + return ""; + } + + /** + * 获得设备序列号(如:WTK7N16923005607), 个别设备无法获取 + * + * @return 设备序列号 + */ + private static String getSerial() { + try { + return Build.SERIAL; + } catch (Exception ex) { + ex.printStackTrace(); + } + return ""; + } + + /** + * 获得设备硬件uuid + * 使用硬件信息,计算出一个随机数 + * + * @return 设备硬件uuid + */ + @NotNull + private static String getDeviceUUID() { + try { + String dev = "3883756" + + Build.BOARD.length() % 10 + + Build.BRAND.length() % 10 + + Build.DEVICE.length() % 10 + + Build.HARDWARE.length() % 10 + + Build.ID.length() % 10 + + Build.MODEL.length() % 10 + + Build.PRODUCT.length() % 10 + + Build.SERIAL.length() % 10; + return new UUID(dev.hashCode(), + Build.SERIAL.hashCode()).toString(); + } catch (Exception ex) { + ex.printStackTrace(); + return ""; + } + } + + /** + * 取SHA1 + * + * @param data 数据 + * @return 对应的hash值 + */ + private static byte[] getHashByString(String data) { + try { + MessageDigest messageDigest = MessageDigest.getInstance("SHA1"); + messageDigest.reset(); + messageDigest.update(data.getBytes("UTF-8")); + return messageDigest.digest(); + } catch (Exception e) { + return "".getBytes(); + } + } + + /** + * 转16进制字符串 + * + * @param data 数据 + * @return 16进制字符串 + */ + @NotNull + private static String bytesToHex(@NotNull byte[] data) { + StringBuilder sb = new StringBuilder(); + String stmp; + for (byte datum : data) { + stmp = (Integer.toHexString(datum & 0xFF)); + if (stmp.length() == 1) { + sb.append("0"); + } + sb.append(stmp); + } + return sb.toString().toUpperCase(Locale.CHINA); + } + + + public static int getStatusBarHeight(@NotNull Context context) { + int result = 0; + int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android"); + if (resourceId > 0) { + result = context.getResources().getDimensionPixelSize(resourceId); + } + return result; + } + + public static int getScreenWidth(Context context) { + int screenWith = -1; + try { + screenWith = context.getResources().getDisplayMetrics().widthPixels; + } catch (Exception e) { + e.printStackTrace(); + } + return screenWith; + } + + public static int getScreenHeight(Context context) { + int screenHeight = -1; + try { + screenHeight = context.getResources().getDisplayMetrics().heightPixels; + } catch (Exception e) { + e.printStackTrace(); + } + return screenHeight; + } + + +} diff --git a/common_base/src/main/java/com/wss/common/utils/ToastUtils.java b/common_base/src/main/java/com/wss/common/utils/ToastUtils.java index 109f3f5..4ed6680 100644 --- a/common_base/src/main/java/com/wss/common/utils/ToastUtils.java +++ b/common_base/src/main/java/com/wss/common/utils/ToastUtils.java @@ -1,44 +1,382 @@ package com.wss.common.utils; +import android.app.AppOpsManager; +import android.app.Application; +import android.app.NotificationManager; import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.content.res.Resources; +import android.graphics.drawable.GradientDrawable; +import android.os.Build; +import android.util.TypedValue; +import android.view.Gravity; import android.view.View; +import android.view.ViewGroup; import android.widget.TextView; import android.widget.Toast; -import com.wss.common.base.R; +import com.wss.common.utils.toast.BaseToast; +import com.wss.common.utils.toast.IToastInterceptor; +import com.wss.common.utils.toast.IToastStrategy; +import com.wss.common.utils.toast.IToastStyle; +import com.wss.common.utils.toast.SafeToast; +import com.wss.common.utils.toast.SupportToast; +import com.wss.common.utils.toast.ToastInterceptor; +import com.wss.common.utils.toast.ToastStrategy; +import com.wss.common.utils.toast.style.ToastBlackStyle; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; /** * Describe:Toast * Created by 吴天强 on 2017/11/2. */ +public final class ToastUtils { + + private static IToastInterceptor sInterceptor; + + private static IToastStrategy sStrategy; + + private static Toast sToast; + + /** + * 不允许外部实例化 + */ + private ToastUtils() { + } + + /** + * 初始化 ToastUtils,在 Application 中初始化 + * + * @param application 应用的上下文 + */ + public static void init(Application application) { + init(application, new ToastBlackStyle(application)); + } + + /** + * 初始化 ToastUtils 及样式 + * + * @param application 应用的上下文 + * @param style Toast样式 + */ + public static void init(Application application, IToastStyle style) { + checkNullPointer(application); + // 初始化 Toast 拦截器 + if (sInterceptor == null) { + setToastInterceptor(new ToastInterceptor()); + } + + // 初始化 Toast 显示处理器 + if (sStrategy == null) { + setToastStrategy(new ToastStrategy()); + } + + // 初始化吐司 + if (areNotificationsEnabled(application)) { + if (Build.VERSION.SDK_INT == Build.VERSION_CODES.N_MR1) { + // 解决 Android 7.1 上主线程被阻塞后吐司会报错的问题 + setToast(new SafeToast(application)); + } else { + setToast(new BaseToast(application)); + } + } else { + // 解决关闭通知栏权限后 Toast 不显示的问题 + setToast(new SupportToast(application)); + } -public class ToastUtils { + // 设置 Toast 视图 + setView(createTextView(application, style)); - public static void show(Context context, int strings) { - show(context, context.getString(strings)); + // 设置 Toast 重心 + setGravity(style.getGravity(), style.getXOffset(), style.getYOffset()); } + /** + * 显示一个对象的吐司 + * + * @param object 对象 + */ + public static void show(Object object) { + show(object != null ? object.toString() : "null"); + } + + /** + * 显示一个吐司 + * + * @param id 如果传入的是正确的 string id 就显示对应字符串 + * 如果不是则显示一个整数的string + */ + public static void show(int id) { + checkToastState(); + try { + // 如果这是一个资源 id + show(getContext().getResources().getText(id)); + } catch (Resources.NotFoundException ignored) { + // 如果这是一个 int 整数 + show(String.valueOf(id)); + } + } + + /** + * 显示一个吐司 + * + * @param id 资源 id + * @param args 参数集 + */ + public static void show(int id, Object... args) { + show(getContext().getResources().getString(id), args); + } + + /** + * 显示一个吐司 + * + * @param format 原字符串 + * @param args 参数集 + */ + public static void show(String format, Object... args) { + show(String.format(format, args)); + } + + /** + * 显示一个吐司 + * + * @param text 需要显示的文本 + */ + public static synchronized void show(CharSequence text) { + checkToastState(); + if (sInterceptor.intercept(sToast, text)) { + return; + } + sStrategy.show(text); + } + + + //***************************************兼容老的Toast的调用方法 start************************************* + + /** + * 老的Toast调用方法 + * + * @param context context + * @param text 显示的内容 + */ public static void show(Context context, String text) { -// show(context, title, Gravity.BOTTOM); - Toast.makeText(context, text, Toast.LENGTH_SHORT).show(); + show(text); + } + //***************************************兼容老的Toast的调用方法 end************************************* + + /** + * 取消吐司的显示 + */ + public static synchronized void cancel() { + checkToastState(); + + sStrategy.cancel(); + } + + /** + * 设置吐司的位置 + * + * @param gravity 重心 + * @param xOffset x轴偏移 + * @param yOffset y轴偏移 + */ + private static void setGravity(int gravity, int xOffset, int yOffset) { + checkToastState(); + gravity = Gravity.getAbsoluteGravity(gravity, sToast.getView().getResources().getConfiguration().getLayoutDirection()); + sToast.setGravity(gravity, xOffset, yOffset); } /** - * 自定义显示Toast弹出提示框 + * 给当前Toast设置新的布局,具体实现可看{@link BaseToast#setView(View)} + */ + public static void setView(int id) { + checkToastState(); + + setView(View.inflate(getContext(), id, null)); + } + + public static void setView(View view) { + checkToastState(); + + // 这个 View 不能为空 + checkNullPointer(view); + + // 当前必须用 Application 的上下文创建的 View,否则可能会导致内存泄露 + Context context = view.getContext(); + if (!(context instanceof Application)) { + throw new IllegalArgumentException("The view must be initialized using the context of the application"); + } + + // 如果吐司已经创建,就重新初始化吐司 + if (sToast != null) { + // 取消原有吐司的显示 + sToast.cancel(); + sToast.setView(view); + } + } + + /** + * 获取当前 Toast 的视图 + */ + @SuppressWarnings("unchecked") + public static V getView() { + checkToastState(); + + return (V) sToast.getView(); + } + + /** + * 初始化全局的Toast样式 * - * @param s s - * @param gravity 弹出位置 + * @param style 样式实现类,框架已经实现三种不同的样式 + */ + public static void initStyle(IToastStyle style) { + checkNullPointer(style); + // 如果吐司已经创建,就重新初始化吐司 + if (sToast != null) { + // 取消原有吐司的显示 + sToast.cancel(); + sToast.setView(createTextView(getContext(), style)); + sToast.setGravity(style.getGravity(), style.getXOffset(), style.getYOffset()); + } + } + + /** + * 设置当前Toast对象 + */ + public static void setToast(Toast toast) { + checkNullPointer(toast); + if (sToast != null && toast.getView() == null) { + // 移花接木 + toast.setView(sToast.getView()); + toast.setGravity(sToast.getGravity(), sToast.getXOffset(), sToast.getYOffset()); + toast.setMargin(sToast.getHorizontalMargin(), sToast.getVerticalMargin()); + } + sToast = toast; + if (sStrategy != null) { + sStrategy.bind(sToast); + } + } + + /** + * 设置 Toast 显示策略 + */ + public static void setToastStrategy(IToastStrategy handler) { + checkNullPointer(handler); + sStrategy = handler; + if (sToast != null) { + sStrategy.bind(sToast); + } + } + + /** + * 设置 Toast 拦截器(可以根据显示的内容决定是否拦截这个Toast) + * 场景:打印 Toast 内容日志、根据 Toast 内容是否包含敏感字来动态切换其他方式显示(这里可以使用我的另外一套框架 XToast) + */ + public static void setToastInterceptor(IToastInterceptor interceptor) { + checkNullPointer(interceptor); + sInterceptor = interceptor; + } + + /** + * 获取当前Toast对象 + */ + public static Toast getToast() { + return sToast; + } + + /** + * 检查吐司状态,如果未初始化请先调用{@link com.wss.common.utils.ToastUtils#init(Application)} + */ + private static void checkToastState() { + // 吐司工具类还没有被初始化,必须要先调用init方法进行初始化 + if (sToast == null) { + throw new IllegalStateException("ToastUtils has not been initialized"); + } + } + + /** + * 检查对象是否为空 + */ + private static void checkNullPointer(Object object) { + if (object == null) { + throw new NullPointerException("are you ok?"); + } + } + + /** + * 生成默认的 TextView 对象 + */ + private static TextView createTextView(Context context, IToastStyle style) { + + GradientDrawable drawable = new GradientDrawable(); + // 设置背景色 + drawable.setColor(style.getBackgroundColor()); + // 设置圆角大小 + drawable.setCornerRadius(style.getCornerRadius()); + + TextView textView = new TextView(context); + textView.setId(android.R.id.message); + textView.setTextColor(style.getTextColor()); + textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, style.getTextSize()); + + // 适配布局反方向 + textView.setPaddingRelative(style.getPaddingStart(), style.getPaddingTop(), style.getPaddingEnd(), style.getPaddingBottom()); + + textView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); + + // setBackground API 版本兼容 + textView.setBackground(drawable); + + // 设置 Z 轴阴影 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + textView.setZ(style.getZ()); + } + + // 设置最大显示行数 + if (style.getMaxLines() > 0) { + textView.setMaxLines(style.getMaxLines()); + } + + return textView; + } + + /** + * 获取上下文对象 + */ + private static Context getContext() { + checkToastState(); + return sToast.getView().getContext(); + } + + /** + * 检查通知栏权限有没有开启 + * 参考 SupportCompat 包中的方法: NotificationManagerCompat.from(context).areNotificationsEnabled(); */ + private static boolean areNotificationsEnabled(Context context) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + return manager != null && manager.areNotificationsEnabled(); + } else { + AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); + ApplicationInfo appInfo = context.getApplicationInfo(); + String packageName = context.getApplicationContext().getPackageName(); + int uid = appInfo.uid; - public static void show(Context context, CharSequence s, int gravity) { - Toast toast = new Toast(context); - View toastView = View.inflate(context, R.layout.toast, null); - toast.setView(toastView); - toast.setDuration(Toast.LENGTH_SHORT); - TextView textView = toastView.findViewById(R.id.tv_message); - textView.setText(s); - toast.setGravity(gravity, 0, 100); - toast.show(); + try { + Class appOpsClass = Class.forName(AppOpsManager.class.getName()); + Method checkOpNoThrowMethod = appOpsClass.getMethod("checkOpNoThrow", Integer.TYPE, Integer.TYPE, String.class); + Field opPostNotificationValue = appOpsClass.getDeclaredField("OP_POST_NOTIFICATION"); + int value = Integer.parseInt(String.valueOf(opPostNotificationValue.get(Integer.class))); + return ((int) checkOpNoThrowMethod.invoke(appOps, value, uid, packageName) == AppOpsManager.MODE_ALLOWED); + } catch (ClassNotFoundException | NoSuchMethodException | NoSuchFieldException + | InvocationTargetException | IllegalAccessException | RuntimeException ignored) { + return true; + } + } } } diff --git a/common_base/src/main/java/com/wss/common/utils/UserInfoUtils.java b/common_base/src/main/java/com/wss/common/utils/UserInfoUtils.java deleted file mode 100644 index d898e31..0000000 --- a/common_base/src/main/java/com/wss/common/utils/UserInfoUtils.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.wss.common.utils; - -import com.wss.common.base.BaseApplication; -import com.wss.common.bean.User; -import com.wss.common.constants.CacheKey; - -/** - * Describe:用户信息帮助类 - * Created by 吴天强 on 2018/11/13. - */ - -public class UserInfoUtils { - - - /** - * 保存用户信息 - * - * @param user user - */ - public static void saveUser(User user) { - CacheUtils.get(BaseApplication.getApplication()) - .put(CacheKey.USER_INFO, user); - CacheUtils.get(BaseApplication.getApplication()) - .put(CacheKey.USER_LOGGED, true); - } - - /** - * 获取用户信息 - * - * @return user - */ - public static User getUser() { - User user = (User) CacheUtils.get(BaseApplication.getApplication()) - .getAsObject(CacheKey.USER_INFO); - if (user == null) { - user = new User(); - } - return user; - } - - /** - * 清除用户信息 - */ - public static void cleanUser() { - saveUser(null); - CacheUtils.get(BaseApplication.getApplication()) - .put(CacheKey.USER_LOGGED, false); - } - - /** - * 是否登录 - * - * @return boolean - */ - public static boolean isLogged() { - Object result = CacheUtils.get(BaseApplication.getApplication()) - .getAsObject(CacheKey.USER_LOGGED); - return result != null && (boolean) result; - } - -} diff --git a/common_base/src/main/java/com/wss/common/utils/Utils.java b/common_base/src/main/java/com/wss/common/utils/Utils.java index fe99f9f..63c460f 100644 --- a/common_base/src/main/java/com/wss/common/utils/Utils.java +++ b/common_base/src/main/java/com/wss/common/utils/Utils.java @@ -1,35 +1,42 @@ package com.wss.common.utils; import android.content.Context; +import android.content.Intent; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.res.AssetManager; +import android.graphics.drawable.GradientDrawable; +import android.net.Uri; +import android.widget.TextView; import com.wss.common.base.BaseApplication; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.regex.Matcher; import java.util.regex.Pattern; +import androidx.annotation.NonNull; + /** * Describe:工具类 * Created by 吴天强 on 2018/10/15. */ - public class Utils { - /** * 读取 asset下的文件 * * @param context context * @param fileName fileName - * @return + * @return String */ - public static String getAssetFileData(Context context, String fileName) { - + @NonNull + public static String getAssetFileData(@NotNull Context context, String fileName) { StringBuilder stringBuilder = new StringBuilder(); try { AssetManager assetManager = context.getAssets(); @@ -76,13 +83,23 @@ public static boolean isNumber(String str) { return isNum.matches(); } + /** + * 判断是否为电话,只校验位数 + * + * @param str str + * @return boolean + */ + public static boolean isPhone(String str) { + return ValidUtils.isValid(str) && str.length() == 11; + } + /** * 获取APP包名 * * @return String */ public static String getPackageName() { - return BaseApplication.getApplication().getPackageName(); + return BaseApplication.i().getPackageName(); } /** @@ -91,7 +108,7 @@ public static String getPackageName() { * @return String */ public static String getVersionName() { - PackageManager packageManager = BaseApplication.getApplication().getPackageManager(); + PackageManager packageManager = BaseApplication.i().getPackageManager(); try { PackageInfo packageInfo = packageManager.getPackageInfo(getPackageName(), 0); return packageInfo.versionName; @@ -107,7 +124,7 @@ public static String getVersionName() { * @return Integer */ public static Integer getVersionCode() { - PackageManager packageManager = BaseApplication.getApplication().getPackageManager(); + PackageManager packageManager = BaseApplication.i().getPackageManager(); try { PackageInfo packageInfo = packageManager.getPackageInfo( getPackageName(), 0); @@ -117,4 +134,71 @@ public static Integer getVersionCode() { } return 0; } + + /** + * 设置TextView的背景色 + * + * @param textView textView + * @param color 颜色 + */ + public static void setTextViewDrawable(@NotNull TextView textView, int color) { + setTextViewDrawable(textView, color, 4); + } + + /** + * 设置TextView的背景色 + * + * @param textView textView + * @param color 颜色 + * @param radius 圆角角度 + */ + public static void setTextViewDrawable(@NotNull TextView textView, int color, float radius) { + GradientDrawable drawable = new GradientDrawable(); + drawable.setCornerRadius(radius); + drawable.setColor(color); + textView.setBackground(drawable); + } + + /** + * 跳转浏览器 + */ + public static void toSystemBrowser(@NonNull Context context, String url) { + //应用内下载失败 跳转浏览器下载 + Intent intent = new Intent(); + intent.setAction("android.intent.action.VIEW"); + Uri contentUrl = Uri.parse(url); + intent.setData(contentUrl); + context.startActivity(intent); + } + + + + + /** + * 电话号码中间替换成* + * + * @param phone 原电话 + * @return 替换后的电话 + */ + @Contract("_ -> param1") + public static String replacePhone(String phone) { + if (!isPhone(phone)) { + return phone; + } + String replace = phone.substring(3, 7); + return phone.replace(replace, "****"); + } + + /** + * 把等于null的字符串转成“” + * + * @param text 原字符串 + * @return 转换后字符串 + */ + public static String checkText(String text) { + if (!ValidUtils.isValid(text)) { + return ""; + } + return text; + } } diff --git a/common_base/src/main/java/com/wss/common/utils/ValidUtils.java b/common_base/src/main/java/com/wss/common/utils/ValidUtils.java new file mode 100644 index 0000000..822401d --- /dev/null +++ b/common_base/src/main/java/com/wss/common/utils/ValidUtils.java @@ -0,0 +1,39 @@ +package com.wss.common.utils; + +import android.text.TextUtils; + +import org.jetbrains.annotations.Contract; + +import java.util.Collection; +import java.util.Map; + +/** + * 对象空判断验证类 + * Created by 吴天强 on 2017/12/3. + */ +public class ValidUtils { + @Contract(value = "null -> false", pure = true) + public static boolean isValid(Collection collection) { + return collection != null && !collection.isEmpty(); + } + + @Contract("null, _ -> false") + public static boolean isValid(Collection collection, int position) { + return collection != null && !collection.isEmpty() && collection.size() > position; + } + + @Contract(value = "null -> false", pure = true) + public static boolean isValid(Map map) { + return map != null && !map.isEmpty(); + } + + @Contract("null -> false") + public static boolean isValid(String str) { + return !TextUtils.isEmpty(str); + } + + @Contract(value = "null -> false; !null -> true", pure = true) + public static boolean isValid(Object obj) { + return obj != null; + } +} diff --git a/common_base/src/main/java/com/wss/common/utils/ZipUtils.java b/common_base/src/main/java/com/wss/common/utils/ZipUtils.java deleted file mode 100644 index eafd00a..0000000 --- a/common_base/src/main/java/com/wss/common/utils/ZipUtils.java +++ /dev/null @@ -1,390 +0,0 @@ -package com.wss.common.utils; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.UnsupportedEncodingException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Enumeration; -import java.util.zip.ZipEntry; -import java.util.zip.ZipException; -import java.util.zip.ZipFile; -import java.util.zip.ZipOutputStream; - -/** - * Java utils 实现的Zip工具 - * - * @author miaowei - */ -public class ZipUtils { - - private static final int BUFF_SIZE = 1024 * 1024; // 1M Byte - - /** - * 批量压缩文件(夹) - * - * @param resFileList 要压缩的文件(夹)列表 - * @param zipFile 生成的压缩文件 - * @throws IOException 当压缩过程出错时抛出 - */ - public static void zipFiles(Collection resFileList, File zipFile) throws IOException { - if (resFileList != null && zipFile != null) { - ZipOutputStream zipout = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFile), BUFF_SIZE)); - for (File resFile : resFileList) { - zipFile(resFile, zipout, ""); - } - zipout.close(); - } - } - - /** - * 批量压缩文件(夹) - * - * @param resFileList 要压缩的文件(夹)列表 - * @param zipFile 生成的压缩文件 - * @param comment 压缩文件的注释 - * @throws IOException 当压缩过程出错时抛出 - */ - public static void zipFiles(Collection resFileList, File zipFile, String comment) throws IOException { - ZipOutputStream zipout = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFile), BUFF_SIZE)); - for (File resFile : resFileList) { - zipFile(resFile, zipout, ""); - } - zipout.setComment(comment); - zipout.close(); - } - - /** - * 解压缩一个文件 - * - * @param zipFile 压缩文件 - * @param folderPath 解压缩的目标目录 - * @throws IOException 当解压缩过程出错时抛出 - */ - public static void upZipFile(File zipFile, String folderPath) throws IOException { - File desDir = new File(folderPath); - if (!desDir.exists()) { - desDir.mkdirs(); - } - ZipFile zf = new ZipFile(zipFile); - for (Enumeration entries = zf.entries(); entries.hasMoreElements(); ) { - ZipEntry entry = ((ZipEntry) entries.nextElement()); - if (entry.isDirectory()) { - - continue; - } - InputStream in = zf.getInputStream(entry); - String str = folderPath + File.separator + entry.getName(); - str = new String(str.getBytes(), "utf-8"); - File desFile = new File(str); - if (!desFile.exists()) { - File fileParentDir = desFile.getParentFile(); - if (!fileParentDir.exists()) { - fileParentDir.mkdirs(); - } - desFile.createNewFile(); - } - OutputStream out = new FileOutputStream(desFile); - byte buffer[] = new byte[BUFF_SIZE]; - int realLength; - while ((realLength = in.read(buffer)) > 0) { - out.write(buffer, 0, realLength); - } - in.close(); - out.close(); - } - } - - /** - * 解压文件名包含传入文字的文件 - * - * @param zipFile 压缩文件 - * @param folderPath 目标文件夹 - * @param nameContains 传入的文件匹配名 - * @throws ZipException 压缩格式有误时抛出 - * @throws IOException IO错误时抛出 - */ - public static ArrayList upZipSelectedFile(File zipFile, String folderPath, String nameContains) throws IOException { - ArrayList fileList = new ArrayList(); - - File desDir = new File(folderPath); - if (!desDir.exists()) { - desDir.mkdir(); - } - - ZipFile zf = new ZipFile(zipFile); - for (Enumeration entries = zf.entries(); entries.hasMoreElements(); ) { - ZipEntry entry = ((ZipEntry) entries.nextElement()); - if (entry.getName().contains(nameContains)) { - InputStream in = zf.getInputStream(entry); - String str = folderPath + File.separator + entry.getName(); - str = new String(str.getBytes("utf-8"), "gbk"); - // str.getBytes("GB2312"),"8859_1" 输出 - // str.getBytes("8859_1"),"GB2312" 输入 - File desFile = new File(str); - if (!desFile.exists()) { - File fileParentDir = desFile.getParentFile(); - if (!fileParentDir.exists()) { - fileParentDir.mkdirs(); - } - desFile.createNewFile(); - } - OutputStream out = new FileOutputStream(desFile); - byte buffer[] = new byte[BUFF_SIZE]; - int realLength; - while ((realLength = in.read(buffer)) > 0) { - out.write(buffer, 0, realLength); - } - in.close(); - out.close(); - fileList.add(desFile); - } - } - return fileList; - } - - /** - * 获得压缩文件内文件列表 - * - * @param zipFile 压缩文件 - * @return 压缩文件内文件名称 - * @throws ZipException 压缩文件格式有误时抛出 - * @throws IOException 当解压缩过程出错时抛出 - */ - public static ArrayList getEntriesNames(File zipFile) throws IOException { - ArrayList entryNames = new ArrayList(); - Enumeration entries = getEntriesEnumeration(zipFile); - while (entries.hasMoreElements()) { - ZipEntry entry = ((ZipEntry) entries.nextElement()); - entryNames.add(new String(getEntryName(entry).getBytes("GB2312"), "8859_1")); - } - return entryNames; - } - - /** - * 获得压缩文件内压缩文件对象以取得其属性 - * - * @param zipFile 压缩文件 - * @return 返回一个压缩文件列表 - * @throws ZipException 压缩文件格式有误时抛出 - * @throws IOException IO操作有误时抛出 - */ - public static Enumeration getEntriesEnumeration(File zipFile) throws IOException { - ZipFile zf = new ZipFile(zipFile); - return zf.entries(); - - } - - /** - * 取得压缩文件对象的注释 - * - * @param entry 压缩文件对象 - * @return 压缩文件对象的注释 - * @throws UnsupportedEncodingException - */ - public static String getEntryComment(ZipEntry entry) throws UnsupportedEncodingException { - return new String(entry.getComment().getBytes("GB2312"), "8859_1"); - } - - /** - * 取得压缩文件对象的名称 - * - * @param entry 压缩文件对象 - * @return 压缩文件对象的名称 - * @throws UnsupportedEncodingException - */ - public static String getEntryName(ZipEntry entry) throws UnsupportedEncodingException { - return new String(entry.getName().getBytes("GB2312"), "8859_1"); - } - - /** - * 压缩文件 - * - * @param resFile 需要压缩的文件(夹) - * @param zipout 压缩的目的文件 - * @param rootpath 压缩的文件路径 - * @throws FileNotFoundException 找不到文件时抛出 - * @throws IOException 当压缩过程出错时抛出 - */ - private static void zipFile(File resFile, ZipOutputStream zipout, String rootpath) throws IOException { - rootpath = rootpath + (rootpath.trim().length() == 0 ? "" : File.separator) + resFile - .getName(); - rootpath = new String(rootpath.getBytes(), "utf-8"); - if (resFile.isDirectory()) { - File[] fileList = resFile.listFiles(); - for (File file : fileList) { - zipFile(file, zipout, rootpath); - } - } else { - byte buffer[] = new byte[BUFF_SIZE]; - BufferedInputStream in = new BufferedInputStream(new FileInputStream(resFile), BUFF_SIZE); - zipout.putNextEntry(new ZipEntry(rootpath)); - int realLength; - while ((realLength = in.read(buffer)) != -1) { - zipout.write(buffer, 0, realLength); - } - in.close(); - zipout.flush(); - zipout.closeEntry(); - } - } - - //第二种实现 - public static void zip(String src, String dest) throws IOException { - // 提供了一个数据项压缩成一个ZIP归档输出流 - ZipOutputStream out = null; - try { - - //DirTraversal.makeRootDirectory(dest); - //File outFile = DirTraversal.getFilePath(dest,"cache.zip"); - - File outFile = new File(dest);// 源文件或者目录 - File fileOrDirectory = new File(src);// 压缩文件路径 - out = new ZipOutputStream(new FileOutputStream(outFile)); - // 如果此文件是一个文件,否则为false。 - if (fileOrDirectory.isFile()) { - zipFileOrDirectory(out, fileOrDirectory, ""); - } else { - // 返回一个文件或空阵列。 - File[] entries = fileOrDirectory.listFiles(); - for (int i = 0; i < entries.length; i++) { - // 递归压缩,更新curPaths - zipFileOrDirectory(out, entries[i], ""); - } - } - } catch (IOException ex) { - ex.printStackTrace(); - } finally { - // 关闭输出流 - if (out != null) { - try { - out.close(); - } catch (IOException ex) { - ex.printStackTrace(); - } - } - } - } - - private static void zipFileOrDirectory(ZipOutputStream out, File fileOrDirectory, String curPath) throws IOException { - // 从文件中读取字节的输入流 - FileInputStream in = null; - try { - // 如果此文件是一个目录,否则返回false。 - if (!fileOrDirectory.isDirectory()) { - // 压缩文件 - byte[] buffer = new byte[4096]; - int bytes_read; - in = new FileInputStream(fileOrDirectory); - // 实例代表一个条目内的ZIP归档 - ZipEntry entry = new ZipEntry(curPath + fileOrDirectory.getName()); - // 条目的信息写入底层流 - out.putNextEntry(entry); - while ((bytes_read = in.read(buffer)) != -1) { - out.write(buffer, 0, bytes_read); - } - out.closeEntry(); - } else { - // 压缩目录 - File[] entries = fileOrDirectory.listFiles(); - for (int i = 0; i < entries.length; i++) { - // 递归压缩,更新curPaths - zipFileOrDirectory(out, entries[i], curPath + fileOrDirectory.getName() + "/"); - } - } - } catch (IOException ex) { - ex.printStackTrace(); - // throw ex; - } finally { - if (in != null) { - try { - in.close(); - } catch (IOException ex) { - ex.printStackTrace(); - } - } - } - } - - @SuppressWarnings("unchecked") - public static void unzip(String zipFileName, String outputDirectory) throws IOException { - ZipFile zipFile = null; - try { - zipFile = new ZipFile(zipFileName); - Enumeration e = zipFile.entries(); - ZipEntry zipEntry = null; - File dest = new File(outputDirectory); - dest.mkdirs(); - while (e.hasMoreElements()) { - zipEntry = (ZipEntry) e.nextElement(); - String entryName = zipEntry.getName(); - InputStream in = null; - FileOutputStream out = null; - try { - if (zipEntry.isDirectory()) { - String name = zipEntry.getName(); - name = name.substring(0, name.length() - 1); - File f = new File(outputDirectory + File.separator + name); - f.mkdirs(); - } else { - int index = entryName.lastIndexOf("\\"); - if (index != -1) { - File df = new File(outputDirectory + File.separator + entryName - .substring(0, index)); - df.mkdirs(); - } - index = entryName.lastIndexOf("/"); - if (index != -1) { - File df = new File(outputDirectory + File.separator + entryName - .substring(0, index)); - df.mkdirs(); - } - File f = new File(outputDirectory + File.separator + zipEntry.getName()); - // f.createNewFile(); - in = zipFile.getInputStream(zipEntry); - out = new FileOutputStream(f); - int c; - byte[] by = new byte[1024]; - while ((c = in.read(by)) != -1) { - out.write(by, 0, c); - } - out.flush(); - } - } catch (IOException ex) { - ex.printStackTrace(); - throw new IOException("解压失败:" + ex.toString()); - } finally { - if (in != null) { - try { - in.close(); - } catch (IOException ex) { - } - } - if (out != null) { - try { - out.close(); - } catch (IOException ex) { - } - } - } - } - } catch (IOException ex) { - ex.printStackTrace(); - throw new IOException("解压失败:" + ex.toString()); - } finally { - if (zipFile != null) { - try { - zipFile.close(); - } catch (IOException ex) { - } - } - } - } -} diff --git a/common_base/src/main/java/com/wss/common/utils/toast/BaseToast.java b/common_base/src/main/java/com/wss/common/utils/toast/BaseToast.java new file mode 100644 index 0000000..47ab095 --- /dev/null +++ b/common_base/src/main/java/com/wss/common/utils/toast/BaseToast.java @@ -0,0 +1,70 @@ +package com.wss.common.utils.toast; + +import android.app.Application; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; +import android.widget.Toast; + +/** + * author : Android 轮子哥 + * github : https://github.com/getActivity/ToastUtils + * time : 2018/11/03 + * desc : Toast 基类 + */ +public class BaseToast extends Toast { + + /** 吐司消息 View */ + private TextView mMessageView; + + public BaseToast(Application application) { + super(application); + } + + @Override + public void setView(View view) { + super.setView(view); + mMessageView = getMessageView(view); + } + + @Override + public void setText(CharSequence s) { + mMessageView.setText(s); + } + + /** + * 智能获取用于显示消息的 TextView + */ + private static TextView getMessageView(View view) { + if (view instanceof TextView) { + return (TextView) view; + } else if (view.findViewById(android.R.id.message) instanceof TextView) { + return ((TextView) view.findViewById(android.R.id.message)); + } else if (view instanceof ViewGroup) { + TextView textView = findTextView((ViewGroup) view); + if (textView != null) { + return textView; + } + } + // 如果设置的布局没有包含一个 TextView 则抛出异常,必须要包含一个 TextView 作为 MessageView + throw new IllegalArgumentException("The layout must contain a TextView"); + } + + /** + * 递归获取 ViewGroup 中的 TextView 对象 + */ + private static TextView findTextView(ViewGroup group) { + for (int i = 0; i < group.getChildCount(); i++) { + View view = group.getChildAt(i); + if ((view instanceof TextView)) { + return (TextView) view; + } else if (view instanceof ViewGroup) { + TextView textView = findTextView((ViewGroup) view); + if (textView != null) { + return textView; + } + } + } + return null; + } +} \ No newline at end of file diff --git a/common_base/src/main/java/com/wss/common/utils/toast/IToastInterceptor.java b/common_base/src/main/java/com/wss/common/utils/toast/IToastInterceptor.java new file mode 100644 index 0000000..ff4bc25 --- /dev/null +++ b/common_base/src/main/java/com/wss/common/utils/toast/IToastInterceptor.java @@ -0,0 +1,21 @@ +package com.wss.common.utils.toast; + +import android.widget.Toast; + +/** + * author : Android 轮子哥 + * github : https://github.com/getActivity/ToastUtils + * time : 2019/05/19 + * desc : Toast 拦截器接口 + */ +public interface IToastInterceptor { + + /** + * 根据显示的文本决定是否拦截该 Toast + * + * @param toast Toast + * @param text 显示的Toast内容 + * @return boolean + */ + boolean intercept(Toast toast, CharSequence text); +} \ No newline at end of file diff --git a/common_base/src/main/java/com/wss/common/utils/toast/IToastStrategy.java b/common_base/src/main/java/com/wss/common/utils/toast/IToastStrategy.java new file mode 100644 index 0000000..657213b --- /dev/null +++ b/common_base/src/main/java/com/wss/common/utils/toast/IToastStrategy.java @@ -0,0 +1,40 @@ +package com.wss.common.utils.toast; + +import android.widget.Toast; + +/** + * author : Android 轮子哥 + * github : https://github.com/getActivity/ToastUtils + * time : 2019/05/19 + * desc : Toast 处理策略 + */ +public interface IToastStrategy { + + /** + * 短吐司显示的时长 + */ + int SHORT_DURATION_TIMEOUT = 1500; + /** + * 长吐司显示的时长 + */ + int LONG_DURATION_TIMEOUT = 3500; + + /** + * 绑定 Toast 对象 + * + * @param toast Toast + */ + void bind(Toast toast); + + /** + * 显示 Toast + * + * @param text 文本 + */ + void show(CharSequence text); + + /** + * 取消 Toast + */ + void cancel(); +} \ No newline at end of file diff --git a/common_base/src/main/java/com/wss/common/utils/toast/IToastStyle.java b/common_base/src/main/java/com/wss/common/utils/toast/IToastStyle.java new file mode 100644 index 0000000..ac85720 --- /dev/null +++ b/common_base/src/main/java/com/wss/common/utils/toast/IToastStyle.java @@ -0,0 +1,101 @@ +package com.wss.common.utils.toast; + +/** + * author : Android 轮子哥 + * github : https://github.com/getActivity/ToastUtils + * time : 2018/09/01 + * desc : 默认样式接口 + */ +public interface IToastStyle { + + /** + * 吐司的重心 + * + * @return 重心 + */ + int getGravity(); + + /** + * X轴偏移 + * + * @return X轴偏移 + */ + int getXOffset(); + + /** + * Y轴偏移 + * + * @return Y轴偏移 + */ + int getYOffset(); + + /** + * 吐司 Z 轴坐标 + * + * @return 吐司 Z 轴坐标 + */ + int getZ(); + + /** + * 背景圆角大小 + * + * @return 圆角大小 + */ + int getCornerRadius(); + + /** + * 背景颜色 + * + * @return 背景颜色 + */ + int getBackgroundColor(); + + /** + * 文本颜色 + * + * @return 文本颜色 + */ + int getTextColor(); + + /** + * 文本大小 + * + * @return 文本大小 + */ + float getTextSize(); + + /** + * 最大行数 + * + * @return 最大显示行数 + */ + int getMaxLines(); + + /** + * 开始内边距 + * + * @return 顶部内边距 + */ + int getPaddingStart(); + + /** + * 顶部内边距 + * + * @return 顶部内边距 + */ + int getPaddingTop(); + + /** + * 结束内边距 + * + * @return 结束内边距 + */ + int getPaddingEnd(); + + /** + * 底部内边距 + * + * @return 底部内边距 + */ + int getPaddingBottom(); +} \ No newline at end of file diff --git a/common_base/src/main/java/com/wss/common/utils/toast/SafeHandler.java b/common_base/src/main/java/com/wss/common/utils/toast/SafeHandler.java new file mode 100644 index 0000000..cb93144 --- /dev/null +++ b/common_base/src/main/java/com/wss/common/utils/toast/SafeHandler.java @@ -0,0 +1,34 @@ +package com.wss.common.utils.toast; + +import android.os.Handler; +import android.os.Message; +import android.view.WindowManager; + +/** + * author : Android 轮子哥 + * github : https://github.com/getActivity/ToastUtils + * time : 2018/12/06 + * desc : Toast 显示安全处理 + */ +final class SafeHandler extends Handler { + + private Handler mHandler; + + SafeHandler(Handler handler) { + mHandler = handler; + } + + @Override + public void handleMessage(Message msg) { + // 捕获这个异常,避免程序崩溃 + try { + // 目前发现在 Android 7.1 主线程被阻塞之后弹吐司会导致崩溃,可使用 Thread.sleep(5000) 进行复现 + // 查看源码得知 Google 已经在 Android 8.0 已经修复了此问题 + // 主线程阻塞之后 Toast 也会被阻塞,Toast 因为超时导致 Window Token 失效 + mHandler.handleMessage(msg); + } catch (WindowManager.BadTokenException | IllegalStateException ignored) { + // android.view.WindowManager$BadTokenException:Unable to add window -- token android.os.BinderProxy is not valid; is your activity running? + // java.lang.IllegalStateException:java.lang.IllegalStateException:View android.widget.LinearLayout has already been added to the window manager. + } + } +} \ No newline at end of file diff --git a/common_base/src/main/java/com/wss/common/utils/toast/SafeToast.java b/common_base/src/main/java/com/wss/common/utils/toast/SafeToast.java new file mode 100644 index 0000000..45439e5 --- /dev/null +++ b/common_base/src/main/java/com/wss/common/utils/toast/SafeToast.java @@ -0,0 +1,39 @@ +package com.wss.common.utils.toast; + +import android.app.Application; +import android.os.Handler; +import android.widget.Toast; + +import java.lang.reflect.Field; + +/** + * author : Android 轮子哥 + * github : https://github.com/getActivity/ToastUtils + * time : 2018/12/06 + * desc : Toast 显示安全处理 + */ +public final class SafeToast extends BaseToast { + + public SafeToast(Application application) { + super(application); + + // 反射 Toast 中的字段 + try { + + // 获取 mTN 字段对象 + Field mTnField = Toast.class.getDeclaredField("mTN"); + mTnField.setAccessible(true); + Object mTn = mTnField.get(this); + + // 获取 mTN 中的 mHandler 字段对象 + Field mHandlerField = mTnField.getType().getDeclaredField("mHandler"); + mHandlerField.setAccessible(true); + Handler mHandler = (Handler) mHandlerField.get(mTn); + + // 偷梁换柱 + mHandlerField.set(mTn, new SafeHandler(mHandler)); + + } catch (IllegalAccessException | NoSuchFieldException ignored) { + } + } +} \ No newline at end of file diff --git a/common_base/src/main/java/com/wss/common/utils/toast/SupportToast.java b/common_base/src/main/java/com/wss/common/utils/toast/SupportToast.java new file mode 100644 index 0000000..0160916 --- /dev/null +++ b/common_base/src/main/java/com/wss/common/utils/toast/SupportToast.java @@ -0,0 +1,32 @@ +package com.wss.common.utils.toast; + +import android.app.Application; + +/** + * author : Android 轮子哥 + * github : https://github.com/getActivity/ToastUtils + * time : 2018/11/02 + * desc : Toast 无通知栏权限兼容 + */ +public final class SupportToast extends BaseToast { + + /** 吐司弹窗显示辅助类 */ + private final ToastHelper mToastHelper; + + public SupportToast(Application application) { + super(application); + mToastHelper = new ToastHelper(this, application); + } + + @Override + public void show() { + // 显示吐司 + mToastHelper.show(); + } + + @Override + public void cancel() { + // 取消显示 + mToastHelper.cancel(); + } +} \ No newline at end of file diff --git a/common_base/src/main/java/com/wss/common/utils/toast/ToastHelper.java b/common_base/src/main/java/com/wss/common/utils/toast/ToastHelper.java new file mode 100644 index 0000000..da4ee47 --- /dev/null +++ b/common_base/src/main/java/com/wss/common/utils/toast/ToastHelper.java @@ -0,0 +1,152 @@ +package com.wss.common.utils.toast; + +import android.app.Activity; +import android.app.Application; +import android.content.Context; +import android.graphics.PixelFormat; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.view.WindowManager; +import android.widget.Toast; + +/** + * author : Android 轮子哥 + * github : https://github.com/getActivity/ToastUtils + * time : 2018/11/02 + * desc : 自定义 Toast 辅助类 + */ +final class ToastHelper extends Handler { + + /** + * 当前的吐司对象 + */ + private final Toast mToast; + + /** + * WindowManager 辅助类 + */ + private final WindowHelper mWindowHelper; + + /** + * 当前应用的包名 + */ + private final String mPackageName; + + /** + * 当前是否已经显示 + */ + private boolean mShow; + + ToastHelper(Toast toast, Application application) { + super(Looper.getMainLooper()); + mToast = toast; + mPackageName = application.getPackageName(); + mWindowHelper = WindowHelper.register(this, application); + } + + @Override + public void handleMessage(Message msg) { + // 收到取消显示的消息 + cancel(); + } + + boolean isShow() { + return mShow; + } + + void setShow(boolean show) { + mShow = show; + } + + /*** + * 显示吐司弹窗 + */ + void show() { + if (!isShow()) { + /* + 这里解释一下,为什么不复用 WindowManager.LayoutParams 这个对象 + 因为如果复用了,不同 Activity 之间不能共用一个,第一个 Activity 调用显示方法可以显示出来,但是会导致后面的 Activity 都显示不出来 + 又或者说,非第一次调用显示方法的 Activity 都会把这个显示请求推送给之前第一个调用显示的 Activity 上面,如果第一个 Activity 已经销毁,还会报以下异常 + android.view.WindowManager$BadTokenException: + Unable to add window -- token android.os.BinderProxy@ef1ccb6 is not valid; is your activity running? + */ + final WindowManager.LayoutParams params = new WindowManager.LayoutParams(); + + /* + // 为什么不能加 TYPE_TOAST,因为通知权限在关闭后设置显示的类型为 Toast 会报错 + // android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running? + params.type = WindowManager.LayoutParams.TYPE_TOAST; + */ + + /* + // 这个是旧版本的写法,新版本已经废弃,因为 Activity onPause 方法被调用后这里把 Toast 取消显示了,这样做的原因:防止内存泄露 + // 判断是否为 Android 6.0 及以上系统并且有悬浮窗权限 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && Settings.canDrawOverlays(mToast.getView().getContext())) { + // 解决使用 WindowManager 创建的 Toast 只能显示在当前 Activity 的问题 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + params.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; + } else { + params.type = WindowManager.LayoutParams.TYPE_PHONE; + } + } + */ + params.height = WindowManager.LayoutParams.WRAP_CONTENT; + params.width = WindowManager.LayoutParams.WRAP_CONTENT; + params.format = PixelFormat.TRANSLUCENT; + params.windowAnimations = android.R.style.Animation_Toast; + params.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON + | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE + | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; + params.packageName = mPackageName; + // 重新初始化位置 + params.gravity = mToast.getGravity(); + params.x = mToast.getXOffset(); + params.y = mToast.getYOffset(); + + try { + Activity topActivity = mWindowHelper.getTopActivity(); + if (topActivity != null && !topActivity.isFinishing()) { + WindowManager windowManager = (WindowManager) topActivity.getSystemService(Context.WINDOW_SERVICE); + if (windowManager != null) { + windowManager.addView(mToast.getView(), params); + } + } + // 添加一个移除吐司的任务 + sendEmptyMessageDelayed(hashCode(), mToast.getDuration() == Toast.LENGTH_LONG ? + IToastStrategy.LONG_DURATION_TIMEOUT : IToastStrategy.SHORT_DURATION_TIMEOUT); + // 当前已经显示 + setShow(true); + } catch (IllegalStateException | WindowManager.BadTokenException ignored) { + // 如果这个 View 对象被重复添加到 WindowManager 则会抛出异常 + // java.lang.IllegalStateException: View android.widget.TextView has already been added to the window manager. + // 如果 WindowManager 绑定的 Activity 已经销毁,则会抛出异常 + // android.view.WindowManager$BadTokenException: Unable to add window -- token android.os.BinderProxy@ef1ccb6 is not valid; is your activity running? + } + } + } + + /** + * 取消吐司弹窗 + */ + void cancel() { + // 移除之前移除吐司的任务 + removeMessages(hashCode()); + if (isShow()) { + try { + Activity topActivity = mWindowHelper.getTopActivity(); + if (topActivity != null) { + WindowManager windowManager = (WindowManager) topActivity.getSystemService(Context.WINDOW_SERVICE); + if (windowManager != null) { + windowManager.removeViewImmediate(mToast.getView()); + } + } + } catch (IllegalArgumentException ignored) { + // 如果当前 WindowManager 没有附加这个 View 则会抛出异常 + // java.lang.IllegalArgumentException: View=android.widget.TextView not attached to window manager + } + // 当前没有显示 + setShow(false); + } + } +} \ No newline at end of file diff --git a/common_base/src/main/java/com/wss/common/utils/toast/ToastInterceptor.java b/common_base/src/main/java/com/wss/common/utils/toast/ToastInterceptor.java new file mode 100644 index 0000000..f0311ce --- /dev/null +++ b/common_base/src/main/java/com/wss/common/utils/toast/ToastInterceptor.java @@ -0,0 +1,18 @@ +package com.wss.common.utils.toast; + +import android.widget.Toast; + +/** + * author : Android 轮子哥 + * github : https://github.com/getActivity/ToastUtils + * time : 2019/05/19 + * desc : Toast 默认拦截器 + */ +public class ToastInterceptor implements IToastInterceptor { + + @Override + public boolean intercept(Toast toast, CharSequence text) { + // 如果是空对象或者空文本就进行拦截 + return text == null || "".equals(text.toString()); + } +} \ No newline at end of file diff --git a/common_base/src/main/java/com/wss/common/utils/toast/ToastStrategy.java b/common_base/src/main/java/com/wss/common/utils/toast/ToastStrategy.java new file mode 100644 index 0000000..24ebdfe --- /dev/null +++ b/common_base/src/main/java/com/wss/common/utils/toast/ToastStrategy.java @@ -0,0 +1,144 @@ +package com.wss.common.utils.toast; + +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.widget.Toast; + +import java.util.Queue; +import java.util.concurrent.ArrayBlockingQueue; + +/** + * author : Android 轮子哥 + * github : https://github.com/getActivity/ToastUtils + * time : 2018/11/12 + * desc : Toast 默认处理器 + */ +public class ToastStrategy extends Handler implements IToastStrategy { + + /** + * 延迟时间 + */ + private static final int DELAY_TIMEOUT = 200; + + /** + * 显示吐司 + */ + private static final int TYPE_SHOW = 1; + /** + * 继续显示 + */ + private static final int TYPE_CONTINUE = 2; + /** + * 取消显示 + */ + private static final int TYPE_CANCEL = 3; + + /** + * 队列最大容量 + */ + private static final int MAX_TOAST_CAPACITY = 3; + + /** + * 吐司队列 + */ + private volatile Queue mQueue; + + /** + * 当前是否正在执行显示操作 + */ + private volatile boolean mShow; + + /** + * 吐司对象 + */ + private Toast mToast; + + public ToastStrategy() { + super(Looper.getMainLooper()); + mQueue = getToastQueue(); + } + + @Override + public void bind(Toast toast) { + mToast = toast; + } + + @Override + public void show(CharSequence text) { + if (mQueue.isEmpty() || !mQueue.contains(text)) { + // 添加一个元素并返回true,如果队列已满,则返回false + if (!mQueue.offer(text)) { + // 移除队列头部元素并添加一个新的元素 + mQueue.poll(); + mQueue.offer(text); + } + } + + if (!mShow) { + mShow = true; + // 延迟一段时间之后再执行,因为在没有通知栏权限的情况下,Toast 只能显示当前 Activity + // 如果当前 Activity 在 ToastUtils.show 之后进行 finish 了,那么这个时候 Toast 可能会显示不出来 + // 因为 Toast 会显示在销毁 Activity 界面上,而不会显示在新跳转的 Activity 上面 + sendEmptyMessageDelayed(TYPE_SHOW, DELAY_TIMEOUT); + } + } + + @Override + public void cancel() { + if (mShow) { + mShow = false; + sendEmptyMessage(TYPE_CANCEL); + } + } + + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case TYPE_SHOW: + // 返回队列头部的元素,如果队列为空,则返回null + CharSequence text = mQueue.peek(); + if (text != null) { + mToast.setText(text); + mToast.show(); + // 等这个 Toast 显示完后再继续显示,要加上一些延迟 + // 不然在某些手机上 Toast 可能会来不及消失就要进行显示,这样是显示不出来的 + sendEmptyMessageDelayed(TYPE_CONTINUE, getToastDuration(text) + DELAY_TIMEOUT); + } else { + mShow = false; + } + break; + case TYPE_CONTINUE: + // 移除并返问队列头部的元素,如果队列为空,则返回null + mQueue.poll(); + if (!mQueue.isEmpty()) { + sendEmptyMessage(TYPE_SHOW); + } else { + mShow = false; + } + break; + case TYPE_CANCEL: + mShow = false; + mQueue.clear(); + mToast.cancel(); + break; + default: + break; + } + } + + /** + * 获取吐司队列 + */ + public Queue getToastQueue() { + return new ArrayBlockingQueue<>(MAX_TOAST_CAPACITY); + } + + /** + * 根据文本来获取吐司的显示时长 + */ + public int getToastDuration(CharSequence text) { + // 如果显示的文字超过了10个就显示长吐司,否则显示短吐司 + return text.length() > 20 ? LONG_DURATION_TIMEOUT : SHORT_DURATION_TIMEOUT; + } +} \ No newline at end of file diff --git a/common_base/src/main/java/com/wss/common/utils/toast/WindowHelper.java b/common_base/src/main/java/com/wss/common/utils/toast/WindowHelper.java new file mode 100644 index 0000000..214bdba --- /dev/null +++ b/common_base/src/main/java/com/wss/common/utils/toast/WindowHelper.java @@ -0,0 +1,91 @@ +package com.wss.common.utils.toast; + +import android.app.Activity; +import android.app.Application; +import android.os.Bundle; + +import org.jetbrains.annotations.NotNull; + +/** + * author : Android 轮子哥 + * github : https://github.com/getActivity/ToastUtils + * time : 2018/11/06 + * desc : WindowManager 辅助类(用于获取当前 Activity 的 WindowManager 对象) + */ +final class WindowHelper implements Application.ActivityLifecycleCallbacks { + + /** + * 栈顶 Activity + */ + private Activity mTopActivity; + + /** + * 用于 Activity 暂停时移除 WindowManager + */ + private final ToastHelper mToastHelper; + + private WindowHelper(ToastHelper toast) { + mToastHelper = toast; + } + + static WindowHelper register(ToastHelper toast, Application application) { + WindowHelper window = new WindowHelper(toast); + application.registerActivityLifecycleCallbacks(window); + return window; + } + + /** + * 获取栈顶的 Activity + */ + Activity getTopActivity() { + return mTopActivity; + } + + /** + * {@link Application.ActivityLifecycleCallbacks} + */ + + @Override + public void onActivityCreated(@NotNull Activity activity, Bundle savedInstanceState) { + mTopActivity = activity; + } + + @Override + public void onActivityStarted(@NotNull Activity activity) { + mTopActivity = activity; + } + + @Override + public void onActivityResumed(@NotNull Activity activity) { + mTopActivity = activity; + } + + // A 跳转 B 页面的生命周期方法执行顺序: + // onPause(A) ---> onCreate(B) ---> onStart(B) ---> onResume(B) ---> onStop(A) ---> onDestroyed(A) + + @Override + public void onActivityPaused(@NotNull Activity activity) { + // 取消这个吐司的显示 + if (mToastHelper.isShow()) { + // 不能放在 onStop 或者 onDestroyed 方法中,因为此时新的 Activity 已经创建完成,必须在这个新的 Activity 未创建之前关闭这个 WindowManager + // 调用取消显示会直接导致新的 Activity 的 onCreate 调用显示吐司可能显示不出来的问题,又或者有时候会立马显示然后立马消失的那种效果 + mToastHelper.cancel(); + } + } + + @Override + public void onActivityStopped(@NotNull Activity activity) { + } + + @Override + public void onActivitySaveInstanceState(@NotNull Activity activity, @NotNull Bundle outState) { + } + + @Override + public void onActivityDestroyed(@NotNull Activity activity) { + if (mTopActivity == activity) { + // 移除对这个 Activity 的引用 + mTopActivity = null; + } + } +} \ No newline at end of file diff --git a/common_base/src/main/java/com/wss/common/utils/toast/style/BaseToastStyle.java b/common_base/src/main/java/com/wss/common/utils/toast/style/BaseToastStyle.java new file mode 100644 index 0000000..618b040 --- /dev/null +++ b/common_base/src/main/java/com/wss/common/utils/toast/style/BaseToastStyle.java @@ -0,0 +1,72 @@ +package com.wss.common.utils.toast.style; + +import android.content.Context; +import android.util.TypedValue; +import android.view.Gravity; + +import com.wss.common.utils.toast.IToastStyle; + + +/** + * author : Android 轮子哥 + * github : https://github.com/getActivity/ToastUtils + * time : 2019/05/19 + * desc : 默认样式基类 + */ +public abstract class BaseToastStyle implements IToastStyle { + + private Context mContext; + + public BaseToastStyle(Context context) { + mContext = context; + } + + @Override + public int getGravity() { + return Gravity.CENTER; + } + + @Override + public int getXOffset() { + return 0; + } + + @Override + public int getYOffset() { + return 0; + } + + @Override + public int getZ() { + return 30; + } + + @Override + public int getMaxLines() { + return 5; + } + + @Override + public int getPaddingEnd() { + return getPaddingStart(); + } + + @Override + public int getPaddingBottom() { + return getPaddingTop(); + } + + /** + * dp转px + */ + protected int dp2px(float dpValue) { + return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpValue, mContext.getResources().getDisplayMetrics()); + } + + /** + * sp转px + */ + protected int sp2px(float spValue) { + return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, spValue, mContext.getResources().getDisplayMetrics()); + } +} \ No newline at end of file diff --git a/common_base/src/main/java/com/wss/common/utils/toast/style/ToastBlackStyle.java b/common_base/src/main/java/com/wss/common/utils/toast/style/ToastBlackStyle.java new file mode 100644 index 0000000..a2c04c7 --- /dev/null +++ b/common_base/src/main/java/com/wss/common/utils/toast/style/ToastBlackStyle.java @@ -0,0 +1,46 @@ +package com.wss.common.utils.toast.style; + +import android.content.Context; + +/** + * author : Android 轮子哥 + * github : https://github.com/getActivity/ToastUtils + * time : 2018/09/01 + * desc : 默认黑色样式实现 + */ +public class ToastBlackStyle extends BaseToastStyle { + + public ToastBlackStyle(Context context) { + super(context); + } + + @Override + public int getCornerRadius() { + return dp2px(4); + } + + @Override + public int getBackgroundColor() { + return 0XBF000000; + } + + @Override + public int getTextColor() { + return 0XEEFFFFFF; + } + + @Override + public float getTextSize() { + return sp2px(14); + } + + @Override + public int getPaddingStart() { + return dp2px(12); + } + + @Override + public int getPaddingTop() { + return dp2px(6); + } +} \ No newline at end of file diff --git a/common_base/src/main/java/com/wss/common/view/SpringboardActivity.java b/common_base/src/main/java/com/wss/common/view/SpringboardActivity.java new file mode 100644 index 0000000..72be373 --- /dev/null +++ b/common_base/src/main/java/com/wss/common/view/SpringboardActivity.java @@ -0,0 +1,44 @@ +package com.wss.common.view; + +import android.view.View; + +import com.wss.common.base.BaseActionBarActivity; +import com.wss.common.base.BaseFragment; +import com.wss.common.base.R; +import com.wss.common.base.mvp.BasePresenter; +import com.wss.common.constants.Dic; +import com.wss.common.utils.ARouterUtils; + +import androidx.fragment.app.FragmentTransaction; + +/** + * Describe:跳板Activity,主要是跳转一些Fragment + * 统一采用ARouter方式跳转 + * Created by 吴天强 on 2020/5/7. + */ +public class SpringboardActivity extends BaseActionBarActivity { + + @Override + protected int getLayoutId() { + return R.layout.activity_springboard; + } + + @Override + protected void initView() { + boolean isActionBar = getIntent().getBooleanExtra(Dic.IS_ACTION_BAR, false); + String titleText = getIntent().getStringExtra(Dic.TITLE_TEXT); + getTitleBar().setVisibility(isActionBar ? View.VISIBLE : View.GONE); + setCenterText(titleText); + BaseFragment fragment = ARouterUtils.getFragment(getIntent().getStringExtra(Dic.TARGET_FRAGMENT_PATH)); + //给Fragment设置带入参数 + fragment.setArguments(getIntent().getBundleExtra(Dic.BUNDLE_DATA)); + FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); + transaction.add(R.id.fl_content, fragment); + transaction.commitAllowingStateLoss(); + } + + @Override + protected BasePresenter createPresenter() { + return null; + } +} \ No newline at end of file diff --git a/common_base/src/main/java/com/wss/common/view/browser/BrowserActivity.java b/common_base/src/main/java/com/wss/common/view/browser/BrowserActivity.java new file mode 100644 index 0000000..82e7fd9 --- /dev/null +++ b/common_base/src/main/java/com/wss/common/view/browser/BrowserActivity.java @@ -0,0 +1,476 @@ +package com.wss.common.view.browser; + +import android.annotation.SuppressLint; +import android.content.Intent; +import android.graphics.Bitmap; +import android.net.Uri; +import android.view.Gravity; +import android.view.KeyEvent; +import android.view.View; +import android.view.ViewGroup; +import android.view.WindowManager; +import android.view.animation.AlphaAnimation; +import android.view.animation.Animation; +import android.webkit.ConsoleMessage; +import android.webkit.JsResult; +import android.webkit.WebChromeClient; +import android.webkit.WebResourceRequest; +import android.webkit.WebSettings; +import android.webkit.WebView; +import android.webkit.WebViewClient; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ProgressBar; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.orhanobut.logger.Logger; +import com.wss.common.base.BaseMvpActivity; +import com.wss.common.base.R; +import com.wss.common.base.R2; +import com.wss.common.constants.Constants; +import com.wss.common.constants.Dic; +import com.wss.common.utils.NetworkUtil; +import com.wss.common.utils.ValidUtils; +import com.wss.common.view.browser.mvp.BrowserPresenter; +import com.wss.common.view.browser.mvp.contract.BrowserContract; +import com.wss.common.widget.dialog.AppDialog; + +import org.jetbrains.annotations.NotNull; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import butterknife.BindView; +import butterknife.OnClick; + +/** + * Describe:浏览器页面-WebView + * Created by 吴天强 on 2020/5/18. + */ +public class BrowserActivity extends BaseMvpActivity implements BrowserContract.View { + + @BindView(R2.id.tv_title) + TextView tvTitle; + + @BindView(R2.id.progress_bar) + ProgressBar progressBar; + + @BindView(R2.id.web_view) + WebView webView; + + @BindView(R2.id.iv_empty) + ImageView ivEmpty; + + @BindView(R2.id.tv_empty) + TextView tvEmpty; + + @BindView(R2.id.ll_empty_view) + LinearLayout llEmptyView; + + @BindView(R2.id.img_back) + ImageView ivBack; + @BindView(R2.id.tv_back) + + TextView tvBack; + @BindView(R2.id.tv_close_right) + TextView tvCloseRight; + + @BindView(R2.id.rl_browser_header) + RelativeLayout relHeader; + /** + * 本地缓存目录 + */ + private String appCacheDir = Constants.WebView.CACHE_DIR; + private boolean isFullScreen = false; + private String url; + private String title; + + + @Override + protected int getLayoutId() { + return R.layout.activity_browser; + } + + public void hiddenHeader() { + relHeader.setVisibility(View.GONE); + } + + @Override + protected void initView() { + //沉浸式状态栏 + setImmersionBarColor(R.color.white); + url = getIntent().getStringExtra(Dic.URL); + title = getIntent().getStringExtra(Dic.TITLE_TEXT); + tvCloseRight.setVisibility(View.GONE); + tvBack.setVisibility(View.GONE); + tvTitle.setText(title); + initWebView(); + refreshPage(); + } + + @OnClick({ + R2.id.img_back, + R2.id.tv_back, + R2.id.tv_close_right, + }) + public void onClick(View v) { + int id = v.getId(); + if (id == R.id.img_back) { + finish(); + } else if (id == R.id.tv_back) { + finish(); + } else if (id == R.id.tv_close_right) { + finish(); + } + } + + /** + * 获取一个WebView实例 + * + * @return + */ + public WebView getWebView() { + return webView; + } + + @SuppressLint("SetJavaScriptEnabled") + private void initWebView() { + WebSettings webSettings = webView.getSettings(); + webSettings.setJavaScriptEnabled(true); + webSettings.setDomStorageEnabled(true); + webSettings.setPluginState(WebSettings.PluginState.ON); + webSettings.setAppCacheEnabled(true); + webSettings.setAppCachePath(appCacheDir); + webSettings.setDatabasePath(appCacheDir); + webSettings.setAppCacheMaxSize(100 * 1024 * 1024); + webSettings.setCacheMode(WebSettings.LOAD_DEFAULT); + webSettings.setAllowFileAccess(true); + webSettings.setRenderPriority(WebSettings.RenderPriority.HIGH); + webSettings.setSupportZoom(true); + webSettings.setBuiltInZoomControls(true); + // 添加新参数 + webSettings.setUseWideViewPort(true); + webSettings.setLoadWithOverviewMode(true); + + setPageCacheCapacity(webSettings); + webSettings.enableSmoothTransition(); + // 是否显示缩放按钮 + webSettings.setDisplayZoomControls(false); + + //设置HTTP HTTPS 混合模式加载页面 + webSettings.setMixedContentMode(2); + webView.setWebViewClient(webViewClient); + webView.setWebChromeClient(chromeClient); + } + + + private class JavaScriptApi { + + } + + @Override + protected BrowserPresenter createPresenter() { + return new BrowserPresenter(); + } + + + /** + * WebView调用JS + * + * @param method 方法名 + * @param data 参数多参已逗号分隔 + */ + private void loadJsMethod(String method, String data) { + if (ValidUtils.isValid(data)) { + // 传递参数调用 + String format = String.format("javascript:%s('%s')", method, data); + webView.loadUrl(format); + } else { + // 无参数调用 + webView.loadUrl(String.format("javascript:%s()", method)); + } + } + + + /** + * 刷新页面 显示网页 + */ + private void refreshPage() { + webView.clearCache(true); + if (NetworkUtil.isNetworkEnabled(context)) { + webView.setVisibility(View.VISIBLE); + progressBar.setVisibility(View.VISIBLE); + webView.loadUrl(url); +// webView.loadUrl("file:///android_asset/demo.html"); + } else { + shoeErrorPage(true); + } + } + + /** + * WebView client + */ + private WebViewClient webViewClient = new WebViewClient() { + + @Override + public boolean shouldOverrideUrlLoading(WebView view, String url) { + if (url.startsWith("http:") || url.startsWith("https:")) { + return false; + } + + Logger.e("shouldOverrideUrlLoading: " + url); + //拦截tel:拨打电话。 + if (url.startsWith("tel:")) { + try { + startActivity(new Intent(Intent.ACTION_DIAL, Uri.parse(url))); + } catch (Exception e) { + e.printStackTrace(); + } + return true; + } + return false; + } + + @Override + public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { + if (request.getUrl().toString().startsWith("http:") || request.getUrl().toString().startsWith("https:")) { + return false; + } + return true; + } + + @Override + public void doUpdateVisitedHistory(WebView view, String url, boolean isReload) { + super.doUpdateVisitedHistory(view, url, isReload); + } + + + @Override + public void onPageStarted(WebView view, String url, Bitmap favicon) { + super.onPageStarted(view, url, favicon); + Logger.e("onPageStarted: " + url); + if (progressBar != null) { + progressBar.setVisibility(View.VISIBLE); + } + } + + + @Override + public void onPageFinished(WebView view, String url) { + super.onPageFinished(view, url); + Logger.e("onPageFinished: " + url); + if (progressBar != null) { + progressBar.setVisibility(View.GONE); + } + } + + @Override + public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { + super.onReceivedError(view, errorCode, description, failingUrl); + if (progressBar != null) { + progressBar.setVisibility(View.GONE); + } + } + + @Override + public void onLoadResource(WebView view, String url) { + super.onLoadResource(view, url); + } + }; + /** + * 显示到选择进度条的进度,根据返回的title获取到当前的标题 + * 如果传过来的参数中带有标题,则显示该标题,不再根据WebChromeClient返回的title获取到当前的标题 + */ + private WebChromeClient chromeClient = new WebChromeClient() { + private View myView = null; + private int mTempProgress = 0; + + @Override + public boolean onConsoleMessage(ConsoleMessage consoleMessage) { + return super.onConsoleMessage(consoleMessage); + } + + @Override + public boolean onJsAlert(WebView view, String url, String message, @NotNull JsResult result) { + showDialog(message); + result.confirm(); + return true; + } + + @Override + public void onProgressChanged(WebView view, int newProgress) { + // 进度加载到100时,就不再重新进行加载,防止页面嵌套页面时,进度条反复加载 + if (progressBar == null || mTempProgress == 100) { + return; + } + mTempProgress = newProgress > 50 ? 100 : newProgress; + if (progressBar.getVisibility() == View.GONE) { + showProgressView(); + } + progressBar.setProgress(mTempProgress); + if (newProgress >= 80 && progressBar.getVisibility() == View.VISIBLE) { + dismissProgressView(); + } + } + + @Override + public void onReceivedTitle(WebView view, String title) { + super.onReceivedTitle(view, title); + if (tvTitle != null && !ValidUtils.isValid(title)) { + tvTitle.setText(title); + } + } + + @Override + public void onShowCustomView(View view, CustomViewCallback callback) { + super.onShowCustomView(view, callback); + isFullScreen = true; + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); + ViewGroup parent = (ViewGroup) webView.getParent().getParent(); + parent.setVisibility(View.GONE); + ((ViewGroup) parent.getParent()).addView(view, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT, Gravity.CENTER)); + myView = view; + chromeClient = this; + } + + @Override + public void onHideCustomView() { + isFullScreen = false; + if (myView != null) { + getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); + if (myView != null && myView.getParent() != null) { + ViewGroup parent = (ViewGroup) myView.getParent(); + parent.removeView(myView); + + if (webView.getParent().getParent() != null) { + ViewGroup parent2 = (ViewGroup) webView.getParent().getParent(); + parent2.setVisibility(View.VISIBLE); + } + } + myView = null; + } + } + }; + + @OnClick({R2.id.img_back, + R2.id.tv_back, + R2.id.tv_close_right, + R2.id.ll_empty_view}) + public void onViewClicked(@NotNull View view) { + int id = view.getId(); + if (id == R.id.img_back || id == R.id.tv_back) { + //返回 + goBack(); + } else if (id == R.id.tv_close_right) { + //关闭 + finish(); + } else if (id == R.id.ll_empty_view) { + //点击错误页 + } + } + + /** + * 显示进度条 + */ + private void showProgressView() { + AlphaAnimation anim = new AlphaAnimation(0, 1.0f); + anim.setDuration(200); + progressBar.startAnimation(anim); + progressBar.setVisibility(View.VISIBLE); + } + + /** + * 隐藏进度条 + */ + protected void dismissProgressView() { + AlphaAnimation anim = new AlphaAnimation(1.0f, 0); + anim.setDuration(200); + anim.setAnimationListener(new Animation.AnimationListener() { + + @Override + public void onAnimationStart(Animation animation) { + } + + @Override + public void onAnimationRepeat(Animation animation) { + } + + // 动画结束后再隐藏进度条 + @Override + public void onAnimationEnd(Animation animation) { + progressBar.setVisibility(View.GONE); + } + }); + progressBar.startAnimation(anim); + // 动画结束前显示进度条 + progressBar.setVisibility(View.VISIBLE); + } + + /** + * 显示错误页面 + * + * @param showError 显示 + */ + private void shoeErrorPage(boolean showError) { + if (showError) { + llEmptyView.setVisibility(View.VISIBLE); + webView.setVisibility(View.GONE); + } else { + llEmptyView.setVisibility(View.GONE); + webView.setVisibility(View.VISIBLE); + } + } + + /** + * 设置WebView缓存容量 + * + * @param webSettings settings + */ + public void setPageCacheCapacity(WebSettings webSettings) { + try { + @SuppressLint("PrivateApi") + Class c = Class.forName("android.webkit.WebSettingsClassic"); + Method tt = c.getMethod("setPageCacheCapacity", int.class); + tt.invoke(webSettings, 5); + } catch (ClassNotFoundException e) { + System.out.println("No such class: " + e); + } catch (NoSuchMethodException | IllegalArgumentException | + IllegalAccessException | InvocationTargetException e) { + e.printStackTrace(); + } + } + + /** + * 弹出对话框 + * + * @param message 提示信息 + */ + private void showDialog(String message) { + new AppDialog.Builder(context) + .setContent(message) + .create() + .show(); + } + + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK) { + goBack(); + return true; + } + return super.onKeyDown(keyCode, event); + } + + /** + * 返回上一步 + */ + private void goBack() { + if (webView.canGoBack()) { + webView.goBack(); + } else { + finish(); + } + } +} diff --git a/common_base/src/main/java/com/wss/common/view/browser/mvp/BrowserPresenter.java b/common_base/src/main/java/com/wss/common/view/browser/mvp/BrowserPresenter.java new file mode 100644 index 0000000..a42a522 --- /dev/null +++ b/common_base/src/main/java/com/wss/common/view/browser/mvp/BrowserPresenter.java @@ -0,0 +1,22 @@ +package com.wss.common.view.browser.mvp; + +import com.wss.common.base.mvp.BasePresenter; +import com.wss.common.view.browser.mvp.contract.BrowserContract; +import com.wss.common.view.browser.mvp.model.BrowserModel; + +/** + * Describe:浏览器控制器 + * Created by 吴天强 on 2020/5/18. + */ +public class BrowserPresenter extends BasePresenter + implements BrowserContract.Presenter { + @Override + protected BrowserModel createModule() { + return new BrowserModel(getLifecycleOwner()); + } + + @Override + public void start() { + + } +} diff --git a/common_base/src/main/java/com/wss/common/view/browser/mvp/contract/BrowserContract.java b/common_base/src/main/java/com/wss/common/view/browser/mvp/contract/BrowserContract.java new file mode 100644 index 0000000..002567e --- /dev/null +++ b/common_base/src/main/java/com/wss/common/view/browser/mvp/contract/BrowserContract.java @@ -0,0 +1,23 @@ +package com.wss.common.view.browser.mvp.contract; + + +import com.wss.common.base.mvp.IBaseView; + +/** + * Describe:浏览器页面契约类 + * Created by 吴天强 on 2020/5/18. + */ +public interface BrowserContract { + + interface Model { + + } + + interface View extends IBaseView { + + } + + interface Presenter { + + } +} diff --git a/common_base/src/main/java/com/wss/common/view/browser/mvp/model/BrowserModel.java b/common_base/src/main/java/com/wss/common/view/browser/mvp/model/BrowserModel.java new file mode 100644 index 0000000..83d333f --- /dev/null +++ b/common_base/src/main/java/com/wss/common/view/browser/mvp/model/BrowserModel.java @@ -0,0 +1,17 @@ +package com.wss.common.view.browser.mvp.model; + +import com.wss.common.base.mvp.BaseModel; +import com.wss.common.view.browser.mvp.contract.BrowserContract; + +import androidx.lifecycle.LifecycleOwner; + +/** + * Describe:浏览器Model + * Created by 吴天强 on 2020/5/18. + */ +public class BrowserModel extends BaseModel implements BrowserContract.Presenter { + + public BrowserModel(LifecycleOwner lifecycleOwner) { + super(lifecycleOwner); + } +} diff --git a/common_base/src/main/java/com/wss/common/view/file/SelectFileActivity.java b/common_base/src/main/java/com/wss/common/view/file/SelectFileActivity.java new file mode 100644 index 0000000..86024eb --- /dev/null +++ b/common_base/src/main/java/com/wss/common/view/file/SelectFileActivity.java @@ -0,0 +1,135 @@ +package com.wss.common.view.file; + +import android.content.Intent; + +import com.wss.common.base.BaseActionBarActivity; +import com.wss.common.base.R; +import com.wss.common.base.R2; +import com.wss.common.constants.Constants; +import com.wss.common.constants.Dic; +import com.wss.common.utils.JsonUtils; +import com.wss.common.utils.ToastUtils; +import com.wss.common.view.file.adapter.SelectFileAdapter; +import com.wss.common.view.file.bean.FileInfo; +import com.wss.common.view.file.mvp.SelectFilePresenter; +import com.wss.common.view.file.mvp.contract.SelectFileContract; + +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; + +import androidx.recyclerview.widget.GridLayoutManager; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; +import butterknife.BindView; + +/** + * Describe:选择手机文件 + * Created by 吴天强 on 2020/6/20. + */ +public class SelectFileActivity extends BaseActionBarActivity implements SelectFileContract.View { + + @BindView(R2.id.recycle_view) + RecyclerView recyclerView; + + private SelectFileAdapter adapter; + private List fileList = new ArrayList<>(); + + /** + * 最大可选文件数 + */ + private int max = 9; + + @Override + protected SelectFilePresenter createPresenter() { + return new SelectFilePresenter(); + } + + @Override + protected int getLayoutId() { + return R.layout.activity_select_file; + } + + @Override + protected void initView() { + if (getType() == Constants.FileType.IMAGE) { + setCenterText(getString(R.string.slelect_image)); + recyclerView.setLayoutManager(new GridLayoutManager(context, 3)); + + } else { + setCenterText(getString(R.string.select_file)); + recyclerView.setLayoutManager(new LinearLayoutManager(context)); + + } + max = getIntent().getIntExtra(Dic.MAX_SELECT_FILE, max); + adapter = new SelectFileAdapter(context, fileList, (fileInfo, position) -> { + if (!fileInfo.isChecked()) { + List allSelect = getAllSelect(); + if (allSelect.size() >= max) { + if (getType() == Constants.FileType.IMAGE) { + ToastUtils.show(context, getString(R.string.max_select_image, max)); + } else { + ToastUtils.show(context, getString(R.string.max_select_file, max)); + } + return; + } + } + fileList.get(position).setChecked(!fileList.get(position).isChecked()); + adapter.notifyItemChanged(position); + }); + recyclerView.setAdapter(adapter); + setRightText(R.string.confirm, v -> { + ArrayList allSelect = getAllSelect(); + if (allSelect.size() < 1) { + ToastUtils.show(context, getString(R.string.no_select)); + return; + } + Intent intent = new Intent(); + intent.putExtra(Dic.SELECT_FILE_PATHS, JsonUtils.toJson(allSelect)); + setResult(RESULT_OK, intent); + finish(); + }); + getPresenter().start(); + } + + @Override + public int getType() { + return getIntent().getIntExtra(Dic.FROM_TYPE, Constants.FileType.IMAGE); + } + + @Override + public void refreshFileList(List fileList) { + this.fileList.clear(); + this.fileList.addAll(fileList); + adapter.notifyDataSetChanged(); + } + + @Override + public void onError(Object tag, String errorMsg) { + super.onError(tag, errorMsg); + showErrorView(errorMsg); + } + + @Override + public void onEmpty(Object tag) { + super.onEmpty(tag); + showEmptyView(); + } + + /** + * 获取全部已选中文件 + * + * @return 所有已选中的文件的路径 + */ + @NotNull + private ArrayList getAllSelect() { + ArrayList pathList = new ArrayList<>(); + for (FileInfo info : fileList) { + if (info.isChecked()) { + pathList.add(info.getFilePath()); + } + } + return pathList; + } +} diff --git a/common_base/src/main/java/com/wss/common/view/file/adapter/SelectFileAdapter.java b/common_base/src/main/java/com/wss/common/view/file/adapter/SelectFileAdapter.java new file mode 100644 index 0000000..8d8cea3 --- /dev/null +++ b/common_base/src/main/java/com/wss/common/view/file/adapter/SelectFileAdapter.java @@ -0,0 +1,53 @@ +package com.wss.common.view.file.adapter; + +import android.content.Context; + +import com.wss.common.base.R; +import com.wss.common.base.adapter.BaseListAdapter; +import com.wss.common.constants.Constants; +import com.wss.common.utils.ImageUtils; +import com.wss.common.view.file.adapter.holder.SelectFileViewHolder; +import com.wss.common.view.file.bean.FileInfo; + +import org.byteam.superadapter.SuperViewHolder; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +/** + * Describe:选择文件适配器 + * Created by 吴天强 on 2020/6/20. + */ +public class SelectFileAdapter extends BaseListAdapter { + + private OnItemClickListener onItemClickListener; + + public SelectFileAdapter(Context context, List mData, OnItemClickListener listener) { + super(context, mData, new SelectFileViewHolder()); + this.onItemClickListener = listener; + } + + @Override + public void onBindData(@NotNull SuperViewHolder holder, int viewType, int layoutPosition, @NotNull FileInfo data) { + holder.findViewById(R.id.iftv_checked).setSelected(data.isChecked()); + if (onItemClickListener != null) { + holder.itemView.setOnClickListener(v -> onItemClickListener.onItemClick(data, layoutPosition)); + } + if (viewType == Constants.FileType.IMAGE) { + //图片 + ImageUtils.loadImageCircleBead(holder.findViewById(R.id.iv_image), data.getFilePath(), 4); + } else { + holder.setText(R.id.tv_name, data.getFileName()); + } + } + + public interface OnItemClickListener { + /** + * Item选择点击事件 + * + * @param fileInfo 文件 + * @param position 下标 + */ + void onItemClick(FileInfo fileInfo, int position); + } +} diff --git a/common_base/src/main/java/com/wss/common/view/file/adapter/holder/SelectFileViewHolder.java b/common_base/src/main/java/com/wss/common/view/file/adapter/holder/SelectFileViewHolder.java new file mode 100644 index 0000000..de7743d --- /dev/null +++ b/common_base/src/main/java/com/wss/common/view/file/adapter/holder/SelectFileViewHolder.java @@ -0,0 +1,33 @@ +package com.wss.common.view.file.adapter.holder; + +import com.wss.common.base.R; +import com.wss.common.constants.Constants; +import com.wss.common.view.file.bean.FileInfo; + +import org.byteam.superadapter.IMulItemViewType; +import org.jetbrains.annotations.NotNull; + +/** + * Describe:选择文件多View + * Created by 吴天强 on 2020/6/20. + */ +public class SelectFileViewHolder implements IMulItemViewType { + + @Override + public int getViewTypeCount() { + return 2; + } + + @Override + public int getItemViewType(int position, @NotNull FileInfo fileInfo) { + return fileInfo.getType(); + } + + @Override + public int getLayoutId(int viewType) { + if (viewType == Constants.FileType.IMAGE) { + return R.layout.item_of_select_image; + } + return R.layout.item_of_select_file; + } +} diff --git a/common_base/src/main/java/com/wss/common/view/file/bean/FileInfo.java b/common_base/src/main/java/com/wss/common/view/file/bean/FileInfo.java new file mode 100644 index 0000000..0a30f85 --- /dev/null +++ b/common_base/src/main/java/com/wss/common/view/file/bean/FileInfo.java @@ -0,0 +1,28 @@ +package com.wss.common.view.file.bean; + + +import com.wss.common.base.bean.BaseBean; + +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + + +/** + * Describe:选择文件 + * Created by 吴天强 on 2019/11/12. + */ +@Getter +@Setter +@ToString +public class FileInfo extends BaseBean { + private String fileName; + private String filePath; + private long fileSize; + private String time; + private boolean checked; + /** + * 文件类型 Constants.FileType + */ + private int type; +} diff --git a/common_base/src/main/java/com/wss/common/view/file/mvp/SelectFilePresenter.java b/common_base/src/main/java/com/wss/common/view/file/mvp/SelectFilePresenter.java new file mode 100644 index 0000000..b62f236 --- /dev/null +++ b/common_base/src/main/java/com/wss/common/view/file/mvp/SelectFilePresenter.java @@ -0,0 +1,36 @@ +package com.wss.common.view.file.mvp; + + +import com.wss.common.base.mvp.BasePresenter; +import com.wss.common.utils.ValidUtils; +import com.wss.common.view.file.mvp.contract.SelectFileContract; +import com.wss.common.view.file.mvp.model.SelectFileModel; + +/** + * Describe:选择文件控制器 + * Created by 吴天强 on 2020/6/20. + */ +public class SelectFilePresenter extends BasePresenter + implements SelectFileContract.Presenter { + @Override + protected SelectFileModel createModule() { + return new SelectFileModel(getLifecycleOwner()); + } + + @Override + public void start() { + showLoading(); + getModel().queryFile(getView().getType()).subscribe( + fileInfoList -> { + dismissLoading(); + if (ValidUtils.isValid(fileInfoList)) { + getView().refreshFileList(fileInfoList); + } else { + getView().onEmpty(""); + } + }, t -> { + dismissLoading(); + getView().onError("", t.getMessage()); + }); + } +} diff --git a/common_base/src/main/java/com/wss/common/view/file/mvp/contract/SelectFileContract.java b/common_base/src/main/java/com/wss/common/view/file/mvp/contract/SelectFileContract.java new file mode 100644 index 0000000..0225ee3 --- /dev/null +++ b/common_base/src/main/java/com/wss/common/view/file/mvp/contract/SelectFileContract.java @@ -0,0 +1,48 @@ +package com.wss.common.view.file.mvp.contract; + +import com.wss.common.base.mvp.IBaseView; +import com.wss.common.view.file.bean.FileInfo; + +import java.util.List; + +import io.reactivex.Observable; + +/** + * Describe:选择文件契约类 + * Created by 吴天强 on 2020/6/20. + */ +public interface SelectFileContract { + + interface Model { + /** + * 查询文件 + * + * @param type 类型 + * @return 文件列表 + */ + Observable> queryFile(int type); + } + + interface View extends IBaseView { + + /** + * 选择文件的类型 + * + * @return 类型 + */ + int getType(); + + /** + * 刷新文件列表 + * + * @param fileList 文件列表 + */ + void refreshFileList(List fileList); + + } + + interface Presenter { + + + } +} diff --git a/common_base/src/main/java/com/wss/common/view/file/mvp/model/SelectFileModel.java b/common_base/src/main/java/com/wss/common/view/file/mvp/model/SelectFileModel.java new file mode 100644 index 0000000..f1a8319 --- /dev/null +++ b/common_base/src/main/java/com/wss/common/view/file/mvp/model/SelectFileModel.java @@ -0,0 +1,202 @@ +package com.wss.common.view.file.mvp.model; + +import android.content.ContentResolver; +import android.database.Cursor; +import android.provider.MediaStore; + +import com.wss.common.base.BaseApplication; +import com.wss.common.base.mvp.BaseModel; +import com.wss.common.constants.Constants; +import com.wss.common.utils.FileUtils; +import com.wss.common.view.file.bean.FileInfo; +import com.wss.common.view.file.mvp.contract.SelectFileContract; + +import org.jetbrains.annotations.NotNull; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import androidx.lifecycle.LifecycleOwner; +import io.reactivex.Observable; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.schedulers.Schedulers; + +/** + * Describe:选择文件Model + * Created by 吴天强 on 2020/6/20. + */ +public class SelectFileModel extends BaseModel implements SelectFileContract.Model { + /** + * 视频后缀 + */ + private static final String[] VIDEO_SUFFIX = {".mp4", ".rmvb", ".avi", ".flv"}; + /** + * 语音后缀 + */ + private static final String[] VOICE_SUFFIX = {".mp3", ".wav", ".ogg", ".midi"}; + /** + * 文档后缀 + */ + private static final String[] DOCUMENT_SUFFIX = {".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf"}; + /** + * 压缩包后缀 + */ + private static final String[] PACKAGE_SUFFIX = {".jar", ".zip", ".rar", ".gz", ".apk", ".img"}; + /** + * 其他文件后缀 + */ + private static final String[] OTHER_SUFFIX = {".htm", ".html", ".php", ".jsp", ".txt", ".java", ".c", ".cpp", ".py", ".xml", ".json", ".log"}; + + public SelectFileModel(LifecycleOwner lifecycleOwner) { + super(lifecycleOwner); + } + + + @Override + public Observable> queryFile(int type) { + return Observable.>create( + subscriber -> { + switch (type) { + case Constants.FileType.IMAGE: + //读取手机图片 + subscriber.onNext(queryImages()); + break; + case Constants.FileType.VIDEO: + //视频 + subscriber.onNext(readSdCardFile(getQuerySql(VIDEO_SUFFIX))); + break; + case Constants.FileType.AUDIO: + //音频 + subscriber.onNext(readSdCardFile(getQuerySql(VOICE_SUFFIX))); + break; + case Constants.FileType.DOC: + //文档 + subscriber.onNext(readSdCardFile(getQuerySql(DOCUMENT_SUFFIX))); + break; + case Constants.FileType.PACKAGE: + //压缩包 + subscriber.onNext(readSdCardFile(getQuerySql(PACKAGE_SUFFIX))); + break; + case Constants.FileType.OTHER: + default: + //其他 + subscriber.onNext(readSdCardFile(getQuerySql(OTHER_SUFFIX))); + break; + } + }) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()); + } + + /** + * 读取手机里的图片 + * + * @return 图片列表 + */ + @NotNull + private List queryImages() { + List imageList = new ArrayList<>(); + ContentResolver mContentResolver = BaseApplication.i().getApplicationContext().getContentResolver(); + String[] projection = { + "_id", + MediaStore.Images.Media.DATA, + MediaStore.Images.Media.BUCKET_DISPLAY_NAME, + MediaStore.Images.Media.DISPLAY_NAME, + MediaStore.Images.Media.DATE_TAKEN, + MediaStore.Images.Media.SIZE}; + + Cursor mCursor = mContentResolver.query( + MediaStore.Images.Media.EXTERNAL_CONTENT_URI, + projection, "(" + + MediaStore.Images.Media.MIME_TYPE + "=? or " + + MediaStore.Images.Media.MIME_TYPE + "=? or " + + MediaStore.Images.Media.MIME_TYPE + "=? or " + + MediaStore.Images.Media.MIME_TYPE + "=? ) and _size > 0", + new String[]{"image/jpg", "image/png", "image/jpeg"}, + MediaStore.Images.Media.DATE_TAKEN + " desc"); + + if (mCursor != null) { + while (mCursor.moveToNext()) { + FileInfo fileInfo = new FileInfo(); + String path = mCursor.getString(mCursor.getColumnIndex(MediaStore.Images.Media.DATA)); + String displayName = mCursor.getString(mCursor.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME)); + int size = mCursor.getInt(mCursor.getColumnIndex(MediaStore.Images.Media.SIZE)); + fileInfo.setFilePath(path); + fileInfo.setFileSize(size); + fileInfo.setFileName(displayName); + imageList.add(fileInfo); + } + mCursor.close(); + } + return imageList; + } + + + /** + * 生成读手机影音SQL + * + * @param suffixList 文件后缀 + * @return 查询SQL + */ + @NotNull + private String getQuerySql(@NotNull String[] suffixList) { + StringBuilder sb = new StringBuilder(); + sb.append("("); + for (String suffix : suffixList) { + sb.append(MediaStore.Files.FileColumns.DATA); + sb.append(" LIKE '%").append(suffix).append("' OR "); + } + return sb.substring(0, sb.length() - 3) + ")"; + } + + + /** + * 读取手机中的文件 + * + * @param sql 查询SQL + * @return 文件列表 + */ + @NotNull + private List readSdCardFile(String sql) { + List result = new ArrayList<>(); + String[] columns = new String[]{ + MediaStore.Files.FileColumns._ID, + MediaStore.Files.FileColumns.MIME_TYPE, + MediaStore.Files.FileColumns.SIZE, + MediaStore.Files.FileColumns.DATE_MODIFIED, + MediaStore.Files.FileColumns.DATA}; + ContentResolver contentResolver = BaseApplication.i().getContentResolver(); + Cursor cursor = contentResolver.query(MediaStore.Files.getContentUri("external"), + columns, sql, null, null); + if (cursor != null) { + int columnIndexOrThrowData = cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.DATA); + while (cursor.moveToNext()) { + String path = cursor.getString(columnIndexOrThrowData); + FileInfo document = formatFile(new File(path)); + //去除空文件 + if (document.getFileSize() > 0) { + result.add(document); + } + } + cursor.close(); + } + return result; + } + + /** + * 格式化读取的文件 + * + * @param file 源文件 + * @return 格式化以后的文件 + */ + @NotNull + private FileInfo formatFile(@NotNull File file) { + FileInfo fileInfo = new FileInfo(); + fileInfo.setFileName(file.getName()); + fileInfo.setFilePath(file.getPath()); + fileInfo.setFileSize(file.length()); + fileInfo.setTime(FileUtils.getFileLastModifiedTime(file)); + return fileInfo; + } +} diff --git a/common_base/src/main/java/com/wss/common/widget/scaleImg/IOThread.java b/common_base/src/main/java/com/wss/common/view/gallery/IOThread.java similarity index 92% rename from common_base/src/main/java/com/wss/common/widget/scaleImg/IOThread.java rename to common_base/src/main/java/com/wss/common/view/gallery/IOThread.java index 5fa78fe..6fc9f96 100644 --- a/common_base/src/main/java/com/wss/common/widget/scaleImg/IOThread.java +++ b/common_base/src/main/java/com/wss/common/view/gallery/IOThread.java @@ -1,4 +1,4 @@ -package com.wss.common.widget.scaleImg; +package com.wss.common.view.gallery; import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; diff --git a/common_base/src/main/java/com/wss/common/widget/scaleImg/ImageDownloader.java b/common_base/src/main/java/com/wss/common/view/gallery/ImageDownloader.java similarity index 61% rename from common_base/src/main/java/com/wss/common/widget/scaleImg/ImageDownloader.java rename to common_base/src/main/java/com/wss/common/view/gallery/ImageDownloader.java index 71235e7..4fb1625 100644 --- a/common_base/src/main/java/com/wss/common/widget/scaleImg/ImageDownloader.java +++ b/common_base/src/main/java/com/wss/common/view/gallery/ImageDownloader.java @@ -1,4 +1,4 @@ -package com.wss.common.widget.scaleImg; +package com.wss.common.view.gallery; import android.app.Activity; @@ -9,5 +9,13 @@ * Created by 吴天强 on 2018年11月16日 */ public interface ImageDownloader { + + /** + * 下载 + * + * @param url URL + * @param activity activity + * @return File + */ File downLoad(String url, Activity activity); } \ No newline at end of file diff --git a/common_base/src/main/java/com/wss/common/view/gallery/ImageGallery.java b/common_base/src/main/java/com/wss/common/view/gallery/ImageGallery.java new file mode 100644 index 0000000..60c257a --- /dev/null +++ b/common_base/src/main/java/com/wss/common/view/gallery/ImageGallery.java @@ -0,0 +1,36 @@ +package com.wss.common.view.gallery; + + +import com.wss.common.base.bean.BaseBean; + +import lombok.Getter; +import lombok.Setter; + +/** + * Describe:缩放图片Bean + * Created by 吴天强 on 2019/7/31. + */ +@Getter +@Setter +public class ImageGallery extends BaseBean { + /** + * 图片描述 + */ + private String describe; + /** + * 图片地址 如果是本地图片 则是图片文件的绝对路径 + */ + private String url; + + public ImageGallery() { + } + + public ImageGallery(String url) { + this.url = url; + } + + public ImageGallery(String describe, String url) { + this.describe = describe; + this.url = url; + } +} diff --git a/common_base/src/main/java/com/wss/common/view/gallery/ImageGalleryActivity.java b/common_base/src/main/java/com/wss/common/view/gallery/ImageGalleryActivity.java new file mode 100644 index 0000000..73a9d6b --- /dev/null +++ b/common_base/src/main/java/com/wss/common/view/gallery/ImageGalleryActivity.java @@ -0,0 +1,230 @@ +package com.wss.common.view.gallery; + +import android.app.Activity; +import android.net.Uri; +import android.os.Bundle; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; +import android.widget.TextView; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.request.target.Target; +import com.davemorrissey.labs.subscaleview.ImageSource; +import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView; +import com.orhanobut.logger.Logger; +import com.wss.common.base.BaseFullScreenActivity; +import com.wss.common.base.R; +import com.wss.common.base.R2; +import com.wss.common.base.mvp.BasePresenter; +import com.wss.common.bean.Event; +import com.wss.common.constants.Dic; +import com.wss.common.constants.EventAction; +import com.wss.common.utils.EventBusUtils; +import com.wss.common.utils.ToastUtils; +import com.wss.common.utils.ValidUtils; +import com.wss.common.widget.ActionBar; +import com.wss.common.widget.IconFontTextView; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.concurrent.ExecutionException; + +import androidx.annotation.Nullable; +import androidx.viewpager.widget.ViewPager; +import butterknife.BindView; +import butterknife.ButterKnife; +import butterknife.Unbinder; + +/** + * Describe:图片画廊 + * Created by 吴天强 on 2020/4/29. + */ +@SuppressWarnings("unchecked") +public class ImageGalleryActivity extends BaseFullScreenActivity { + + @BindView(R2.id.rl_title_bar) + View titleBarLayout; + + @BindView(R2.id.actionbar) + ActionBar actionBar; + + @BindView(R2.id.view_pager) + ViewPager mViewPager; + + @BindView(R2.id.tv_img_count) + TextView tvImgCount; + + @BindView(R2.id.tv_describe) + TextView tvDescribe; + + private Unbinder butterKnifeBind; + private Activity activity; + + /*** + * 图片集合 + */ + private List imageList = new ArrayList<>(); + private List mViews = new ArrayList<>(); + + private int currentPosition; + + private ImageViewerAdapter mAdapter; + /** + * 是否是本地图片 + */ + private boolean isLocalImage; + /** + * 是否全屏显示 + */ + private boolean isFullScreen; + + @Override + protected BasePresenter createPresenter() { + return null; + } + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + isFullScreen = getIntent().getBooleanExtra(Dic.FULL_SCREEN, false); + if (isFullScreen) { + requestWindowFeature(Window.FEATURE_NO_TITLE); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); + } + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_image_gallery); + activity = this; + butterKnifeBind = ButterKnife.bind(this); + Collection serializableExtra = (Collection) getIntent().getSerializableExtra(Dic.IMAGE_LIST); + if (serializableExtra != null) { + imageList.addAll(serializableExtra); + } else { + ToastUtils.show(context, getString(R.string.please_setting_image)); + finish(); + } + isLocalImage = getIntent().getBooleanExtra(Dic.IMAGE_LOCAL, false); + currentPosition = getIntent().getIntExtra(Dic.IMAGE_POSITION, 0); + loadImage(); + mAdapter = new ImageViewerAdapter(mViews); + mViewPager.setAdapter(mAdapter); + mViewPager.setCurrentItem(currentPosition); + mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + + } + + @Override + public void onPageSelected(int position) { + currentPosition = position; + setImageChangeText(); + } + + @Override + public void onPageScrollStateChanged(int state) { + + } + }); + if (!isFullScreen) { + titleBarLayout.setVisibility(View.VISIBLE); + tvImgCount.setVisibility(View.GONE); + IconFontTextView rightIcon = new IconFontTextView(context); + rightIcon.setTextColor(getResources().getColor(R.color.color_333333)); + rightIcon.setTextSize(14); + rightIcon.setValue(getString(R.string.icon_delete)); + rightIcon.setOnClickListener(v -> { + //删除照片发个通知出去 带上删除的position + ToastUtils.show(context, getString(R.string.delete_success)); + EventBusUtils.sendEvent(new Event(EventAction.IMAGE_GALLERY_DELETE, currentPosition)); + imageList.remove(currentPosition); + int size = imageList.size(); + if (size < 1) { + finish(); + return; + } + mViewPager.removeView(mViews.remove(currentPosition)); + mAdapter.notifyDataSetChanged(); + setImageChangeText(); + }); + actionBar.setRightView(rightIcon); + actionBar.setLeftIcon(R.drawable.ic_back_black, v -> { + + }); + actionBar.setCenterTextColor(R.color.color_333333); + //加粗 + actionBar.setCenterTextBold(true); + actionBar.showBackImg(true); + } + setImageChangeText(); + } + + private void setImageChangeText() { + if (isFullScreen) { + tvImgCount.setText(String.format("%s/%s", currentPosition + 1, imageList.size())); + } else { + actionBar.setCenterText(String.format("%s/%s", currentPosition + 1, imageList.size())); + } + tvDescribe.setText(imageList.get(currentPosition).getDescribe()); + } + + private void loadImage() { + for (ImageGallery imageGallery : imageList) { + SubsamplingScaleImageView scaleImageView = new SubsamplingScaleImageView(context); + scaleImageView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); + if (isFullScreen) { + scaleImageView.setOnClickListener(v -> finish()); + } + + if (isLocalImage) { + scaleImageView.setImage(ImageSource.uri(Uri.fromFile(new File(imageGallery.getUrl())))); + } else { + if (!ValidUtils.isValid(imageGallery.getUrl())) { + return; + } + IOThread.getSingleThread().execute(() -> { + File downLoadFile; + try { + downLoadFile = mImageDownloader.downLoad(imageGallery.getUrl(), activity); + //如果图片路径不为空则开始执行 + if (ValidUtils.isValid(downLoadFile)) { + activity.runOnUiThread(() -> scaleImageView.setImage(ImageSource.uri(Uri.fromFile(downLoadFile)))); + } + } catch (Exception e) { + e.printStackTrace(); + Logger.e("加载图片异常" + e.getMessage()); + } + }); + } + mViews.add(scaleImageView); + } + + } + + /** + * 图片下载器 + */ + private ImageDownloader mImageDownloader = (url, activity) -> { + File file = null; + try { + file = Glide.with(activity) + .load(url) + .downloadOnly(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL) + .get(); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + Logger.e("下载图片异常" + e.getMessage()); + } + return file; + }; + + @Override + protected void onDestroy() { + super.onDestroy(); + if (butterKnifeBind != null) { + butterKnifeBind.unbind(); + } + } +} diff --git a/common_base/src/main/java/com/wss/common/widget/scaleImg/ImageViewerAdapter.java b/common_base/src/main/java/com/wss/common/view/gallery/ImageViewerAdapter.java similarity index 78% rename from common_base/src/main/java/com/wss/common/widget/scaleImg/ImageViewerAdapter.java rename to common_base/src/main/java/com/wss/common/view/gallery/ImageViewerAdapter.java index d82d370..149a774 100644 --- a/common_base/src/main/java/com/wss/common/widget/scaleImg/ImageViewerAdapter.java +++ b/common_base/src/main/java/com/wss/common/view/gallery/ImageViewerAdapter.java @@ -1,25 +1,24 @@ -package com.wss.common.widget.scaleImg; +package com.wss.common.view.gallery; -import android.app.Dialog; -import android.support.annotation.NonNull; -import android.support.v4.view.PagerAdapter; import android.view.View; import android.view.ViewGroup; +import org.jetbrains.annotations.NotNull; + import java.util.List; +import androidx.annotation.NonNull; +import androidx.viewpager.widget.PagerAdapter; + /** * Describe:图片查看器适配器 * Created by 吴天强 on 2018年11月16日 */ class ImageViewerAdapter extends PagerAdapter { - private List views; - private Dialog dialog; - ImageViewerAdapter(List views, Dialog dialog) { + ImageViewerAdapter(List views) { this.views = views; - this.dialog = dialog; } @NonNull @@ -30,9 +29,8 @@ public Object instantiateItem(@NonNull ViewGroup container, int position) { } @Override - public void destroyItem(@NonNull ViewGroup container, int position, Object object) { + public void destroyItem(@NonNull ViewGroup container, int position, @NotNull Object object) { if (position == 0 && views.size() == 0) { - dialog.dismiss(); return; } if (position == views.size()) { diff --git a/common_base/src/main/java/com/wss/common/view/scan/ScanActivity.java b/common_base/src/main/java/com/wss/common/view/scan/ScanActivity.java new file mode 100644 index 0000000..b071433 --- /dev/null +++ b/common_base/src/main/java/com/wss/common/view/scan/ScanActivity.java @@ -0,0 +1,106 @@ +package com.wss.common.view.scan; + +import android.view.View; + +import com.orhanobut.logger.Logger; +import com.wss.common.base.BaseActivity; +import com.wss.common.base.R; +import com.wss.common.base.R2; +import com.wss.common.bean.Event; +import com.wss.common.constants.EventAction; +import com.wss.common.utils.EventBusUtils; +import com.wss.common.utils.PermissionsUtils; +import com.wss.common.utils.ToastUtils; + +import java.util.Arrays; + +import butterknife.BindView; +import butterknife.OnClick; +import me.devilsen.czxing.code.BarcodeFormat; +import me.devilsen.czxing.view.ScanBoxView; +import me.devilsen.czxing.view.ScanListener; +import me.devilsen.czxing.view.ScanView; + + +/** + * Describe:扫一扫首页 + * Created by 吴天强 on 2019/12/27. + */ +public class ScanActivity extends BaseActivity { + + @BindView(R2.id.qr_code_view) + ScanView qrCodeView; + + @Override + protected void initView() { + PermissionsUtils.checkCamera(this).subscribe( + aBoolean -> { + if (aBoolean) { + qrCodeView.setScanListener(new ScanListener() { + @Override + public void onScanSuccess(String result, BarcodeFormat format) { + Logger.e("二维码扫描结果:" + result); + ToastUtils.show(result); + EventBusUtils.sendEvent(new Event<>(EventAction.SCAN_QR_CODE_RESULT, result)); + finish(); + } + + @Override + public void onOpenCameraError() { + ToastUtils.show(context, "打开相机出错"); + } + }); + ScanBoxView scanBox = qrCodeView.getScanBox(); + scanBox.setCornerColor(getResources().getColor(R.color.theme));//扫描四角颜色 + scanBox.setScanLineColor(Arrays.asList(getResources().getColor(R.color.theme), + getResources().getColor(R.color.theme), getResources().getColor(R.color.theme)));//扫描线条颜色 + + } else { + finish(); + } + } + ); + } + + + @OnClick(R2.id.iv_back) + public void onClick(View v) { + finish(); + } + + @Override + protected void onResume() { + super.onResume(); + if (qrCodeView != null) { + // 打开后置摄像头开始预览,但是并未开始识别 + qrCodeView.openCamera(); + // 显示扫描框,并开始识别 + qrCodeView.startScan(); + } + } + + @Override + protected void onPause() { + super.onPause(); + if (qrCodeView != null) { + qrCodeView.stopScan(); + //关闭摄像头预览,并且隐藏扫描框 + qrCodeView.closeCamera(); + } + } + + + @Override + protected void onDestroy() { + super.onDestroy(); + if (qrCodeView != null) { + qrCodeView.onDestroy(); + } + } + + @Override + protected int getLayoutId() { + return R.layout.activity_scan; + } + +} diff --git a/common_base/src/main/java/com/wss/common/widget/ActionBar.java b/common_base/src/main/java/com/wss/common/widget/ActionBar.java index e49f9f1..3e6d4be 100644 --- a/common_base/src/main/java/com/wss/common/widget/ActionBar.java +++ b/common_base/src/main/java/com/wss/common/widget/ActionBar.java @@ -2,7 +2,7 @@ import android.app.Activity; import android.content.Context; -import android.support.v4.content.ContextCompat; +import android.graphics.Typeface; import android.text.TextUtils; import android.util.AttributeSet; import android.view.View; @@ -14,12 +14,13 @@ import com.wss.common.base.R; import com.wss.common.utils.PxUtils; +import androidx.core.content.ContextCompat; + /** * Describe:自定义的ActionBar * Created by 吴天强 on 2017/8/22. */ - public class ActionBar extends RelativeLayout { private LinearLayout llActionbar; @@ -35,16 +36,20 @@ public class ActionBar extends RelativeLayout { /** * 字体颜色 */ - private int leftTextColor = R.color.white; - private int centerTextColor = R.color.white; - private int rightTextColor = R.color.white; + private int leftTextColor = R.color.black; + private int centerTextColor = R.color.black; + private int rightTextColor = R.color.black; /** * 字体大小 */ private int lefTextSize = 16; - private int centerTextSize = 16; + private int centerTextSize = 18; private int rightTextSize = 16; + /** + * 中间显示字体是否加粗 + */ + private boolean isCenterTextBold; public ActionBar(Context context) { this(context, null); @@ -81,10 +86,19 @@ public void setRightTextSize(int rightTextSize) { this.rightTextSize = rightTextSize; } + /** + * 是否加粗中间显示的字体 + * + * @param centerTextBold 是否加粗 + */ + public void setCenterTextBold(boolean centerTextBold) { + isCenterTextBold = centerTextBold; + } + /** * 获取跟布局 */ - public View getRootView() { + public View getActionBarRootView() { return rootView; } @@ -110,10 +124,12 @@ public void setLeftIcon(int res, OnClickListener l) { llLeft.setVisibility(VISIBLE); llLeft.setVisibility(VISIBLE); llLeft.removeAllViews(); - ImageView ivLeft = new ImageView(getContext()); + ImageView ivLeft = getImageView(); ivLeft.setImageResource(res); llLeft.addView(ivLeft); - llLeft.setOnClickListener(l); + if (l != null) { + llLeft.setOnClickListener(l); + } } /** @@ -125,7 +141,7 @@ public void setLeftIcon(int res, OnClickListener l) { public void setCenterIcon(int res, OnClickListener l) { llCenter.setVisibility(VISIBLE); llCenter.removeAllViews(); - ImageView center = new ImageView(getContext()); + ImageView center = getImageView(); center.setImageResource(res); llCenter.addView(center); llCenter.setOnClickListener(l); @@ -140,7 +156,7 @@ public void setCenterIcon(int res, OnClickListener l) { public void setRightIcon(int res, OnClickListener l) { llRight.setVisibility(VISIBLE); llRight.removeAllViews(); - ImageView right = new ImageView(getContext()); + ImageView right = getImageView(); right.setImageResource(res); llRight.addView(right); if (l != null) { @@ -192,6 +208,9 @@ public void setCenterText(CharSequence text, OnClickListener l) { center.setEllipsize(TextUtils.TruncateAt.END); center.setMaxLines(1); center.setTextColor(getResources().getColor(centerTextColor)); + if (isCenterTextBold) { + center.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD)); + } llCenter.addView(center); if (l != null) { llCenter.setOnClickListener(l); @@ -309,13 +328,10 @@ public void setRightView(View v, OnClickListener listener) { */ public void showBackImg(boolean show) { if (show) { - setLeftIcon(R.drawable.ic_back, new OnClickListener() { - @Override - public void onClick(View v) { - Context ctx = ActionBar.this.getContext(); - if (ctx instanceof Activity) { - ((Activity) ctx).onBackPressed(); - } + setLeftIcon(R.drawable.ic_back_black, v -> { + Context ctx = ActionBar.this.getContext(); + if (ctx instanceof Activity) { + ((Activity) ctx).onBackPressed(); } }); } else { @@ -349,7 +365,7 @@ public TextView getTextView() { */ public ImageView getImageView() { ImageView iv = new ImageView(getContext()); - iv.setLayoutParams(new LayoutParams(PxUtils.dp2px(getContext(), 25), PxUtils.dp2px(getContext(), 25))); + iv.setLayoutParams(new LayoutParams(PxUtils.dp2px(24), PxUtils.dp2px(24))); return iv; } diff --git a/common_base/src/main/java/com/wss/common/widget/AutoTextView.java b/common_base/src/main/java/com/wss/common/widget/AutoTextView.java new file mode 100644 index 0000000..f12011e --- /dev/null +++ b/common_base/src/main/java/com/wss/common/widget/AutoTextView.java @@ -0,0 +1,65 @@ +package com.wss.common.widget; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.ViewTreeObserver; + +/** + * 自动改变其显示行数的TextView + * create by yangwei + * on 2020/6/8 17:12 + */ +public class AutoTextView extends androidx.appcompat.widget.AppCompatTextView { + public AutoTextView(Context context) { + super(context); + } + + public AutoTextView(Context context, AttributeSet attrs) { + super(context, attrs); + init(); + } + + // 标记当前TextView的展开/收缩状态 + // true,已经展开 + // false,以及收缩 + private boolean expandableStatus = false; + private final int MAX_LINES = 2;//默认最多显示多少行 + private int lines;//如果textview内容完全神展开需要显示多少 + + private void init() { + final ViewTreeObserver mViewTreeObserver = this.getViewTreeObserver(); + + mViewTreeObserver.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { + + @Override + public boolean onPreDraw() { + // 避免重复监听 + AutoTextView.this.getViewTreeObserver().removeOnPreDrawListener(this); + lines = getLineCount(); + return true; + } + }); + this.setMaxLines(MAX_LINES); + } + + /** + * 是否展开 + * + * @param isExpand + */ + public void setExpandable(boolean isExpand) { + if (isExpand) { + + setMaxLines(lines + 1); + } else { + + setMaxLines(MAX_LINES); + } + + expandableStatus = isExpand; + } + + public boolean getExpandableStatus() { + return expandableStatus; + } +} diff --git a/common_base/src/main/java/com/wss/common/widget/CountClickView.java b/common_base/src/main/java/com/wss/common/widget/CountClickView.java index d65b611..403111b 100644 --- a/common_base/src/main/java/com/wss/common/widget/CountClickView.java +++ b/common_base/src/main/java/com/wss/common/widget/CountClickView.java @@ -11,8 +11,6 @@ import com.wss.common.base.R; import com.wss.common.base.R2; import com.wss.common.utils.PxUtils; -import com.wss.common.widget.dialog.AppDialog; -import com.wss.common.widget.dialog.DialogType; import butterknife.BindView; import butterknife.ButterKnife; @@ -53,7 +51,10 @@ public class CountClickView extends LinearLayout { private int minusNot = R.drawable.input_minus_disabled; private int addCan = R.drawable.input_add_default; private int addNot = R.drawable.input_add_disabled; - private boolean input = false;//是否支持如输入 默认不支持 + /** + * 是否支持如输入 默认不支持 + */ + private boolean input = false; public CountClickView(Context context) { this(context, null); @@ -74,31 +75,6 @@ private void init(Context context) { this.setBackgroundResource(android.R.color.transparent); ButterKnife.bind(this, View.inflate(context, R.layout.layout_count_click_view, this)); - tvCount.setOnClickListener(new OnClickListener() { - @Override - public void onClick(final View v) { - if (input) { - new AppDialog(mContext, DialogType.COUNT) - .setTitle("修改数量") - .setRightButton(new AppDialog.OnButtonClickListener() { - @Override - public void onClick(String val) { - tvCount.setText(val); - if (afterClickListener != null) { - afterClickListener.onAfter(getCount()); - if (getCount() == getMinCount()) { - afterClickListener.onMin(); - } - } - judgeTheViews(Integer.valueOf(val)); - } - }) - .setNumber(minCount, maxCount, getCount()) - .show(); - } - } - }); - judgeTheViews(getCount()); } @@ -107,12 +83,12 @@ public int getCount() { if (TextUtils.isEmpty(text)) { return INIT_COUNT; } - return Integer.valueOf(text); + return Integer.parseInt(text); } @OnClick({R2.id.iv_plus, R2.id.iv_minus}) public void onClick(View v) { - int count = Integer.valueOf(tvCount.getText().toString().trim()); + int count = Integer.parseInt(tvCount.getText().toString().trim()); if (R.id.iv_plus == v.getId()) { if (count < getMaxCount()) @@ -150,13 +126,11 @@ private void judgeTheViews(int count) { * 设置 按钮父类的大小 */ public void setBtnParentSize(int width, int height) { - llMinus.setLayoutParams(new LinearLayout.LayoutParams(PxUtils.dp2px(mContext, width), - PxUtils.dp2px(mContext, height))); - llPlus.setLayoutParams(new LinearLayout.LayoutParams(PxUtils.dp2px(mContext, width), - PxUtils.dp2px(mContext, height))); + llMinus.setLayoutParams(new LinearLayout.LayoutParams(PxUtils.dp2px(width), PxUtils.dp2px(height))); + llPlus.setLayoutParams(new LinearLayout.LayoutParams(PxUtils.dp2px(width), PxUtils.dp2px(height))); //如果设置了该处大小 则需要更新中间View的高度 LinearLayout.LayoutParams layoutParams = (LayoutParams) tvCount.getLayoutParams(); - layoutParams.height = PxUtils.dp2px(mContext, height); + layoutParams.height = PxUtils.dp2px(height); } /** @@ -172,10 +146,10 @@ public void setBtnParentBg(int bgColor) { * 设置加减按钮大小 */ public void setBtnSize(int width, int height) { - ivPlus.setLayoutParams(new LinearLayout.LayoutParams(PxUtils.dp2px(mContext, width), - PxUtils.dp2px(mContext, height))); - ivMinus.setLayoutParams(new LinearLayout.LayoutParams(PxUtils.dp2px(mContext, width), - PxUtils.dp2px(mContext, height))); + ivPlus.setLayoutParams(new LinearLayout.LayoutParams(PxUtils.dp2px(width), + PxUtils.dp2px(height))); + ivMinus.setLayoutParams(new LinearLayout.LayoutParams(PxUtils.dp2px(width), + PxUtils.dp2px(height))); } /** @@ -200,7 +174,7 @@ public void setButtonRes(int minusCan, int minusNot, int addCan, int addNot) { */ public void setCountViewAttr(int bgColor, int textColor, int marginLeft, int marginRight) { LinearLayout.LayoutParams layoutParams = (LayoutParams) tvCount.getLayoutParams(); - layoutParams.setMargins(PxUtils.dp2px(mContext, marginLeft), 0, PxUtils.dp2px(mContext, marginRight), 0); + layoutParams.setMargins(PxUtils.dp2px(marginLeft), 0, PxUtils.dp2px(marginRight), 0); tvCount.setBackgroundColor(getResources().getColor(bgColor)); if (textColor != 0) { tvCount.setTextColor(getResources().getColor(textColor)); diff --git a/common_base/src/main/java/com/wss/common/widget/EnhanceEditText.java b/common_base/src/main/java/com/wss/common/widget/EnhanceEditText.java new file mode 100644 index 0000000..d34cb5a --- /dev/null +++ b/common_base/src/main/java/com/wss/common/widget/EnhanceEditText.java @@ -0,0 +1,388 @@ +package com.wss.common.widget; + +import android.content.Context; +import android.content.res.TypedArray; +import android.text.Editable; +import android.text.InputFilter; +import android.text.InputType; +import android.text.TextWatcher; +import android.text.method.PasswordTransformationMethod; +import android.util.AttributeSet; +import android.view.Gravity; +import android.view.View; +import android.view.inputmethod.EditorInfo; +import android.widget.EditText; +import android.widget.LinearLayout; + +import com.wss.common.base.R; +import com.wss.common.base.R2; +import com.wss.common.utils.KeyboardUtils; +import com.wss.common.utils.ValidUtils; + +import androidx.annotation.Nullable; +import butterknife.BindView; +import butterknife.ButterKnife; +import butterknife.OnClick; + +/** + * Describe 增强版输入框,左右带图标 + * Created by 吴天强 on 2020/4/20. + */ +public class EnhanceEditText extends LinearLayout { + /** + * 无操作 + */ + public static final int ACTION_NONE = 0; + /** + * 搜索事件 + */ + public static final int ACTION_SEARCH = 1; + /** + * 下一步 + */ + public static final int ACTION_NEXT = 2; + /** + * 完成 + */ + public static final int ACTION_DONE = 3; + + /** + * 输入文本 + */ + public static final int INPUT_TEXT = 0; + /** + * 输入密码 + */ + public static final int INPUT_PASSWORD = 1; + + /** + * 输入手机 + */ + public static final int INPUT_PHONE = 2; + /** + * 输入数字 + */ + public static final int INPUT_NUMBER = 3; + + + @BindView(R2.id.ll_edt_view) + LinearLayout llEdtView; + + @BindView(R2.id.iftv_left) + IconFontTextView iftvLeft; + + @BindView(R2.id.edt_text) + EditText editText; + + @BindView(R2.id.iftv_clean) + IconFontTextView iftvClean; + + @BindView(R2.id.ll_clean_view) + View cleanView; + + private int textColor = 0xFF333333; + private int hintColor = 0XFF999999; + private int leftIconColor = 0XFF999999; + private int cleanIconColor = 0XFF999999; + private String leftIcon; + private String cleanIcon; + private String hintText; + private int textSize = 14; + /** + * 背景资源 + */ + private int bgResource = R.drawable.bg_of_color_f5_4radius; + /** + * 是否显示清除按钮 默认true + */ + private boolean showCleanIcon = true; + /** + * 是否现在左侧icon 默认true + */ + private boolean showLeftIcon = true; + /** + * 是否显示背景 默认true + */ + private boolean showBackground = true; + /** + * 键盘最后执行的Action + */ + private int action = ACTION_NONE; + /** + * 输入框类型 + */ + private int inputType = INPUT_TEXT; + private int maxLength; + private int maxLines; + + private OnTextChangeListener onTextChangeListener; + private OnActionClickListener onActionClickListener; + + + public EnhanceEditText(Context context) { + this(context, null); + } + + public EnhanceEditText(Context context, @Nullable AttributeSet attrs) { + this(context, attrs, 0); + } + + public EnhanceEditText(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + ButterKnife.bind(this, View.inflate(getContext(), R.layout.layout_search, this)); + TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.EnhanceEditText); + textColor = a.getColor(R.styleable.EnhanceEditText_eTextColor, textColor); + hintColor = a.getColor(R.styleable.EnhanceEditText_eHintTextColor, hintColor); + leftIcon = a.getString(R.styleable.EnhanceEditText_eLeftIconFont); + leftIconColor = a.getColor(R.styleable.EnhanceEditText_eLeftIconColor, leftIconColor); + cleanIcon = a.getString(R.styleable.EnhanceEditText_eCleanIconFont); + cleanIconColor = a.getColor(R.styleable.EnhanceEditText_eCleanIconColor, cleanIconColor); + hintText = a.getString(R.styleable.EnhanceEditText_eHintText); + textSize = a.getDimensionPixelSize(R.styleable.EnhanceEditText_eTextSize, textSize); + showCleanIcon = a.getBoolean(R.styleable.EnhanceEditText_eShowClean, showCleanIcon); + bgResource = a.getResourceId(R.styleable.EnhanceEditText_eBg, bgResource); + showLeftIcon = a.getBoolean(R.styleable.EnhanceEditText_eShowLeft, showLeftIcon); + showBackground = a.getBoolean(R.styleable.EnhanceEditText_eShowBg, showBackground); + action = a.getInt(R.styleable.EnhanceEditText_eAction, action); + inputType = a.getInt(R.styleable.EnhanceEditText_eInputType, inputType); + maxLength = a.getInt(R.styleable.EnhanceEditText_eMaxLength, maxLength); + maxLines = a.getInt(R.styleable.EnhanceEditText_eMaxLines, maxLines); + a.recycle(); + initView(); + } + + private void initView() { + setGravity(Gravity.CENTER_VERTICAL); + if (showBackground) { + setBackgroundResource(bgResource); + } + if (showLeftIcon && ValidUtils.isValid(leftIcon)) { + iftvLeft.setValue(leftIcon); + iftvLeft.setTextColor(leftIconColor); + } else { + iftvLeft.setVisibility(VISIBLE); + } + if (showCleanIcon && ValidUtils.isValid(cleanIcon)) { + iftvClean.setValue(cleanIcon); + iftvClean.setTextColor(cleanIconColor); + } + editText.setHint(hintText); + editText.setTextSize(textSize); + editText.setTextColor(textColor); + editText.setHintTextColor(hintColor); + editText.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + if (onTextChangeListener != null) { + onTextChangeListener.beforeTextChanged(s, start, count, after); + } + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + if (onTextChangeListener != null) { + onTextChangeListener.onTextChanged(s, start, before, count); + } + } + + @Override + public void afterTextChanged(Editable s) { + if (onTextChangeListener != null) { + onTextChangeListener.afterTextChanged(s); + } + if (showCleanIcon) { + cleanView.setVisibility(s.toString().length() > 0 ? VISIBLE : GONE); + } + } + }); + setInputFiller(); + setOnEditorAction(); + } + + /** + * 设置输入框的一些属性 + */ + private void setInputFiller() { + switch (inputType) { + case INPUT_PASSWORD: + editText.setInputType(InputType.TYPE_TEXT_VARIATION_PASSWORD); + editText.setTransformationMethod(PasswordTransformationMethod.getInstance()); + break; + case INPUT_PHONE: + editText.setInputType(InputType.TYPE_CLASS_PHONE); + break; + case INPUT_NUMBER: + editText.setInputType(InputType.TYPE_CLASS_NUMBER); + break; + case INPUT_TEXT: + default: + editText.setInputType(InputType.TYPE_CLASS_TEXT); + break; + } + if (maxLength > 0) { + editText.setFilters(new InputFilter[]{new InputFilter.LengthFilter(maxLength)}); + } + if (maxLines > 0) { + editText.setMaxLines(maxLines); + } + } + + /** + * 设置输入框的执行事件 + */ + private void setOnEditorAction() { + switch (action) { + case ACTION_SEARCH: + editText.setImeOptions(EditorInfo.IME_ACTION_SEARCH); + break; + case ACTION_NEXT: + editText.setImeOptions(EditorInfo.IME_ACTION_NEXT); + break; + case ACTION_DONE: + editText.setImeOptions(EditorInfo.IME_ACTION_DONE); + break; + case ACTION_NONE: + default: + editText.setImeOptions(EditorInfo.IME_ACTION_NONE); + break; + } + + editText.setOnEditorActionListener((v, actionId, event) -> { + KeyboardUtils.hideKeyboard(v); + if (onActionClickListener == null) { + return false; + } + switch (actionId) { + case EditorInfo.IME_ACTION_SEARCH: + //搜索 + onActionClickListener.onEditorAction(ACTION_SEARCH); + break; + case EditorInfo.IME_ACTION_NEXT: + //下一步 + onActionClickListener.onEditorAction(ACTION_NEXT); + break; + case EditorInfo.IME_ACTION_DONE: + //完成 + onActionClickListener.onEditorAction(ACTION_DONE); + break; + case EditorInfo.IME_ACTION_NONE: + default: + //无操作 + onActionClickListener.onEditorAction(ACTION_NONE); + break; + } + return true; + }); + } + + @OnClick(R2.id.ll_clean_view) + public void onClean() { + getEditText().setText(""); + } + + + /** + * 返回输入框字符 + * + * @return String + */ + public String getText() { + return getEditText().getText().toString().trim(); + } + + /** + * 清除搜索框内容 + */ + public void clearSearchText() { + onClean(); + } + + /** + * 返回输入框View + * + * @return EditText + */ + public EditText getEditText() { + return editText; + } + + /** + * 设置搜索按钮点击回调 + * + * @param onActionClickListener OnEditActionCallback + */ + public void setOnActionClickListener(OnActionClickListener onActionClickListener) { + this.onActionClickListener = onActionClickListener; + } + + /** + * 设置文本输入变化监听 + * + * @param textChangeListener listener + */ + public void setTextChangeListener(OnTextChangeListener textChangeListener) { + this.onTextChangeListener = textChangeListener; + } + + /** + * 设置文本 + * + * @param text 文本 + */ + public void setText(CharSequence text) { + editText.setText(text); + } + + /** + * 设置输入框光标位置 + * + * @param position 位置 + */ + public void setSelection(int position) { + editText.setSelection(position); + } + + /** + * 文本输入变化监听 + */ + public interface OnTextChangeListener { + /** + * 输入前 + * + * @param s s + * @param start start + * @param count count + * @param after after + */ + void beforeTextChanged(CharSequence s, int start, int count, int after); + + /** + * 变化 + * + * @param s s + * @param start start + * @param before before + * @param count count + */ + void onTextChanged(CharSequence s, int start, int before, int count); + + /** + * 变化后 + * + * @param s 文本 + */ + void afterTextChanged(Editable s); + } + + /** + * 键盘搜索按钮点击 + */ + public interface OnActionClickListener { + /** + * 按钮被点击 + * + * @param action 事件ID + */ + void onEditorAction(int action); + } +} diff --git a/common_base/src/main/java/com/wss/common/widget/FlowLayout.java b/common_base/src/main/java/com/wss/common/widget/FlowLayout.java index f7b8e8f..40ca2e3 100644 --- a/common_base/src/main/java/com/wss/common/widget/FlowLayout.java +++ b/common_base/src/main/java/com/wss/common/widget/FlowLayout.java @@ -2,7 +2,6 @@ import android.content.Context; import android.content.res.TypedArray; -import android.support.v4.text.TextUtilsCompat; import android.util.AttributeSet; import android.util.LayoutDirection; import android.view.View; @@ -13,12 +12,13 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; - import java.util.Locale; +import androidx.core.text.TextUtilsCompat; + /** * 流式布局 - * Created by wtq on 2016/12/15. + * Created by lss on 2016/12/15. */ public class FlowLayout extends ViewGroup { private static final String TAG = "FlowLayout"; @@ -128,7 +128,7 @@ protected void onLayout(boolean changed, int l, int t, int r, int b) { for (int i = 0; i < cCount; i++) { View child = getChildAt(i); - if (child.getVisibility() == View.GONE) continue; + if (child.getVisibility() == View.GONE){ continue;} MarginLayoutParams lp = (MarginLayoutParams) child .getLayoutParams(); @@ -179,6 +179,8 @@ protected void onLayout(boolean changed, int l, int t, int r, int b) { // 适配了rtl,需要把lineViews里面的数组倒序排 Collections.reverse(lineViews); break; + default: + break; } for (int j = 0; j < lineViews.size(); j++) { diff --git a/common_base/src/main/java/com/wss/common/widget/GradientTextView.java b/common_base/src/main/java/com/wss/common/widget/GradientTextView.java new file mode 100644 index 0000000..d218b20 --- /dev/null +++ b/common_base/src/main/java/com/wss/common/widget/GradientTextView.java @@ -0,0 +1,56 @@ +package com.wss.common.widget; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.LinearGradient; +import android.graphics.Paint; +import android.graphics.Rect; +import android.graphics.Shader; +import android.util.AttributeSet; + +import androidx.appcompat.widget.AppCompatTextView; + +/** + * Describe:带渐变颜色的TextView + * Created by 吴天强 on 2019/7/1. + */ +public class GradientTextView extends AppCompatTextView { + + private Rect mTextBound = new Rect(); + private boolean gradient; + + public GradientTextView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @SuppressLint("DrawAllocation") + @Override + protected void onDraw(Canvas canvas) { + int mViewWidth = getMeasuredWidth(); + Paint mPaint = getPaint(); + String mTipText = getText().toString(); + mPaint.getTextBounds(mTipText, 0, mTipText.length(), mTextBound); + LinearGradient mLinearGradient; + if (gradient) { + mLinearGradient = new LinearGradient(0, 0, mViewWidth, 0, + new int[]{0xFF1A3AFF, 0xFF10E17D}, null, Shader.TileMode.REPEAT); + mPaint.setFakeBoldText(true); + } else { + mLinearGradient = new LinearGradient(0, 0, mViewWidth, 0, + new int[]{0xFF000000, 0xFF000000}, null, Shader.TileMode.REPEAT); + mPaint.setFakeBoldText(false); + } + mPaint.setShader(mLinearGradient); + canvas.drawText(mTipText, (getMeasuredWidth() >> 1) - (mTextBound.width() >> 1), (getMeasuredHeight() >> 1) + (mTextBound.height() >> 1), mPaint); + invalidate(); + } + + /** + * 设置是否渐变 + */ + public void setGradient(boolean gradient) { + this.gradient = gradient; + postInvalidate(); + } +} \ No newline at end of file diff --git a/common_base/src/main/java/com/wss/common/widget/HinderWebView.java b/common_base/src/main/java/com/wss/common/widget/HinderWebView.java index 46bc9a9..fff0b94 100644 --- a/common_base/src/main/java/com/wss/common/widget/HinderWebView.java +++ b/common_base/src/main/java/com/wss/common/widget/HinderWebView.java @@ -34,7 +34,6 @@ public boolean onTouchEvent(MotionEvent ev) { case MotionEvent.ACTION_MOVE: float Y = ev.getY(); float Ys = Y - oldY; - //滑动到顶部让父控件重新获得触摸事件 if (Ys > 0 && t == 0) { getParent().getParent().requestDisallowInterceptTouchEvent(false); diff --git a/common_base/src/main/java/com/wss/common/widget/IconFontTextView.java b/common_base/src/main/java/com/wss/common/widget/IconFontTextView.java new file mode 100644 index 0000000..887a699 --- /dev/null +++ b/common_base/src/main/java/com/wss/common/widget/IconFontTextView.java @@ -0,0 +1,94 @@ +package com.wss.common.widget; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Typeface; +import android.util.AttributeSet; + +import com.wss.common.base.R; +import com.wss.common.utils.ValidUtils; + +import androidx.annotation.Nullable; +import androidx.appcompat.widget.AppCompatTextView; + +/** + * Describe:使用ali IconFont的TextView + * Created by 吴天强 on 2019/7/9. + */ +public class IconFontTextView extends AppCompatTextView { + + private Context context; + private String fontFile = "iconfont/iconfont.ttf"; + private String defaultText;//默认文字 + private String checkedText;//选择之后文字 + + public IconFontTextView(Context context) { + this(context, null); + } + + public IconFontTextView(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + this.context = context; + if (attrs != null) { + TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.IconFontTextView); + defaultText = a.getString(R.styleable.IconFontTextView_value); + checkedText = a.getString(R.styleable.IconFontTextView_valueChecked); + setFontFile(a.getString(R.styleable.IconFontTextView_fontFile)); + a.recycle(); + } + setTextState(); + setTypeFace(); + } + + @Override + public void setSelected(boolean selected) { + super.setSelected(selected); + setTextState(); + } + + /*** + * 设置显示Value + */ + public void setValue(String defaultText) { + this.defaultText = defaultText; + setTextState(); + } + + /*** + * 设置显示Value + * @param defaultText 默认显示 + * @param checkedText 选中显示 + */ + public void setValue(String defaultText, String checkedText) { + this.defaultText = defaultText; + this.checkedText = checkedText; + setTextState(); + } + + + /** + * 设置字体库 + */ + public void setFontFile(String typeFacePath) { + if (ValidUtils.isValid(typeFacePath)) { + fontFile = typeFacePath; + } + setTypeFace(); + } + + private void setTextState() { + if (ValidUtils.isValid(checkedText)) { + setText(isSelected() ? checkedText : defaultText); + } else { + setText(defaultText); + } + } + + private void setTypeFace() { + try { + Typeface typeface = Typeface.createFromAsset(context.getAssets(), fontFile); + setTypeface(typeface); + } catch (Throwable ignored) { + } + } +} diff --git a/common_base/src/main/java/com/wss/common/widget/LVCircularRing.java b/common_base/src/main/java/com/wss/common/widget/LVCircularRing.java index 41c84d3..f3184f2 100644 --- a/common_base/src/main/java/com/wss/common/widget/LVCircularRing.java +++ b/common_base/src/main/java/com/wss/common/widget/LVCircularRing.java @@ -16,11 +16,11 @@ import com.wss.common.base.R; + /** * 自定义加载框View - * Created by wtq on 2016/12/15. + * Created by 吴天强 on 2016/12/15. */ - public class LVCircularRing extends View { private float mWidth = 0f; private float mPadding = 0f; diff --git a/common_base/src/main/java/com/wss/common/widget/MultipleItemView.java b/common_base/src/main/java/com/wss/common/widget/MultipleItemView.java index e8adc19..ec199ae 100644 --- a/common_base/src/main/java/com/wss/common/widget/MultipleItemView.java +++ b/common_base/src/main/java/com/wss/common/widget/MultipleItemView.java @@ -4,7 +4,6 @@ import android.content.res.TypedArray; import android.graphics.Color; import android.graphics.drawable.Drawable; -import android.support.annotation.Nullable; import android.util.AttributeSet; import android.view.View; import android.widget.EditText; @@ -17,6 +16,7 @@ import com.wss.common.base.R2; import com.wss.common.utils.PxUtils; +import androidx.annotation.Nullable; import butterknife.BindView; import butterknife.ButterKnife; @@ -237,8 +237,7 @@ public MultipleItemView setRightTextSize(int size) { */ public MultipleItemView setLeftIconMargin(int left, int top, int right, int bottom) { LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) ivLeft.getLayoutParams(); - layoutParams.setMargins(PxUtils.dp2px(getContext(), left), PxUtils.dp2px(getContext(), top), - PxUtils.dp2px(getContext(), right), PxUtils.dp2px(getContext(), bottom)); + layoutParams.setMargins(PxUtils.dp2px(left), PxUtils.dp2px(top), PxUtils.dp2px(right), PxUtils.dp2px(bottom)); return this; } @@ -253,8 +252,8 @@ public MultipleItemView setLeftIconMargin(int left, int top, int right, int bott */ public MultipleItemView setRightIconMargin(int left, int top, int right, int bottom) { LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) ivRight.getLayoutParams(); - layoutParams.setMargins(PxUtils.dp2px(getContext(), left), PxUtils.dp2px(getContext(), top), - PxUtils.dp2px(getContext(), right), PxUtils.dp2px(getContext(), bottom)); + layoutParams.setMargins(PxUtils.dp2px(left), PxUtils.dp2px(top), + PxUtils.dp2px(right), PxUtils.dp2px(bottom)); return this; } @@ -289,8 +288,8 @@ public MultipleItemView setLeftIconResource(int resId) { * @return MultifunctionalItemView */ public MultipleItemView setLeftIconSize(int width, int height) { - LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(PxUtils.dp2px(getContext(), width), - PxUtils.dp2px(getContext(), height)); + LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(PxUtils.dp2px(width), + PxUtils.dp2px(height)); lp.setMargins(0, 0, 4, 0); ivLeft.setLayoutParams(lp); return this; @@ -327,8 +326,8 @@ public MultipleItemView setRightIconResource(int resId) { * @return MultifunctionalItemView */ public MultipleItemView setRightIconSize(int width, int height) { - ivRight.setLayoutParams(new LinearLayout.LayoutParams(PxUtils.dp2px(getContext(), width), - PxUtils.dp2px(getContext(), height))); + ivRight.setLayoutParams(new LinearLayout.LayoutParams(PxUtils.dp2px(width), + PxUtils.dp2px(height))); return this; } @@ -342,8 +341,8 @@ public MultipleItemView setRightIconSize(int width, int height) { * @return MultifunctionalItemView */ public MultipleItemView setContentPadding(int left, int top, int right, int bottom) { - content.setPadding(PxUtils.dp2px(getContext(), left), PxUtils.dp2px(getContext(), top), - PxUtils.dp2px(getContext(), right), PxUtils.dp2px(getContext(), bottom)); + content.setPadding(PxUtils.dp2px(left), PxUtils.dp2px(top), + PxUtils.dp2px(right), PxUtils.dp2px(bottom)); return this; } diff --git a/common_base/src/main/java/com/wss/common/widget/NoScrollGridView.java b/common_base/src/main/java/com/wss/common/widget/NoScrollGridView.java new file mode 100644 index 0000000..4e64493 --- /dev/null +++ b/common_base/src/main/java/com/wss/common/widget/NoScrollGridView.java @@ -0,0 +1,47 @@ +package com.wss.common.widget; + +import android.content.Context; +import android.util.AttributeSet; +import android.widget.AdapterView; +import android.widget.GridView; + +import androidx.annotation.Nullable; + +/** + * 不可滑动的GridView + * + * @author 杨伟 + * create by 2020-4-27 + */ +public class NoScrollGridView extends GridView { + + public NoScrollGridView(Context context) { + super(context); + } + + public NoScrollGridView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public NoScrollGridView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + /** + * 设置GridView不可滑动 + * + * @param widthMeasureSpec + * @param heightMeasureSpec + */ + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, + MeasureSpec.AT_MOST); + super.onMeasure(widthMeasureSpec, expandSpec); + } + + @Override + public void setOnItemClickListener(@Nullable AdapterView.OnItemClickListener listener) { + super.setOnItemClickListener(listener); + } +} \ No newline at end of file diff --git a/common_base/src/main/java/com/wss/common/widget/NoScrollListView.java b/common_base/src/main/java/com/wss/common/widget/NoScrollListView.java new file mode 100644 index 0000000..d695c64 --- /dev/null +++ b/common_base/src/main/java/com/wss/common/widget/NoScrollListView.java @@ -0,0 +1,38 @@ +package com.wss.common.widget; + +import android.content.Context; +import android.util.AttributeSet; +import android.widget.ListView; + +/** + * 不可滑动的ListView + * @author 杨伟 + * create by 2020-4-17 + */ +public class NoScrollListView extends ListView { + + public NoScrollListView(Context context) { + super(context); + } + + public NoScrollListView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public NoScrollListView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + /** + * 设置listView不可滑动 + * + * @param widthMeasureSpec + * @param heightMeasureSpec + */ + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, + MeasureSpec.AT_MOST); + super.onMeasure(widthMeasureSpec, expandSpec); + } +} \ No newline at end of file diff --git a/common_base/src/main/java/com/wss/common/widget/NoScrollViewPager.java b/common_base/src/main/java/com/wss/common/widget/NoScrollViewPager.java index 7a36879..b1074c9 100644 --- a/common_base/src/main/java/com/wss/common/widget/NoScrollViewPager.java +++ b/common_base/src/main/java/com/wss/common/widget/NoScrollViewPager.java @@ -2,10 +2,11 @@ import android.annotation.SuppressLint; import android.content.Context; -import android.support.v4.view.ViewPager; import android.util.AttributeSet; import android.view.MotionEvent; +import androidx.viewpager.widget.ViewPager; + /** * Describe:可禁止滚动的ViewPager * Created by 吴天强 on 2018/11/1. diff --git a/common_base/src/main/java/com/wss/common/widget/NumberProgressBar.java b/common_base/src/main/java/com/wss/common/widget/NumberProgressBar.java index b129306..2b1b74a 100644 --- a/common_base/src/main/java/com/wss/common/widget/NumberProgressBar.java +++ b/common_base/src/main/java/com/wss/common/widget/NumberProgressBar.java @@ -10,10 +10,11 @@ import android.graphics.RectF; import android.graphics.Typeface; import android.util.AttributeSet; -import android.util.TypedValue; import android.view.View; import com.wss.common.base.R; +import com.wss.common.utils.PxUtils; + /** * Describe:数字进度条 @@ -25,14 +26,15 @@ public class NumberProgressBar extends View { /** * 右侧未完成进度条的颜色 */ - private int paintStartColor = 0xffe5e5e5; + private static final int PAINT_START_COLOR = 0xffe5e5e5; /** - * Contxt + * context */ private Context context; - /**l + /** + * l * 主线程传过来进程 0 - 100 */ private int progress; @@ -102,10 +104,10 @@ public NumberProgressBar(Context context, AttributeSet attrs) { super(context, attrs); this.context = context; // 构造器中初始化数据 - smallR = dip2px(context, 4);//小圆半径 - bigR = dip2px(context, 8);//大圆半径 - radius = dip2px(context, 10) / 2;//进度条高度 - jR = dip2px(context, 6);//矩形 + smallR = PxUtils.dp2px(4);//小圆半径 + bigR = PxUtils.dp2px(8);//大圆半径 + radius = PxUtils.dp2px(10) / 2;//进度条高度 + jR = PxUtils.dp2px(6);//矩形 initData(); } @@ -116,15 +118,15 @@ public NumberProgressBar(Context context, AttributeSet attrs) { private void initData() { // 未完成进度条画笔的属性 - paintStart.setColor(paintStartColor); - paintStart.setStrokeWidth(dip2px(context, 1)); + paintStart.setColor(PAINT_START_COLOR); + paintStart.setStrokeWidth(PxUtils.dp2px(1)); paintStart.setDither(true); paintStart.setAntiAlias(true); paintStart.setStyle(Paint.Style.FILL); // 已完成进度条画笔的属性 - paintInit.setColor(context.getResources().getColor(R.color.blue)); - paintInit.setStrokeWidth(dip2px(context, 1)); + paintInit.setColor(context.getResources().getColor(R.color.theme)); + paintInit.setStrokeWidth(PxUtils.dp2px(1)); paintInit.setAntiAlias(true); paintInit.setDither(true); paintInit.setStyle(Paint.Style.FILL); @@ -136,14 +138,14 @@ private void initData() { paintSmall.setStyle(Paint.Style.FILL); // 大圆画笔 - paintEndBig.setColor(context.getResources().getColor(R.color.blue)); + paintEndBig.setColor(context.getResources().getColor(R.color.theme)); paintEndBig.setAntiAlias(true); paintEndBig.setStyle(Paint.Style.FILL); // 百分比文字画笔的属性 - int paintTextSizePx = sp2px(context, 11); //设置百分比文字的尺寸 - paintText.setColor(context.getResources().getColor(R.color.blue)); + int paintTextSizePx = PxUtils.sp2px(11); //设置百分比文字的尺寸 + paintText.setColor(context.getResources().getColor(R.color.theme)); paintText.setTextSize(paintTextSizePx); paintText.setAntiAlias(true); paintText.setTypeface(Typeface.DEFAULT_BOLD); @@ -215,14 +217,4 @@ public void setProgress(int progress) { this.progress = progress; invalidate(); } - - public static int dip2px(Context ctx, float dp) { - float density = ctx.getResources().getDisplayMetrics().density; - int px = (int) (dp * density + 0.5f); - return px; - } - - public static int sp2px(Context context, float spValue) { - return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, spValue, context.getResources().getDisplayMetrics()); - } } \ No newline at end of file diff --git a/common_base/src/main/java/com/wss/common/widget/ObserverButton.java b/common_base/src/main/java/com/wss/common/widget/ObserverButton.java index 64b9f47..34b165a 100644 --- a/common_base/src/main/java/com/wss/common/widget/ObserverButton.java +++ b/common_base/src/main/java/com/wss/common/widget/ObserverButton.java @@ -11,20 +11,21 @@ import com.wss.common.base.R; +import org.jetbrains.annotations.NotNull; + import java.util.ArrayList; import java.util.List; +import androidx.appcompat.widget.AppCompatTextView; + /** * Describe:观察多个输入框的Button * Created by 吴天强 on 2018/10/26. */ - -public class ObserverButton extends android.support.v7.widget.AppCompatTextView { - +public class ObserverButton extends AppCompatTextView { private List editTextList = new ArrayList<>(); - private boolean canPress; private int defaultBg = Color.GRAY; private int pressBg = Color.BLUE; @@ -55,7 +56,7 @@ public ObserverButton(Context context, AttributeSet attrs, int defStyleAttr) { } - public void observer(EditText... editTexts) { + public void observer(@NotNull EditText... editTexts) { for (EditText editText : editTexts) { editText.addTextChangedListener(textWatcher); editTextList.add(editText); diff --git a/common_base/src/main/java/com/wss/common/widget/PagerSlidingTabStrip.java b/common_base/src/main/java/com/wss/common/widget/PagerSlidingTabStrip.java index 96a6528..fcb9632 100644 --- a/common_base/src/main/java/com/wss/common/widget/PagerSlidingTabStrip.java +++ b/common_base/src/main/java/com/wss/common/widget/PagerSlidingTabStrip.java @@ -1,17 +1,13 @@ package com.wss.common.widget; -import android.annotation.SuppressLint; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Paint.Style; import android.graphics.Typeface; -import android.os.Build; import android.os.Parcel; import android.os.Parcelable; -import android.support.v4.view.ViewPager; -import android.support.v4.view.ViewPager.OnPageChangeListener; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.TypedValue; @@ -25,23 +21,22 @@ import android.widget.TextView; import com.wss.common.base.R; +import com.wss.common.utils.PxUtils; + +import org.jetbrains.annotations.NotNull; import java.util.Locale; +import androidx.viewpager.widget.ViewPager; + /** * 水平滑动TabView * wtq 2016年6月28日14:09:46 */ public class PagerSlidingTabStrip extends HorizontalScrollView { - private static final String TAG = PagerSlidingTabStrip.class.getSimpleName(); - - public interface IconTabProvider { - int getPageIconResId(int position); - } - private final PageListener pageListener = new PageListener(); - public OnPageChangeListener delegatePageListener; + public ViewPager.OnPageChangeListener delegatePageListener; private LinearLayout tabsContainer; private ViewPager pager; @@ -54,23 +49,57 @@ public interface IconTabProvider { private Paint rectPaint; private Paint dividerPaint; - private int indicatorColor = 0XFFFF7F00;//指示器颜色 - private int underlineColor = 0XFFB9B9B9;//上下横向颜色 - private int dividerColor = 0X00FF7F00;//水平分割线颜色 - private int textDefaultColor = 0XFF999999;//标题默认颜色 - private int textSelectColor = indicatorColor;//标题选中颜色 + /** + * 指示器颜色 + */ + private int indicatorColor = 0XFFFF7F00; + /** + * 上下横向颜色 + */ + private int underlineColor = 0XFFB9B9B9; + /** + * 水平分割线颜色 + */ + private int dividerColor = 0X00FF7F00; + /** + * 标题默认颜色 + */ + private int textDefaultColor = 0XFF999999; + /** + * 标题选中颜色 + */ + private int textSelectColor = indicatorColor; - private boolean shouldExpand = true;//tab是否平均分配在屏幕上 + /** + * tab是否平均分配在屏幕上 + */ + private boolean shouldExpand = true; + /** + * 文字是否大写 + */ private boolean textAllCaps = true; - private boolean bold = false;//是否加粗 - private boolean topLine = true;//是否显示顶部横向 - private boolean bottomLine = true;//是否显示底部横向 + /** + * 文字是否加粗 + */ + private boolean bold = false; + /** + * 是否显示顶部横向 + */ + private boolean topLine = true; + /** + * 是否显示底部横向 + */ + private boolean bottomLine = true; private int scrollOffset = 52; private int indicatorHeight = 4; private float underlineHeight = 0.5f; private int dividerPadding = 12; - private int tabPadding = 17; + /** + * Tab左右边距 + */ + private int tabPaddingLeft = 0; + private int tabPaddingRight = 0; private int dividerWidth = 1; private int redDotTop = 15; private int redDotWidth = 20; @@ -87,8 +116,7 @@ public PagerSlidingTabStrip(Context context, AttributeSet attrs) { this(context, attrs, 0); } - public PagerSlidingTabStrip(Context context, AttributeSet attrs, - int defStyle) { + public PagerSlidingTabStrip(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); setFillViewport(true); @@ -96,77 +124,42 @@ public PagerSlidingTabStrip(Context context, AttributeSet attrs, tabsContainer = new LinearLayout(context); tabsContainer.setOrientation(LinearLayout.HORIZONTAL); - tabsContainer.setLayoutParams(new LayoutParams( - LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); + tabsContainer.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); addView(tabsContainer); + //把一些DP SP的值做一个转换 DisplayMetrics dm = getResources().getDisplayMetrics(); - - scrollOffset = (int) TypedValue.applyDimension( - TypedValue.COMPLEX_UNIT_DIP, scrollOffset, dm); - indicatorHeight = (int) TypedValue.applyDimension( - TypedValue.COMPLEX_UNIT_DIP, indicatorHeight, dm); - underlineHeight = (int) TypedValue.applyDimension( - TypedValue.COMPLEX_UNIT_DIP, underlineHeight, dm); - dividerPadding = (int) TypedValue.applyDimension( - TypedValue.COMPLEX_UNIT_DIP, dividerPadding, dm); - tabPadding = (int) TypedValue.applyDimension( - TypedValue.COMPLEX_UNIT_DIP, tabPadding, dm); - dividerWidth = (int) TypedValue.applyDimension( - TypedValue.COMPLEX_UNIT_DIP, dividerWidth, dm); - tabTextSize = (int) TypedValue.applyDimension( - TypedValue.COMPLEX_UNIT_SP, tabTextSize, dm); - redDotTop = (int) TypedValue.applyDimension( - TypedValue.COMPLEX_UNIT_DIP, redDotTop, dm); - redDotWidth = (int) TypedValue.applyDimension( - TypedValue.COMPLEX_UNIT_DIP, redDotWidth, dm); + scrollOffset = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, scrollOffset, dm); + indicatorHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, indicatorHeight, dm); + underlineHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, underlineHeight, dm); + dividerPadding = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dividerPadding, dm); + dividerWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dividerWidth, dm); + tabTextSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, tabTextSize, dm); + redDotTop = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, redDotTop, dm); + redDotWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, redDotWidth, dm); + tabPaddingLeft = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, tabPaddingLeft, dm); + tabPaddingRight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, tabPaddingRight, dm); + + //获取自定义属性值 TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PagerSlidingTabStrip); - - indicatorColor = a.getColor( - R.styleable.PagerSlidingTabStrip_pstsIndicatorColor, - indicatorColor); - textSelectColor = a.getColor( - R.styleable.PagerSlidingTabStrip_pstsTextSelectedColor, - textSelectColor); - textDefaultColor = a.getColor( - R.styleable.PagerSlidingTabStrip_pstsTextDefaultColor, - textDefaultColor); - underlineColor = a.getColor( - R.styleable.PagerSlidingTabStrip_pstsUnderlineColor, - underlineColor); - tabTextSize = a.getDimensionPixelSize( - R.styleable.PagerSlidingTabStrip_pstsTextSize, tabTextSize); - - dividerColor = a - .getColor(R.styleable.PagerSlidingTabStrip_pstsDividerColor, - dividerColor); - indicatorHeight = a.getDimensionPixelSize( - R.styleable.PagerSlidingTabStrip_pstsIndicatorHeight, - indicatorHeight); - bold = a.getBoolean(R.styleable.PagerSlidingTabStrip_pstsBold, - bold); - topLine = a.getBoolean(R.styleable.PagerSlidingTabStrip_pstsHasTopLine, - topLine); - bottomLine = a.getBoolean(R.styleable.PagerSlidingTabStrip_pstsHasBottomLine, - bottomLine); - dividerPadding = a.getDimensionPixelSize( - R.styleable.PagerSlidingTabStrip_pstsDividerPadding, - dividerPadding); - tabPadding = a.getDimensionPixelSize( - R.styleable.PagerSlidingTabStrip_pstsTabPaddingLeftRight, - tabPadding); - tabPadding = a.getDimensionPixelSize( - R.styleable.PagerSlidingTabStrip_pstsTextSize, tabPadding); - - shouldExpand = a - .getBoolean(R.styleable.PagerSlidingTabStrip_pstsShouldExpand, - shouldExpand); - scrollOffset = a - .getDimensionPixelSize( - R.styleable.PagerSlidingTabStrip_pstsScrollOffset, - scrollOffset); - textAllCaps = a.getBoolean( - R.styleable.PagerSlidingTabStrip_pstsTextAllCaps, textAllCaps); + indicatorColor = a.getColor(R.styleable.PagerSlidingTabStrip_pstsIndicatorColor, indicatorColor); + textSelectColor = a.getColor(R.styleable.PagerSlidingTabStrip_pstsTextSelectedColor, textSelectColor); + textDefaultColor = a.getColor(R.styleable.PagerSlidingTabStrip_pstsTextDefaultColor, textDefaultColor); + underlineColor = a.getColor(R.styleable.PagerSlidingTabStrip_pstsUnderlineColor, underlineColor); + tabTextSize = a.getDimensionPixelSize(R.styleable.PagerSlidingTabStrip_pstsTextSize, tabTextSize); + + dividerColor = a.getColor(R.styleable.PagerSlidingTabStrip_pstsDividerColor, dividerColor); + indicatorHeight = a.getDimensionPixelSize(R.styleable.PagerSlidingTabStrip_pstsIndicatorHeight, indicatorHeight); + bold = a.getBoolean(R.styleable.PagerSlidingTabStrip_pstsBold, bold); + topLine = a.getBoolean(R.styleable.PagerSlidingTabStrip_pstsHasTopLine, topLine); + bottomLine = a.getBoolean(R.styleable.PagerSlidingTabStrip_pstsHasBottomLine, bottomLine); + dividerPadding = a.getDimensionPixelSize(R.styleable.PagerSlidingTabStrip_pstsDividerPadding, dividerPadding); + tabPaddingLeft = a.getDimensionPixelSize(R.styleable.PagerSlidingTabStrip_pstsTabPaddingLeft, tabPaddingLeft); + tabPaddingRight = a.getDimensionPixelSize(R.styleable.PagerSlidingTabStrip_pstsTabPaddingRight, tabPaddingRight); + + shouldExpand = a.getBoolean(R.styleable.PagerSlidingTabStrip_pstsShouldExpand, shouldExpand); + scrollOffset = a.getDimensionPixelSize(R.styleable.PagerSlidingTabStrip_pstsScrollOffset, scrollOffset); + textAllCaps = a.getBoolean(R.styleable.PagerSlidingTabStrip_pstsTextAllCaps, textAllCaps); a.recycle(); @@ -183,60 +176,29 @@ public PagerSlidingTabStrip(Context context, AttributeSet attrs, } } - - public void setViewPager(ViewPager pager) { - this.pager = pager; - + /** + * 更新页面 + */ + private void notifyDataSetChanged() { if (pager.getAdapter() == null) { - throw new IllegalStateException( - "ViewPager does not have adapter instance."); + throw new IllegalStateException("ViewPager does not have adapter instance."); } - - pager.addOnPageChangeListener(pageListener); - notifyDataSetChanged(); - } - - public void setOnPageChangeListener(OnPageChangeListener listener) { - this.delegatePageListener = listener; - } - - public void notifyDataSetChanged() { - tabsContainer.removeAllViews(); - tabCount = pager.getAdapter().getCount(); - for (int i = 0; i < tabCount; i++) { - if (pager.getAdapter() instanceof IconTabProvider) { - addIconTab(i, - ((IconTabProvider) pager.getAdapter()) - .getPageIconResId(i)); + addIconTab(i, ((IconTabProvider) pager.getAdapter()).getPageIconResId(i)); } else { - String title = pager.getAdapter().getPageTitle(i).toString(); + String title = String.valueOf(pager.getAdapter().getPageTitle(i)); addTextTab(i, title); } - } - updateTabStyles(); - getViewTreeObserver().addOnGlobalLayoutListener( new OnGlobalLayoutListener() { - - @SuppressWarnings("deprecation") - @SuppressLint("NewApi") @Override public void onGlobalLayout() { - - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) { - getViewTreeObserver().removeGlobalOnLayoutListener( - this); - } else { - getViewTreeObserver().removeOnGlobalLayoutListener( - this); - } - + getViewTreeObserver().removeOnGlobalLayoutListener(this); currentPosition = pager.getCurrentItem(); scrollToChild(currentPosition, 0); } @@ -244,79 +206,76 @@ public void onGlobalLayout() { } + /** + * 添加文本Tab + * + * @param position 位置 + * @param title tab显示文字 + */ private void addTextTab(final int position, String title) { - - TextView tab = new TextView(getContext()); - tab.setText(title); - tab.setGravity(Gravity.CENTER); - tab.setSingleLine(); + TextView tvTab = new TextView(getContext()); + tvTab.setText(title); + tvTab.setGravity(Gravity.CENTER); + tvTab.setSingleLine(); if (position != 0) { - tab.setTextColor(textDefaultColor); - tab.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); + tvTab.setTextColor(textDefaultColor); + tvTab.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL)); } else { if (bold) { - tab.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD)); + tvTab.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD)); } - tab.setTextColor(textSelectColor); + tvTab.setTextColor(textSelectColor); } - - addTab(position, tab); + addTab(position, tvTab); } + /** + * 添加IconTab + * + * @param position position + * @param resId icon资源 + */ private void addIconTab(final int position, int resId) { - ImageButton tab = new ImageButton(getContext()); tab.setImageResource(resId); - addTab(position, tab); } - private void addTab(final int position, View tab) { - tab.setFocusable(true); - tab.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - if (onPagerTabClick != null) { - onPagerTabClick.onClick(position); - } - pager.setCurrentItem(position); + /** + * 添加Tab + * + * @param position 位置 + * @param tabView tab + */ + private void addTab(int position, @NotNull View tabView) { + tabView.setFocusable(true); + tabView.setOnClickListener(v -> { + if (onPagerTabClick != null) { + onPagerTabClick.onClick(position); } + pager.setCurrentItem(position); }); - tab.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, - LayoutParams.MATCH_PARENT)); - + tabView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT)); LinearLayout linearLayout = new LinearLayout(getContext()); if (shouldExpand) { - linearLayout.setLayoutParams(new LinearLayout.LayoutParams(0, - LayoutParams.MATCH_PARENT, 1.0f)); + linearLayout.setLayoutParams(new LinearLayout.LayoutParams(0, LayoutParams.MATCH_PARENT, 1.0f)); } else { - linearLayout.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, - LayoutParams.MATCH_PARENT)); + LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT); + lp.setMargins(0, 0, PxUtils.dp2px(20), 0); + linearLayout.setLayoutParams(lp); } - - linearLayout.setLayoutParams(new LinearLayout.LayoutParams(0, LayoutParams.MATCH_PARENT, 1.0f)); - linearLayout.setPadding(tabPadding, 0, tabPadding, 0); + linearLayout.setPadding(tabPaddingLeft, 0, tabPaddingRight, 0); linearLayout.setGravity(Gravity.CENTER); -// ImageView view = new ImageView(getContext()); -// view.setLayoutParams(new LayoutParams(redDotWidth, redDotWidth)); -// view.setPadding(0, redDotTop, 0, 0); -// view.setImageBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.red)); -// view.setVisibility(View.GONE); - linearLayout.addView(tab); -// linearLayout.addView(view); + linearLayout.addView(tabView); tabsContainer.addView(linearLayout); } private void updateTabStyles() { - for (int i = 0; i < tabCount; i++) { - View v = ((ViewGroup) tabsContainer.getChildAt(i)).getChildAt(0); - if (v instanceof TextView) { - TextView tab = (TextView) v; if (i != 0) { tab.setTextColor(textDefaultColor); @@ -328,7 +287,6 @@ private void updateTabStyles() { tab.setTextColor(textSelectColor); } tab.setTextSize(TypedValue.COMPLEX_UNIT_PX, tabTextSize); - tab.setAllCaps(textAllCaps); } } @@ -414,18 +372,17 @@ protected void onDraw(Canvas canvas) { } } - private class PageListener implements OnPageChangeListener { + private class PageListener implements ViewPager.OnPageChangeListener { @Override - public void onPageScrolled(int position, float positionOffset, - int positionOffsetPixels) { + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { currentPosition = position; currentPositionOffset = positionOffset; - if (tabsContainer.getChildAt(position) != null) - scrollToChild(position, (int) (positionOffset * tabsContainer - .getChildAt(position).getWidth())); + if (tabsContainer.getChildAt(position) != null) { + scrollToChild(position, (int) (positionOffset * tabsContainer.getChildAt(position).getWidth())); + } invalidate(); @@ -507,7 +464,7 @@ public void writeToParcel(Parcel dest, int flags) { dest.writeInt(currentPosition); } - public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { + public static final Creator CREATOR = new Creator() { @Override public SavedState createFromParcel(Parcel in) { return new SavedState(in); @@ -547,6 +504,25 @@ public void showPosition(int position) { viewGroup.getChildAt(1).setVisibility(View.VISIBLE); } } + /** + * 添加ViewPager + * + * @param pager ViewPager + */ + public void setViewPager(@NotNull ViewPager pager) { + this.pager = pager; + pager.addOnPageChangeListener(pageListener); + notifyDataSetChanged(); + } + + /** + * 设置ViewPager滑动监听 + * + * @param listener 监听器 + */ + public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener) { + this.delegatePageListener = listener; + } /** * 下方滑动指示器颜色 @@ -687,9 +663,13 @@ public void setTextSelectColorResource(int resId) { /** * 设置item左右padding + * + * @param leftPadding 左边距 + * @param rightPadding 右边距 */ - public void setTabPaddingLeftRight(int paddingPx) { - this.tabPadding = paddingPx; + public void setTabPadding(int leftPadding, int rightPadding) { + this.tabPaddingLeft = leftPadding; + this.tabPaddingRight = rightPadding; updateTabStyles(); } @@ -709,5 +689,17 @@ public void setShowTopLine(boolean show) { invalidate(); } + /** + * IconTab 提供则 + */ + public interface IconTabProvider { + /** + * 返回Icon资源ID + * + * @param position position + * @return icon资源图片 + */ + int getPageIconResId(int position); + } } diff --git a/common_base/src/main/java/com/wss/common/widget/ProgressWebView.java b/common_base/src/main/java/com/wss/common/widget/ProgressWebView.java deleted file mode 100644 index f2bf3f6..0000000 --- a/common_base/src/main/java/com/wss/common/widget/ProgressWebView.java +++ /dev/null @@ -1,108 +0,0 @@ -package com.wss.common.widget; - -import android.annotation.SuppressLint; -import android.content.Context; -import android.os.Build; -import android.os.Handler; -import android.support.annotation.RequiresApi; -import android.text.TextUtils; -import android.util.AttributeSet; -import android.view.View; -import android.view.ViewGroup; -import android.webkit.WebChromeClient; -import android.webkit.WebSettings; -import android.webkit.WebView; - -import com.wss.common.widget.dialog.LoadingDialog; - - -/** - * 带进度条的WebView - * wtq 2016年6月28日14:09:46 - */ -public class ProgressWebView extends WebView { - private WebViewProgressBar progressBar; - private Handler handler; - private WebView _this; - private LoadingDialog loadingDialog; - - @SuppressLint("SetJavaScriptEnabled") - @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) - public ProgressWebView(Context context, AttributeSet attrs) { - super(context, attrs); - progressBar = new WebViewProgressBar(context); - progressBar.setLayoutParams(new ViewGroup.LayoutParams - (ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); - progressBar.setVisibility(GONE); - addView(progressBar); - handler = new Handler(); - _this = this; - loadingDialog = new LoadingDialog(context); - loadingDialog.setCancelable(true); - - setWebChromeClient(new MyWebChromeClient()); -// setWebViewClient(new MyWebClient()); - - /** - * Webview在安卓5.0之前默认允许其加载混合网络协议内容 - * 在安卓5.0之后,默认不允许加载http与https混合内容,需要设置webview允许其加载混合网络协议内容 - */ - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW); - - } - - /** 设置webView不显示图片问题 */ - if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) { - getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW); - } - getSettings().setJavaScriptEnabled(true); - getSettings().setBlockNetworkImage(false); - - } - - public void showDialog(String text) { - if (!TextUtils.isEmpty(text)) { - loadingDialog.setTitleText("正在加载···"); - } - loadingDialog.show(); - } - - private class MyWebChromeClient extends WebChromeClient { - @Override - public void onProgressChanged(WebView view, int newProgress) { - if (newProgress == 100) { - progressBar.setProgress(100); - handler.postDelayed(runnable, 200); - } else if (progressBar.getVisibility() == GONE) { - progressBar.setVisibility(VISIBLE); - } - if (newProgress < 5) { - newProgress = 5; - } - progressBar.setProgress(newProgress); - super.onProgressChanged(view, newProgress); - } - } - - - - - private Runnable runnable = new Runnable() { - @Override - public void run() { - dismissDialog(); - } - }; - - /** - * 关闭加载框 - */ - public void dismissDialog() { - if (loadingDialog.isShowing()) { - loadingDialog.dismiss(); - } - progressBar.setVisibility(View.GONE); - } - -} \ No newline at end of file diff --git a/common_base/src/main/java/com/wss/common/widget/SlideLayout.java b/common_base/src/main/java/com/wss/common/widget/SlideLayout.java index aa61dee..7f8fefe 100644 --- a/common_base/src/main/java/com/wss/common/widget/SlideLayout.java +++ b/common_base/src/main/java/com/wss/common/widget/SlideLayout.java @@ -7,8 +7,6 @@ import android.content.res.TypedArray; import android.os.Parcel; import android.os.Parcelable; -import android.support.v4.view.MotionEventCompat; -import android.support.v4.view.ViewCompat; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; @@ -21,6 +19,9 @@ import com.wss.common.base.R; +import androidx.core.view.MotionEventCompat; +import androidx.core.view.ViewCompat; + /** * Describe:分页滑动Layout 如:商品详情页 滑动查看图文详情 @@ -580,10 +581,13 @@ public void writeToParcel(Parcel out, int flags) { public static final Creator CREATOR = new Creator() { + + @Override public SavedState createFromParcel(Parcel in) { return new SavedState(in); } + @Override public SavedState[] newArray(int size) { return new SavedState[size]; } diff --git a/common_base/src/main/java/com/wss/common/widget/StickyNavLayout.java b/common_base/src/main/java/com/wss/common/widget/StickyNavLayout.java new file mode 100644 index 0000000..257c526 --- /dev/null +++ b/common_base/src/main/java/com/wss/common/widget/StickyNavLayout.java @@ -0,0 +1,394 @@ +package com.wss.common.widget; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; + +import java.util.ArrayList; +import java.util.List; + +import androidx.core.widget.NestedScrollView; + +/** + * Describe:滑动粘性ScrollView,设置View的tag = sticky 滑动可吸顶 + * Created by 吴天强 on 2020/05/13. + * Copy from: https://github.com/LidongWen/MultiTypeAdapter + */ +public class StickyNavLayout extends NestedScrollView { + + public interface OnViewStickyListener { + + void onSticky(View view); + + void onUnSticky(View view); + } + + /** + * Tag for views that should stick and have constant drawing. e.g. TextViews, ImageViews etc + */ + public static final String STICKY_TAG = "sticky"; + /** + * Flag for views that should stick and have non-constant drawing. e.g. Buttons, ProgressBars etc + */ + public static final String FLAG_NONCONSTANT = "-nonconstant"; + /** + * Flag for views that have aren't fully opaque + */ + public static final String FLAG_HASTRANSPARENCY = "-hastransparency"; + /** + * Default height of the shadow peeking out below the stuck view. + */ + private static final int DEFAULT_SHADOW_HEIGHT = 10; // dp; + private ArrayList stickyViews; + private View currentlyStickingView; + private float stickyViewTopOffset; + private final Runnable invalidateRunnable = new Runnable() { + @Override + public void run() { + if (currentlyStickingView != null) { + int l = getLeftForViewRelativeOnlyChild(currentlyStickingView); + int t = getBottomForViewRelativeOnlyChild(currentlyStickingView); + int r = getRightForViewRelativeOnlyChild(currentlyStickingView); + int b = (int) (getScrollY() + (currentlyStickingView.getHeight() + stickyViewTopOffset)); + invalidate(l, t, r, b); + } + postDelayed(this, 16); + } + }; + private int stickyViewLeftOffset; + private boolean redirectTouchesToStickyView; + private boolean clippingToPadding; + private boolean clipToPaddingHasBeenSet; + private int mShadowHeight = DEFAULT_SHADOW_HEIGHT; + private Drawable mShadowDrawable; + private boolean hasNotDoneActionDown = true; + + private List mOnViewStickyListeners; + + public StickyNavLayout(Context context) { + this(context, null); + } + + public StickyNavLayout(Context context, AttributeSet attrs) { + this(context, attrs, android.R.attr.scrollViewStyle); + } + + public StickyNavLayout(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + setup(); + } + + public void addOnViewStickyListener(OnViewStickyListener stickyListener) { + if (mOnViewStickyListeners == null) + mOnViewStickyListeners = new ArrayList<>(); + mOnViewStickyListeners.add(stickyListener); + } + + public void removeOnViewStickyListener(OnViewStickyListener stickyListener) { + if (mOnViewStickyListeners != null) + mOnViewStickyListeners.remove(stickyListener); + } + + public void clearOnViewStickyListener() { + if (mOnViewStickyListeners != null) + mOnViewStickyListeners.clear(); + } + + public void setShadowHeight(int height) { + mShadowHeight = height; + } + + public void setShadowDrawable(Drawable shadowDrawable) { + mShadowDrawable = shadowDrawable; + } + + public void setup() { + stickyViews = new ArrayList<>(); + } + + private int getLeftForViewRelativeOnlyChild(View v) { + int left = v.getLeft(); + while (v.getParent() != null && v.getParent() != getChildAt(0)) { + v = (View) v.getParent(); + left += v.getLeft(); + } + return left; + } + + private int getTopForViewRelativeOnlyChild(View v) { + int top = v.getTop(); + while (v.getParent() != null && v.getParent() != getChildAt(0)) { + v = (View) v.getParent(); + top += v.getTop(); + } + return top; + } + + private int getRightForViewRelativeOnlyChild(View v) { + int right = v.getRight(); + while (v.getParent() != null && v.getParent() != getChildAt(0)) { + v = (View) v.getParent(); + right += v.getRight(); + } + return right; + } + + private int getBottomForViewRelativeOnlyChild(View v) { + int bottom = v.getBottom(); + while (v.getParent() != null && v.getParent() != getChildAt(0)) { + v = (View) v.getParent(); + bottom += v.getBottom(); + } + return bottom; + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + super.onLayout(changed, l, t, r, b); + if (!clipToPaddingHasBeenSet) { + clippingToPadding = true; + } + notifyHierarchyChanged(); + } + + @Override + public void setClipToPadding(boolean clipToPadding) { + super.setClipToPadding(clipToPadding); + clippingToPadding = clipToPadding; + clipToPaddingHasBeenSet = true; + } + + @Override + public void addView(View child) { + super.addView(child); + findStickyViews(child); + } + + @Override + public void addView(View child, int index) { + super.addView(child, index); + findStickyViews(child); + } + + @Override + public void addView(View child, int index, ViewGroup.LayoutParams params) { + super.addView(child, index, params); + findStickyViews(child); + } + + @Override + public void addView(View child, int width, int height) { + super.addView(child, width, height); + findStickyViews(child); + } + + @Override + public void addView(View child, ViewGroup.LayoutParams params) { + super.addView(child, params); + findStickyViews(child); + } + + @Override + protected void dispatchDraw(Canvas canvas) { + super.dispatchDraw(canvas); + if (currentlyStickingView != null) { + canvas.save(); + canvas.translate(getPaddingLeft() + stickyViewLeftOffset, getScrollY() + + stickyViewTopOffset + (clippingToPadding ? getPaddingTop() : 0)); + canvas.clipRect(0, (clippingToPadding ? -stickyViewTopOffset : 0), + getWidth() - stickyViewLeftOffset, + currentlyStickingView.getHeight() + mShadowHeight + 1); + if (mShadowDrawable != null) { + int left = 0; + int top = currentlyStickingView.getHeight(); + int right = currentlyStickingView.getWidth(); + int bottom = currentlyStickingView.getHeight() + mShadowHeight; + mShadowDrawable.setBounds(left, top, right, bottom); + mShadowDrawable.draw(canvas); + } + canvas.clipRect(0, (clippingToPadding ? -stickyViewTopOffset : 0), getWidth(), + currentlyStickingView.getHeight()); + if (getStringTagForView(currentlyStickingView).contains(FLAG_HASTRANSPARENCY)) { + showView(currentlyStickingView); + currentlyStickingView.draw(canvas); + hideView(currentlyStickingView); + } else { + currentlyStickingView.draw(canvas); + } + canvas.restore(); + } + } + + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + if (ev.getAction() == MotionEvent.ACTION_DOWN) { + redirectTouchesToStickyView = true; + } + if (redirectTouchesToStickyView) { + redirectTouchesToStickyView = currentlyStickingView != null; + if (redirectTouchesToStickyView) { + redirectTouchesToStickyView = + ev.getY() <= (currentlyStickingView.getHeight() + stickyViewTopOffset) && + ev.getX() >= getLeftForViewRelativeOnlyChild(currentlyStickingView) && + ev.getX() <= getRightForViewRelativeOnlyChild(currentlyStickingView); + } + } else if (currentlyStickingView == null) { + redirectTouchesToStickyView = false; + } + if (redirectTouchesToStickyView) { + ev.offsetLocation(0, -1 * ((getScrollY() + stickyViewTopOffset) + - getTopForViewRelativeOnlyChild(currentlyStickingView))); + } + return super.dispatchTouchEvent(ev); + } + + @Override + public boolean onTouchEvent(MotionEvent ev) { + if (redirectTouchesToStickyView) { + ev.offsetLocation(0, ((getScrollY() + stickyViewTopOffset) + - getTopForViewRelativeOnlyChild(currentlyStickingView))); + } + if (ev.getAction() == MotionEvent.ACTION_DOWN) { + hasNotDoneActionDown = false; + } + if (hasNotDoneActionDown) { + MotionEvent down = MotionEvent.obtain(ev); + down.setAction(MotionEvent.ACTION_DOWN); + super.onTouchEvent(down); + hasNotDoneActionDown = false; + } + if (ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_CANCEL) { + hasNotDoneActionDown = true; + } + return super.onTouchEvent(ev); + } + + @Override + protected void onScrollChanged(int l, int t, int oldl, int oldt) { + super.onScrollChanged(l, t, oldl, oldt); + doTheStickyThing(); + } + + private void doTheStickyThing() { + View viewThatShouldStick = null; + View approachingView = null; + for (View v : stickyViews) { + int viewTop = getTopForViewRelativeOnlyChild(v) - getScrollY() + + (clippingToPadding ? 0 : getPaddingTop()); + if (viewTop <= 0) { + if (viewThatShouldStick == null || viewTop > + (getTopForViewRelativeOnlyChild(viewThatShouldStick) + - getScrollY() + (clippingToPadding ? 0 : getPaddingTop()))) { + viewThatShouldStick = v; + } + } else { + if (approachingView == null || viewTop < (getTopForViewRelativeOnlyChild(approachingView) + - getScrollY() + (clippingToPadding ? 0 : getPaddingTop()))) { + approachingView = v; + } + } + } + if (viewThatShouldStick != null) { + stickyViewTopOffset = approachingView == null ? 0 : + Math.min(0, getTopForViewRelativeOnlyChild(approachingView) - getScrollY() + + (clippingToPadding ? 0 : getPaddingTop()) - viewThatShouldStick.getHeight()); + if (viewThatShouldStick != currentlyStickingView) { + if (currentlyStickingView != null) { + if (mOnViewStickyListeners != null) + for (OnViewStickyListener onViewStickyListener : mOnViewStickyListeners) + onViewStickyListener.onUnSticky(currentlyStickingView); + stopStickingCurrentlyStickingView(); + } + // only compute the x offset when we start sticking. + stickyViewLeftOffset = getLeftForViewRelativeOnlyChild(viewThatShouldStick); + startStickingView(viewThatShouldStick); + if (mOnViewStickyListeners != null) + for (OnViewStickyListener onViewStickyListener : mOnViewStickyListeners) + onViewStickyListener.onSticky(currentlyStickingView); + } + } else if (currentlyStickingView != null) { + if (mOnViewStickyListeners != null) + for (OnViewStickyListener onViewStickyListener : mOnViewStickyListeners) + onViewStickyListener.onUnSticky(currentlyStickingView); + stopStickingCurrentlyStickingView(); + } + } + + private void startStickingView(View viewThatShouldStick) { + currentlyStickingView = viewThatShouldStick; + if (currentlyStickingView != null) { + if (getStringTagForView(currentlyStickingView).contains(FLAG_HASTRANSPARENCY)) { + hideView(currentlyStickingView); + } + if (getStringTagForView(currentlyStickingView).contains(FLAG_NONCONSTANT)) { + post(invalidateRunnable); + } + } + } + + private void stopStickingCurrentlyStickingView() { + if (getStringTagForView(currentlyStickingView).contains(FLAG_HASTRANSPARENCY)) { + showView(currentlyStickingView); + } + currentlyStickingView = null; + removeCallbacks(invalidateRunnable); + } + + @Override + protected void onDetachedFromWindow() { + removeCallbacks(invalidateRunnable); + super.onDetachedFromWindow(); + } + + /** + * Notify that the sticky attribute has been added or removed from one or more views in the View hierarchy + */ + public void notifyStickyAttributeChanged() { + notifyHierarchyChanged(); + } + + private void notifyHierarchyChanged() { + if (currentlyStickingView != null) { + stopStickingCurrentlyStickingView(); + } + stickyViews.clear(); + findStickyViews(getChildAt(0)); + doTheStickyThing(); + invalidate(); + } + + private void findStickyViews(View v) { + if (!detainStickyView(v) && (v instanceof ViewGroup)) { + ViewGroup vg = (ViewGroup) v; + for (int i = 0; i < vg.getChildCount(); i++) + findStickyViews(vg.getChildAt(i)); + } + } + + private boolean detainStickyView(View view) { + String tag = getStringTagForView(view); + if (tag.contains(STICKY_TAG)) { + stickyViews.add(view); + return true; + } + return false; + } + + private String getStringTagForView(View v) { + Object tagObject = v.getTag(); + return String.valueOf(tagObject); + } + + private void hideView(View v) { + v.setAlpha(0); + } + + private void showView(View v) { + v.setAlpha(1); + } + +} \ No newline at end of file diff --git a/common_base/src/main/java/com/wss/common/widget/StrongRadioGroup.java b/common_base/src/main/java/com/wss/common/widget/StrongRadioGroup.java index 66889fb..226a45f 100644 --- a/common_base/src/main/java/com/wss/common/widget/StrongRadioGroup.java +++ b/common_base/src/main/java/com/wss/common/widget/StrongRadioGroup.java @@ -14,13 +14,9 @@ * Describe:可添加任意ViewGroup的RadioGroup * Created by 吴天强 on 2019/3/18. */ - public class StrongRadioGroup extends LinearLayout { - // holds the checked id; the selection is empty by default private int mCheckedId = -1; - // tracks children radio buttons checked state private CompoundButton.OnCheckedChangeListener mChildOnCheckedChangeListener; - // when true, mOnCheckedChangeListener discards events private boolean mProtectFromCheckedChange = false; private OnCheckedChangeListener mOnCheckedChangeListener; private PassThroughHierarchyChangeListener mPassThroughListener; @@ -192,7 +188,7 @@ public void setOnCheckedChangeListener(OnCheckedChangeListener listener) { */ @Override public LayoutParams generateLayoutParams(AttributeSet attrs) { - return new StrongRadioGroup.LayoutParams(getContext(), attrs); + return new LayoutParams(getContext(), attrs); } /** @@ -200,7 +196,7 @@ public LayoutParams generateLayoutParams(AttributeSet attrs) { */ @Override protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { - return p instanceof StrongRadioGroup.LayoutParams; + return p instanceof LayoutParams; } @Override @@ -260,9 +256,9 @@ public LayoutParams(MarginLayoutParams source) { /** *

* Fixes the child's width to - * {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT} and the + * {@link ViewGroup.LayoutParams#WRAP_CONTENT} and the * child's height to - * {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT} when not + * {@link ViewGroup.LayoutParams#WRAP_CONTENT} when not * specified in the XML file. *

* @@ -335,8 +331,8 @@ public void onCheckedChanged(CompoundButton buttonView, *

*/ private class PassThroughHierarchyChangeListener implements - ViewGroup.OnHierarchyChangeListener { - private ViewGroup.OnHierarchyChangeListener mOnHierarchyChangeListener; + OnHierarchyChangeListener { + private OnHierarchyChangeListener mOnHierarchyChangeListener; public void onChildViewAdded(View parent, View child) { if (parent == StrongRadioGroup.this && child instanceof RadioButton) { diff --git a/common_base/src/main/java/com/wss/common/widget/SwipeItemLayout.java b/common_base/src/main/java/com/wss/common/widget/SwipeItemLayout.java new file mode 100644 index 0000000..03dd298 --- /dev/null +++ b/common_base/src/main/java/com/wss/common/widget/SwipeItemLayout.java @@ -0,0 +1,780 @@ +package com.wss.common.widget; + +import android.content.Context; +import android.util.AttributeSet; +import android.util.Log; +import android.view.MotionEvent; +import android.view.VelocityTracker; +import android.view.View; +import android.view.ViewConfiguration; +import android.view.ViewGroup; +import android.view.ViewParent; +import android.view.animation.Interpolator; +import android.widget.Scroller; + +import androidx.core.view.ViewCompat; +import androidx.recyclerview.widget.RecyclerView; + +/** + * Describe:可侧滑ViewGroup,其中子ViewGroup有且只能有2个 + * Created by 吴天强 on 2020/4/20. + * Copy from: https://github.com/fornana/swipeitemlayout + */ +public class SwipeItemLayout extends ViewGroup { + enum Mode { + RESET, DRAG, FLING, TAP + } + + private Mode mTouchMode; + + private ViewGroup mMainView; + private ViewGroup mSideView; + + private ScrollRunnable mScrollRunnable; + private int mScrollOffset; + private int mMaxScrollOffset; + + private boolean mInLayout; + private boolean mIsLaidOut; + + public SwipeItemLayout(Context context) { + this(context, null); + } + + public SwipeItemLayout(Context context, AttributeSet attrs) { + super(context, attrs); + + mTouchMode = Mode.RESET; + mScrollOffset = 0; + mIsLaidOut = false; + + mScrollRunnable = new ScrollRunnable(context); + } + + public boolean isOpen() { + return mScrollOffset != 0; + } + + Mode getTouchMode() { + return mTouchMode; + } + + void setTouchMode(Mode mode) { + switch (mTouchMode) { + case FLING: + mScrollRunnable.abort(); + break; + case RESET: + break; + } + + mTouchMode = mode; + } + + public void open() { + if (mScrollOffset != -mMaxScrollOffset) { + //正在open,不需要处理 + if (mTouchMode == Mode.FLING && mScrollRunnable.isScrollToLeft()) + return; + + //当前正在向右滑,abort + if (mTouchMode == Mode.FLING /*&& !mScrollRunnable.mScrollToLeft*/) + mScrollRunnable.abort(); + + mScrollRunnable.startScroll(mScrollOffset, -mMaxScrollOffset); + } + } + + public void close() { + if (mScrollOffset != 0) { + //正在close,不需要处理 + if (mTouchMode == Mode.FLING && !mScrollRunnable.isScrollToLeft()) + return; + + //当前正向左滑,abort + if (mTouchMode == Mode.FLING /*&& mScrollRunnable.mScrollToLeft*/) + mScrollRunnable.abort(); + + mScrollRunnable.startScroll(mScrollOffset, 0); + } + } + + void fling(int xVel) { + mScrollRunnable.startFling(mScrollOffset, xVel); + } + + void revise() { + if (mScrollOffset < -mMaxScrollOffset / 2) + open(); + else + close(); + } + + boolean trackMotionScroll(int deltaX) { + if (deltaX == 0) + return false; + + boolean over = false; + int newLeft = mScrollOffset + deltaX; + if ((deltaX > 0 && newLeft > 0) || (deltaX < 0 && newLeft < -mMaxScrollOffset)) { + over = true; + newLeft = Math.min(newLeft, 0); + newLeft = Math.max(newLeft, -mMaxScrollOffset); + } + + offsetChildrenLeftAndRight(newLeft - mScrollOffset); + mScrollOffset = newLeft; + return over; + } + + private boolean ensureChildren() { + int childCount = getChildCount(); + + if (childCount != 2) + return false; + + View childView = getChildAt(0); + if (!(childView instanceof ViewGroup)) + return false; + mMainView = (ViewGroup) childView; + + childView = getChildAt(1); + if (!(childView instanceof ViewGroup)) + return false; + mSideView = (ViewGroup) childView; + return true; + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + if (!ensureChildren()) + throw new RuntimeException("SwipeItemLayout的子视图不符合规定"); + + int widthMode = MeasureSpec.getMode(widthMeasureSpec); + int widthSize = MeasureSpec.getSize(widthMeasureSpec); + int heightMode = MeasureSpec.getMode(heightMeasureSpec); + int heightSize = MeasureSpec.getSize(heightMeasureSpec); + + MarginLayoutParams lp = null; + int horizontalMargin, verticalMargin; + int horizontalPadding = getPaddingLeft() + getPaddingRight(); + int verticalPadding = getPaddingTop() + getPaddingBottom(); + + lp = (MarginLayoutParams) mMainView.getLayoutParams(); + horizontalMargin = lp.leftMargin + lp.rightMargin; + verticalMargin = lp.topMargin + lp.bottomMargin; + measureChildWithMargins(mMainView, + widthMeasureSpec, horizontalMargin + horizontalPadding, + heightMeasureSpec, verticalMargin + verticalPadding); + + if (widthMode == MeasureSpec.AT_MOST) + widthSize = Math.min(widthSize, mMainView.getMeasuredWidth() + horizontalMargin + horizontalPadding); + else if (widthMode == MeasureSpec.UNSPECIFIED) + widthSize = mMainView.getMeasuredWidth() + horizontalMargin + horizontalPadding; + + if (heightMode == MeasureSpec.AT_MOST) + heightSize = Math.min(heightSize, mMainView.getMeasuredHeight() + verticalMargin + verticalPadding); + else if (heightMode == MeasureSpec.UNSPECIFIED) + heightSize = mMainView.getMeasuredHeight() + verticalMargin + verticalPadding; + + setMeasuredDimension(widthSize, heightSize); + + //side layout大小为自身实际大小 + lp = (MarginLayoutParams) mSideView.getLayoutParams(); + verticalMargin = lp.topMargin + lp.bottomMargin; + mSideView.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), + MeasureSpec.makeMeasureSpec(getMeasuredHeight() - verticalMargin - verticalPadding, MeasureSpec.EXACTLY)); + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + if (!ensureChildren()) + throw new RuntimeException("SwipeItemLayout的子视图不符合规定"); + + mInLayout = true; + + int pl = getPaddingLeft(); + int pt = getPaddingTop(); + int pr = getPaddingRight(); + int pb = getPaddingBottom(); + + MarginLayoutParams mainLp = (MarginLayoutParams) mMainView.getLayoutParams(); + MarginLayoutParams sideParams = (MarginLayoutParams) mSideView.getLayoutParams(); + + int childLeft = pl + mainLp.leftMargin; + int childTop = pt + mainLp.topMargin; + int childRight = getWidth() - (pr + mainLp.rightMargin); + int childBottom = getHeight() - (mainLp.bottomMargin + pb); + mMainView.layout(childLeft, childTop, childRight, childBottom); + + childLeft = childRight + sideParams.leftMargin; + childTop = pt + sideParams.topMargin; + childRight = childLeft + sideParams.leftMargin + sideParams.rightMargin + mSideView.getMeasuredWidth(); + childBottom = getHeight() - (sideParams.bottomMargin + pb); + mSideView.layout(childLeft, childTop, childRight, childBottom); + + mMaxScrollOffset = mSideView.getWidth() + sideParams.leftMargin + sideParams.rightMargin; + mScrollOffset = mScrollOffset < -mMaxScrollOffset / 2 ? -mMaxScrollOffset : 0; + + offsetChildrenLeftAndRight(mScrollOffset); + mInLayout = false; + mIsLaidOut = true; + } + + void offsetChildrenLeftAndRight(int delta) { + ViewCompat.offsetLeftAndRight(mMainView, delta); + ViewCompat.offsetLeftAndRight(mSideView, delta); + } + + @Override + public void requestLayout() { + if (!mInLayout) { + super.requestLayout(); + } + } + + @Override + protected LayoutParams generateDefaultLayoutParams() { + return new MarginLayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); + } + + @Override + protected LayoutParams generateLayoutParams(LayoutParams p) { + return p instanceof MarginLayoutParams ? p : new MarginLayoutParams(p); + } + + @Override + protected boolean checkLayoutParams(LayoutParams p) { + return p instanceof MarginLayoutParams && super.checkLayoutParams(p); + } + + @Override + public LayoutParams generateLayoutParams(AttributeSet attrs) { + return new MarginLayoutParams(getContext(), attrs); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + + if (mScrollOffset != 0 && mIsLaidOut) { + offsetChildrenLeftAndRight(-mScrollOffset); + mScrollOffset = 0; + } else + mScrollOffset = 0; + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + + if (mScrollOffset != 0 && mIsLaidOut) { + offsetChildrenLeftAndRight(-mScrollOffset); + mScrollOffset = 0; + } else + mScrollOffset = 0; + removeCallbacks(mScrollRunnable); + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + final int action = ev.getActionMasked(); + //click main view,但是它处于open状态,所以,不需要点击效果,直接拦截不调用click listener + switch (action) { + case MotionEvent.ACTION_DOWN: { + final int x = (int) ev.getX(); + final int y = (int) ev.getY(); + View pointView = findTopChildUnder(this, x, y); + if (pointView != null && pointView == mMainView && mScrollOffset != 0) + return true; + break; + } + + case MotionEvent.ACTION_MOVE: + case MotionEvent.ACTION_CANCEL: + break; + + case MotionEvent.ACTION_UP: { + final int x = (int) ev.getX(); + final int y = (int) ev.getY(); + View pointView = findTopChildUnder(this, x, y); + if (pointView != null && pointView == mMainView && mTouchMode == Mode.TAP && mScrollOffset != 0) + return true; + } + } + + return false; + } + + @Override + public boolean onTouchEvent(MotionEvent ev) { + final int action = ev.getActionMasked(); + //click main view,但是它处于open状态,所以,不需要点击效果,直接拦截不调用click listener + switch (action) { + case MotionEvent.ACTION_DOWN: { + final int x = (int) ev.getX(); + final int y = (int) ev.getY(); + View pointView = findTopChildUnder(this, x, y); + if (pointView != null && pointView == mMainView && mScrollOffset != 0) + return true; + break; + } + + case MotionEvent.ACTION_MOVE: + case MotionEvent.ACTION_CANCEL: + break; + + case MotionEvent.ACTION_UP: { + final int x = (int) ev.getX(); + final int y = (int) ev.getY(); + View pointView = findTopChildUnder(this, x, y); + if (pointView != null && pointView == mMainView && mTouchMode == Mode.TAP && mScrollOffset != 0) { + close(); + return true; + } + } + } + + return false; + } + + @Override + protected void onVisibilityChanged(View changedView, int visibility) { + super.onVisibilityChanged(changedView, visibility); + if (getVisibility() != View.VISIBLE) { + mScrollOffset = 0; + invalidate(); + } + } + + private static final Interpolator sInterpolator = new Interpolator() { + @Override + public float getInterpolation(float t) { + t -= 1.0f; + return t * t * t * t * t + 1.0f; + } + }; + + class ScrollRunnable implements Runnable { + private static final int FLING_DURATION = 200; + private Scroller mScroller; + private boolean mAbort; + private int mMinVelocity; + private boolean mScrollToLeft; + + ScrollRunnable(Context context) { + mScroller = new Scroller(context, sInterpolator); + mAbort = false; + mScrollToLeft = false; + + ViewConfiguration configuration = ViewConfiguration.get(context); + mMinVelocity = configuration.getScaledMinimumFlingVelocity(); + } + + void startScroll(int startX, int endX) { + if (startX != endX) { + Log.e("scroll - startX - endX", "" + startX + " " + endX); + setTouchMode(Mode.FLING); + mAbort = false; + mScrollToLeft = endX < startX; + mScroller.startScroll(startX, 0, endX - startX, 0, 400); + ViewCompat.postOnAnimation(SwipeItemLayout.this, this); + } + } + + void startFling(int startX, int xVel) { + Log.e("fling - startX", "" + startX); + + if (xVel > mMinVelocity && startX != 0) { + startScroll(startX, 0); + return; + } + + if (xVel < -mMinVelocity && startX != -mMaxScrollOffset) { + startScroll(startX, -mMaxScrollOffset); + return; + } + + startScroll(startX, startX > -mMaxScrollOffset / 2 ? 0 : -mMaxScrollOffset); + } + + void abort() { + if (!mAbort) { + mAbort = true; + if (!mScroller.isFinished()) { + mScroller.abortAnimation(); + removeCallbacks(this); + } + } + } + + //是否正在滑动需要另外判断 + boolean isScrollToLeft() { + return mScrollToLeft; + } + + @Override + public void run() { + Log.e("abort", Boolean.toString(mAbort)); + if (!mAbort) { + boolean more = mScroller.computeScrollOffset(); + int curX = mScroller.getCurrX(); + Log.e("curX", "" + curX); + + boolean atEdge = trackMotionScroll(curX - mScrollOffset); + if (more && !atEdge) { + ViewCompat.postOnAnimation(SwipeItemLayout.this, this); + return; + } + + if (atEdge) { + removeCallbacks(this); + if (!mScroller.isFinished()) + mScroller.abortAnimation(); + setTouchMode(Mode.RESET); + } + + if (!more) { + setTouchMode(Mode.RESET); + //绝对不会出现这种意外的!!!可以注释掉 + if (mScrollOffset != 0) { + if (Math.abs(mScrollOffset) > mMaxScrollOffset / 2) + mScrollOffset = -mMaxScrollOffset; + else + mScrollOffset = 0; + ViewCompat.postOnAnimation(SwipeItemLayout.this, this); + } + } + } + } + } + + public static class OnSwipeItemTouchListener implements RecyclerView.OnItemTouchListener { + private SwipeItemLayout mCaptureItem; + private float mLastMotionX; + private float mLastMotionY; + private VelocityTracker mVelocityTracker; + + private int mActivePointerId; + + private int mTouchSlop; + private int mMaximumVelocity; + + private boolean mDealByParent; + private boolean mIsProbeParent; + + public OnSwipeItemTouchListener(Context context) { + ViewConfiguration configuration = ViewConfiguration.get(context); + mTouchSlop = configuration.getScaledTouchSlop(); + mMaximumVelocity = configuration.getScaledMaximumFlingVelocity(); + mActivePointerId = -1; + mDealByParent = false; + mIsProbeParent = false; + } + + @Override + public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent ev) { + if (mIsProbeParent) + return false; + + boolean intercept = false; + final int action = ev.getActionMasked(); + + if (mVelocityTracker == null) { + mVelocityTracker = VelocityTracker.obtain(); + } + mVelocityTracker.addMovement(ev); + + switch (action) { + case MotionEvent.ACTION_DOWN: { + mActivePointerId = ev.getPointerId(0); + final float x = ev.getX(); + final float y = ev.getY(); + mLastMotionX = x; + mLastMotionY = y; + + boolean pointOther = false; + SwipeItemLayout pointItem = null; + //首先知道ev针对的是哪个item + View pointView = findTopChildUnder(rv, (int) x, (int) y); + if (pointView == null || !(pointView instanceof SwipeItemLayout)) { + //可能是head view或bottom view + pointOther = true; + } else + pointItem = (SwipeItemLayout) pointView; + + //此时的pointOther=true,意味着点击的view为空或者点击的不是item + //还没有把点击的是item但是不是capture item给过滤出来 + if (!pointOther && (mCaptureItem == null || mCaptureItem != pointItem)) + pointOther = true; + + //点击的是capture item + if (!pointOther) { + Mode touchMode = mCaptureItem.getTouchMode(); + + //如果它在fling,就转为drag + //需要拦截,并且requestDisallowInterceptTouchEvent + boolean disallowIntercept = false; + if (touchMode == Mode.FLING) { + mCaptureItem.setTouchMode(Mode.DRAG); + disallowIntercept = true; + intercept = true; + } else {//如果是expand的,就不允许parent拦截 + mCaptureItem.setTouchMode(Mode.TAP); + if (mCaptureItem.isOpen()) + disallowIntercept = true; + } + + if (disallowIntercept) { + final ViewParent parent = rv.getParent(); + if (parent != null) + parent.requestDisallowInterceptTouchEvent(true); + } + } else {//capture item为null或者与point item不一样 + //直接将其close掉 + if (mCaptureItem != null && mCaptureItem.isOpen()) { + mCaptureItem.close(); + mCaptureItem = null; + intercept = true; + } + + if (pointItem != null) { + mCaptureItem = pointItem; + mCaptureItem.setTouchMode(Mode.TAP); + } else + mCaptureItem = null; + } + + //如果parent处于fling状态,此时,parent就会转为drag。此时,应该将后续move都交给parent处理 + mIsProbeParent = true; + mDealByParent = rv.onInterceptTouchEvent(ev); + mIsProbeParent = false; + if (mDealByParent) + intercept = false; + break; + } + + case MotionEvent.ACTION_POINTER_DOWN: { + final int actionIndex = ev.getActionIndex(); + mActivePointerId = ev.getPointerId(actionIndex); + + mLastMotionX = ev.getX(actionIndex); + mLastMotionY = ev.getY(actionIndex); + break; + } + + case MotionEvent.ACTION_POINTER_UP: { + final int actionIndex = ev.getActionIndex(); + final int pointerId = ev.getPointerId(actionIndex); + if (pointerId == mActivePointerId) { + final int newIndex = actionIndex == 0 ? 1 : 0; + mActivePointerId = ev.getPointerId(newIndex); + + mLastMotionX = ev.getX(newIndex); + mLastMotionY = ev.getY(newIndex); + } + break; + } + + //down时,已经将capture item定下来了。所以,后面可以安心考虑event处理 + case MotionEvent.ACTION_MOVE: { + final int activePointerIndex = ev.findPointerIndex(mActivePointerId); + if (activePointerIndex == -1) + break; + + //在down时,就被认定为parent的drag,所以,直接交给parent处理即可 + if (mDealByParent) { + if (mCaptureItem != null && mCaptureItem.isOpen()) + mCaptureItem.close(); + return false; + } + + final int x = (int) (ev.getX(activePointerIndex) + .5f); + final int y = (int) ((int) ev.getY(activePointerIndex) + .5f); + + int deltaX = (int) (x - mLastMotionX); + int deltaY = (int) (y - mLastMotionY); + final int xDiff = Math.abs(deltaX); + final int yDiff = Math.abs(deltaY); + + if (mCaptureItem != null && !mDealByParent) { + Mode touchMode = mCaptureItem.getTouchMode(); + + if (touchMode == Mode.TAP) { + //如果capture item是open的,下拉有两种处理方式: + // 1、下拉后,直接close item + // 2、只要是open的,就拦截所有它的消息,这样如果点击open的,就只能滑动该capture item + //网易邮箱,在open的情况下,下拉直接close + //QQ,在open的情况下,下拉也是close。但是,做的不够好,没有达到该效果。 + if (xDiff > mTouchSlop && xDiff > yDiff) { + mCaptureItem.setTouchMode(Mode.DRAG); + final ViewParent parent = rv.getParent(); + parent.requestDisallowInterceptTouchEvent(true); + + deltaX = deltaX > 0 ? deltaX - mTouchSlop : deltaX + mTouchSlop; + } else {// if(yDiff>mTouchSlop){ + mIsProbeParent = true; + boolean isParentConsume = rv.onInterceptTouchEvent(ev); + mIsProbeParent = false; + if (isParentConsume) { + //表明不是水平滑动,即不判定为SwipeItemLayout的滑动 + //但是,可能是下拉刷新SwipeRefreshLayout或者RecyclerView的滑动 + //一般的下拉判定,都是yDiff>mTouchSlop,所以,此处这么写不会出问题 + //这里这么做以后,如果判定为下拉,就直接close + mDealByParent = true; + mCaptureItem.close(); + } + } + } + + touchMode = mCaptureItem.getTouchMode(); + if (touchMode == Mode.DRAG) { + intercept = true; + mLastMotionX = x; + mLastMotionY = y; + + //对capture item进行拖拽 + mCaptureItem.trackMotionScroll(deltaX); + } + } + break; + } + + case MotionEvent.ACTION_UP: + if (mCaptureItem != null) { + Mode touchMode = mCaptureItem.getTouchMode(); + if (touchMode == Mode.DRAG) { + final VelocityTracker velocityTracker = mVelocityTracker; + velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity); + int xVel = (int) velocityTracker.getXVelocity(mActivePointerId); + mCaptureItem.fling(xVel); + + intercept = true; + } + } + cancel(); + break; + + case MotionEvent.ACTION_CANCEL: + if (mCaptureItem != null) + mCaptureItem.revise(); + cancel(); + break; + } + + return intercept; + } + + @Override + public void onTouchEvent(RecyclerView rv, MotionEvent ev) { + final int action = ev.getActionMasked(); + final int actionIndex = ev.getActionIndex(); + + if (mVelocityTracker == null) { + mVelocityTracker = VelocityTracker.obtain(); + } + mVelocityTracker.addMovement(ev); + + switch (action) { + case MotionEvent.ACTION_POINTER_DOWN: + mActivePointerId = ev.getPointerId(actionIndex); + + mLastMotionX = ev.getX(actionIndex); + mLastMotionY = ev.getY(actionIndex); + break; + + case MotionEvent.ACTION_POINTER_UP: + final int pointerId = ev.getPointerId(actionIndex); + if (pointerId == mActivePointerId) { + final int newIndex = actionIndex == 0 ? 1 : 0; + mActivePointerId = ev.getPointerId(newIndex); + + mLastMotionX = ev.getX(newIndex); + mLastMotionY = ev.getY(newIndex); + } + break; + + //down时,已经将capture item定下来了。所以,后面可以安心考虑event处理 + case MotionEvent.ACTION_MOVE: { + final int activePointerIndex = ev.findPointerIndex(mActivePointerId); + if (activePointerIndex == -1) + break; + + final float x = ev.getX(activePointerIndex); + final float y = (int) ev.getY(activePointerIndex); + + int deltaX = (int) (x - mLastMotionX); + + if (mCaptureItem != null && mCaptureItem.getTouchMode() == Mode.DRAG) { + mLastMotionX = x; + mLastMotionY = y; + + //对capture item进行拖拽 + mCaptureItem.trackMotionScroll(deltaX); + } + break; + } + + case MotionEvent.ACTION_UP: + if (mCaptureItem != null) { + Mode touchMode = mCaptureItem.getTouchMode(); + if (touchMode == Mode.DRAG) { + final VelocityTracker velocityTracker = mVelocityTracker; + velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity); + int xVel = (int) velocityTracker.getXVelocity(mActivePointerId); + mCaptureItem.fling(xVel); + } + } + cancel(); + break; + + case MotionEvent.ACTION_CANCEL: + if (mCaptureItem != null) + mCaptureItem.revise(); + + cancel(); + break; + + } + } + + @Override + public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) { + } + + void cancel() { + mDealByParent = false; + mActivePointerId = -1; + if (mVelocityTracker != null) { + mVelocityTracker.recycle(); + mVelocityTracker = null; + } + } + + } + + static View findTopChildUnder(ViewGroup parent, int x, int y) { + final int childCount = parent.getChildCount(); + for (int i = childCount - 1; i >= 0; i--) { + final View child = parent.getChildAt(i); + if (x >= child.getLeft() && x < child.getRight() + && y >= child.getTop() && y < child.getBottom()) { + return child; + } + } + return null; + } + + public static void closeAllItems(RecyclerView recyclerView) { + for (int i = 0; i < recyclerView.getChildCount(); i++) { + View child = recyclerView.getChildAt(i); + if (child instanceof SwipeItemLayout) { + SwipeItemLayout swipeItemLayout = (SwipeItemLayout) child; + if (swipeItemLayout.isOpen()) + swipeItemLayout.close(); + } + } + } + + +} diff --git a/common_base/src/main/java/com/wss/common/widget/ViewPagerForScrollView.java b/common_base/src/main/java/com/wss/common/widget/ViewPagerForScrollView.java new file mode 100644 index 0000000..56897e5 --- /dev/null +++ b/common_base/src/main/java/com/wss/common/widget/ViewPagerForScrollView.java @@ -0,0 +1,126 @@ +package com.wss.common.widget; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; + +import com.wss.common.utils.PxUtils; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.LinkedHashMap; + +import androidx.viewpager.widget.ViewPager; + +/** + * ViewPager和ScrollView嵌套空白问题 + * + * @author 杨伟 + * create by 2020-4-17 + */ +public class ViewPagerForScrollView extends ViewPager implements Serializable { + + private static final long serialVersionUID = 1L; + + + private int current; + private int height = 0; + /** + * 保存position与对于的View + */ + private HashMap mChildrenViews = new LinkedHashMap<>(); + private boolean scroll = true; + /** + * 最小高度 + */ + private int minHeight; + + public ViewPagerForScrollView(Context context) { + super(context); + } + + public ViewPagerForScrollView(Context context, AttributeSet attrs) { + super(context, attrs); + minHeight = PxUtils.getScreenHeight(context); + } + + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + try { + if (mChildrenViews.size() > current) { + View child = mChildrenViews.get(current); + if (child != null) { + child.measure(widthMeasureSpec, View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)); + height = child.getMeasuredHeight(); + //如果计算出ViewPager的高度小于最小高度,则使用最小高度作为ViewPager高度 + if (height < minHeight) { + height = minHeight; + } + } + } + heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY); + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * 重置ViewPager的高度 + * + * @param current 第几页的 + */ + public void resetHeight(int current) { + this.current = current; + if (mChildrenViews.size() > current) { + ViewGroup.LayoutParams layoutParams = getLayoutParams(); + if (layoutParams == null) { + layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, height); + } else { + layoutParams.height = height; + } + + setLayoutParams(layoutParams); + } + } + + /** + * 保存position与对于的View + */ + public void setObjectForPosition(View view, int position) { + mChildrenViews.put(position, view); + } + + + @SuppressLint("ClickableViewAccessibility") + @Override + public boolean onTouchEvent(MotionEvent ev) { + if (!scroll) { + return true; + } + return super.onTouchEvent(ev); + } + + /** + * 设置ViewPager显示的最小高度 + * + * @param minHeight 最小高度 + */ + public void setMinHeight(int minHeight) { + this.minHeight = minHeight; + } + + /** + * 设置是否可滚动 + * + * @param scroll 滚动 + */ + public void setScroll(boolean scroll) { + this.scroll = scroll; + } + +} \ No newline at end of file diff --git a/common_base/src/main/java/com/wss/common/widget/WebViewProgressBar.java b/common_base/src/main/java/com/wss/common/widget/WebViewProgressBar.java deleted file mode 100644 index f9e53c7..0000000 --- a/common_base/src/main/java/com/wss/common/widget/WebViewProgressBar.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.wss.common.widget; - -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.util.AttributeSet; -import android.view.View; - -import com.wss.common.base.R; - - -/** - * WebView进度条 - * Created by wtq on 2016/12/15. - */ -public class WebViewProgressBar extends View { - private int progress = 1; - private final static int HEIGHT = 5; - private Paint paint; - private final static int colors[] = new int[]{}; - - public WebViewProgressBar(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public WebViewProgressBar(Context context) { - super(context); - paint = new Paint(Paint.DITHER_FLAG); - paint.setStyle(Paint.Style.STROKE); - paint.setStrokeWidth(HEIGHT); - paint.setAntiAlias(true); - paint.setColor(context.getResources().getColor(R.color.theme)); - } - - public void setProgress(int progress) { - this.progress = progress; - invalidate(); - } - - @Override - protected void onDraw(Canvas canvas) { - canvas.drawRect(0, 0, getWidth() * progress / 100, HEIGHT, paint); - } -} \ No newline at end of file diff --git a/common_base/src/main/java/com/wss/common/widget/dialog/AppDialog.java b/common_base/src/main/java/com/wss/common/widget/dialog/AppDialog.java index b6903f0..ccb55ec 100644 --- a/common_base/src/main/java/com/wss/common/widget/dialog/AppDialog.java +++ b/common_base/src/main/java/com/wss/common/widget/dialog/AppDialog.java @@ -2,8 +2,8 @@ import android.app.Dialog; import android.content.Context; -import android.text.Editable; -import android.text.TextUtils; +import android.content.DialogInterface; +import android.graphics.Color; import android.text.TextWatcher; import android.view.Gravity; import android.view.View; @@ -11,7 +11,6 @@ import android.view.WindowManager; import android.widget.Button; import android.widget.EditText; -import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ScrollView; import android.widget.TextView; @@ -20,14 +19,19 @@ import com.wss.common.base.R2; import com.wss.common.utils.KeyboardUtils; import com.wss.common.utils.PxUtils; -import com.wss.common.widget.CountClickView; +import com.wss.common.utils.ValidUtils; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; import java.util.List; +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; import butterknife.BindView; import butterknife.ButterKnife; import butterknife.OnClick; - +import butterknife.Unbinder; /** * Describe:自定义对话框 @@ -35,78 +39,105 @@ */ public class AppDialog { + private static final int MAX_ITEM = 7; + /** + * 对话框的顶级父类 + */ @BindView(R2.id.dialog_layout) - LinearLayout dialogLayout;//对话框的顶级父类 + LinearLayout dialogLayout; + /** + * 中间显示的Dialog 父View + */ @BindView(R2.id.ll_center) - LinearLayout llCenter;//中间显示的Dialog 父View + LinearLayout llCenter; @BindView(R2.id.tv_title) TextView tvTitle; @BindView(R2.id.tv_content) TextView tvContent; @BindView(R2.id.edt_input) EditText edtInput; - @BindView(R2.id.iv_minus) - ImageView ivMinus; - @BindView(R2.id.edt_count) - EditText edtCount; - @BindView(R2.id.iv_plus) - ImageView ivPlus; - @BindView(R2.id.ll_count_view) - LinearLayout llCountView; + @BindView(R2.id.btn_left) Button btnLeft; @BindView(R2.id.btn_right) Button btnRight; @BindView(R2.id.btn_line) View btnLine; - @BindView(R2.id.ll_content_layout) - LinearLayout contentLayout;//中间弹出对话框的View + /** + * 中间弹出对话框的Content View + */ + @BindView(R2.id.ll_content_layout) + LinearLayout contentLayout; + @BindView(R2.id.center_scroll_view) + ScrollView centerScrollView; + /** + * 底部弹出的Dialog 父View + */ @BindView(R2.id.ll_bottom) - LinearLayout llBottom;//底部弹出的Dialog 父View - @BindView(R2.id.tv_bottom_title) - TextView tvBottomTitle; + LinearLayout llBottom; @BindView(R2.id.ll_context) LinearLayout llContext; - @BindView(R2.id.sLayout_content) - ScrollView sLayoutContent; + @BindView(R2.id.bottom_scroll_view) + ScrollView bottomScrollView; @BindView(R2.id.tv_cancel) TextView tvCancel; - @DialogType.Type - private int type; - private int maxCount = CountClickView.MAX_COUNT; - private int minCount = CountClickView.MIN_COUNT; private Dialog dialog; - private Context mContext; + private Unbinder butterKnifeBinder; + private Builder builder; - private OnButtonClickListener leftListener; - private OnButtonClickListener rightListener; - private OnItemClickListener itemClickListener; - private String title;//标题 + private AppDialog() { + + } + + private AppDialog(Builder builder) { + this.builder = builder; + } - public AppDialog(Context context) { - this(context, DialogType.DEFAULT); + /** + * 显示对话框 + */ + public void show() { + initView(); + dialog.show(); + } + + public boolean isShowing() { + return dialog != null && dialog.isShowing(); + } + + /** + * 关闭对话框 + */ + public void dismiss() { + if (dialog != null) { + dialog.dismiss(); + } + if (butterKnifeBinder != null) { + butterKnifeBinder.unbind(); + } } - public AppDialog(Context context, @DialogType.Type int type) { - this.mContext = context; - this.type = type; - View dialogView = View.inflate(mContext, R.layout.dialog_app, null); - ButterKnife.bind(this, dialogView); + /** + * 初始化View + */ + private void initView() { + View dialogView = View.inflate(builder.context, R.layout.dialog_app, null); + butterKnifeBinder = ButterKnife.bind(this, dialogView); int themeResId = R.style.DialogStyle; - if (type == DialogType.BOTTOM_IN) { + if (builder.type == DialogType.BOTTOM_IN) { themeResId = R.style.ActionSheetDialogStyle; - dialogView.setMinimumWidth(PxUtils.getScreenWidth(mContext)); + dialogView.setMinimumWidth(PxUtils.getScreenWidth(builder.context)); } - dialog = new Dialog(mContext, themeResId); + dialog = new Dialog(builder.context, themeResId); dialog.setContentView(dialogView); Window window = dialog.getWindow(); if (window != null) { - if (type == DialogType.BOTTOM_IN) { + if (builder.type == DialogType.BOTTOM_IN) { window.getAttributes().gravity = Gravity.BOTTOM; WindowManager.LayoutParams lp = window.getAttributes(); lp.x = 0; @@ -116,499 +147,810 @@ public AppDialog(Context context, @DialogType.Type int type) { window.getAttributes().gravity = Gravity.CENTER; } } - dialog.setCanceledOnTouchOutside(false); - } - - private void initView() { - switch (type) { - case DialogType.DEFAULT: - setTitleText(); - break; + dialog.setCanceledOnTouchOutside(builder.canceledOnTouchOutside); + dialog.setCancelable(builder.cancelable); + dialog.setOnDismissListener(builder.dialogDismissListener); + switch (builder.type) { case DialogType.INPUT: - setTitleText(); - edtInput.setVisibility(View.VISIBLE); - tvContent.setVisibility(View.GONE); - llCountView.setVisibility(View.GONE); - dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE); - break; - case DialogType.COUNT: - setTitleText(); - edtInput.setVisibility(View.GONE); - tvContent.setVisibility(View.GONE); - llCountView.setVisibility(View.VISIBLE); - dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE); + //带文本框输入 + setInputSetting(); break; case DialogType.NO_TITLE: tvTitle.setVisibility(View.GONE); + setCommonSetting(); break; case DialogType.BOTTOM_IN: //底部弹出对话框 - tvBottomTitle.setText(title); - llCenter.setVisibility(View.GONE); + setBottomSetting(); + break; + case DialogType.REPLACE_ALL: + //替换全部View + dialogLayout.removeAllViews(); + dialogLayout.addView(builder.allDialogView); + break; + case DialogType.REPLACE_CONTENT: + //替换Content View + contentLayout.removeAllViews(); + contentLayout.addView(builder.contentView); + break; + case DialogType.REPLACE_BOTTOM: + //替换底部View llBottom.setVisibility(View.VISIBLE); + llBottom.removeAllViews(); + llBottom.addView(builder.bottomView); break; + case DialogType.DEFAULT: + //默认对话框 default: + setCommonSetting(); break; } } - private void setTitleText() { - if (!TextUtils.isEmpty(title)) { - tvTitle.setText(title); - } - } - - - /** - * 设置Title - */ - public AppDialog setTitle(String title) { - this.title = title; - return this; - } /** - * 设置显示内容 + * 常规对话框相关设置 */ - public AppDialog setContent(String content) { - tvContent.setText(content); - return this; + private void setCommonSetting() { + llCenter.setVisibility(View.VISIBLE); + tvContent.setTextSize(builder.contentTextSize); + btnLeft.setTextSize(builder.leftButtonTextSize); + btnRight.setTextSize(builder.rightButtonTextSize); + tvContent.setTextColor(builder.contentTextColor); + btnLeft.setTextColor(builder.leftButtonTextColor); + btnRight.setTextColor(builder.rightButtonTextColor); + if (ValidUtils.isValid(builder.title)) { + tvTitle.setText(builder.title); + } + if (ValidUtils.isValid(builder.letButtonText)) { + btnLeft.setText(builder.letButtonText); + } + if (ValidUtils.isValid(builder.rightButtonText)) { + btnRight.setText(builder.rightButtonText); + } + tvContent.setText(builder.content); + centerScrollView.post(() -> { + int height = centerScrollView.getHeight(); + int max = PxUtils.getScreenHeight(builder.context) * 3 / 5; + if (height > max) { + LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) bottomScrollView.getLayoutParams(); + params.height = max; + centerScrollView.setLayoutParams(params); + } + }); + if (builder.isSingleButton) { + //单按钮 + btnLeft.setVisibility(View.GONE); + btnLine.setVisibility(View.GONE); + btnRight.setBackgroundResource(R.drawable.corners_white_gray_selecter); + } } /** - * 加减输入模式下 设置的数字 - * - * @param minCount minCount - * @param maxCount maxCount - * @param current current + * 文本框输入类型相关设置 */ - public AppDialog setNumber(int minCount, int maxCount, int current) { - this.minCount = minCount; - this.maxCount = maxCount; - edtCount.setText(String.valueOf(current)); - edtCount.setSelection(edtCount.getText().length()); - edtCount.addTextChangedListener(textWatcher); - judgeTheViews(current); - return this; + private void setInputSetting() { + setCommonSetting(); + edtInput.setVisibility(View.VISIBLE); + tvContent.setVisibility(View.GONE); + if (dialog.getWindow() != null) { + dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE); + } + edtInput.setTextSize(builder.inputTextSize); + edtInput.setTextColor(builder.inputTextColor); + edtInput.setHintTextColor(builder.inputHintTextColor); + if (builder.textWatcher != null) { + edtInput.addTextChangedListener(builder.textWatcher); + } + if (ValidUtils.isValid(builder.inputHintText)) { + edtInput.setHint(builder.inputHintText); + } + if (ValidUtils.isValid(builder.inputDefaultText)) { + edtInput.setText(builder.inputDefaultText); + edtInput.setSelection(builder.inputDefaultText.length()); + } } /** - * 显示对话框 + * 底部弹出类型相关设置 */ - public void show() { - initView(); - dialog.show(); + private void setBottomSetting() { + llBottom.setVisibility(View.VISIBLE); + tvCancel.setTextSize(builder.bottomCancelTextSize); + tvCancel.setTextColor(builder.bottomCancelTextColor); + if (ValidUtils.isValid(builder.bottomTitleText)) { + tvCancel.setText(builder.bottomCancelText); + } + int size = ValidUtils.isValid(builder.bottomItems) ? builder.bottomItems.size() : 0; + setItemScrollViewHeight(size); + llContext.removeAllViews(); + for (int i = 0; i < size; i++) { + View v = View.inflate(builder.context, R.layout.layout_item_of_dialog_bottom_in, null); + TextView item = v.findViewById(R.id.tv_text); + item.setText(builder.bottomItems.get(i)); + item.setTag(i); + item.setTextColor(builder.bottomItemTextColor); + item.setTextSize(builder.bottomItemTextSize); + item.setOnClickListener(v1 -> { + if (builder.itemClickListener != null) { + builder.itemClickListener.onItemClick((int) v1.getTag(), ((TextView) v1).getText().toString()); + } + dismiss(); + }); + llContext.addView(v); + } } - /** - * 关闭对话框 - */ - public void dismiss() { - if (dialog != null) { - dialog.dismiss(); + @OnClick({R2.id.btn_left, R2.id.btn_right, R2.id.tv_cancel}) + public void onClick(@NonNull View v) { + if (v.getId() == R.id.btn_left) { + onButtonClick(builder.letButtonListener); + } else if (v.getId() == R.id.btn_right) { + onButtonClick(builder.rightButtonListener); + } else if (v.getId() == R.id.tv_cancel) { + dismiss(); } } + /** - * 给左边按钮设置文字 事件 + * 给点击事件设置数据 * - * @param text 文字 - * @param listener 事件 - * @return AppDialog + * @param listener listener */ - public AppDialog setLeftButton(String text, OnButtonClickListener listener) { - this.leftListener = listener; - if (!TextUtils.isEmpty(text)) { - btnLeft.setText(text); + private void onButtonClick(OnButtonClickListener listener) { + if (builder.type == DialogType.INPUT) { + if (listener != null) { + listener.onClick(edtInput.getText().toString().trim()); + } + KeyboardUtils.hideKeyboard(edtInput); + } else { + if (listener != null) { + listener.onClick(tvContent.getText().toString()); + } } - return this; + dismiss(); } /** - * 给左边按钮设置文字 事件 + * 设置底部弹出带条目的ScrollView的高度 * - * @param listener 事件 - * @return AppDialog + * @param size 条目数量 */ - public AppDialog setLeftButton(OnButtonClickListener listener) { - return setLeftButton(null, listener); + private void setItemScrollViewHeight(int size) { + // 添加条目过多的时候控制高度 + if (size >= MAX_ITEM) { + LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) bottomScrollView.getLayoutParams(); + params.height = PxUtils.getScreenHeight(builder.context) / 2; + bottomScrollView.setLayoutParams(params); + } } + /** - * 给左边按钮设置文字 事件 + * 相机的Item * - * @param text text - * @return AppDialog - */ - public AppDialog setLeftButton(String text) { - return setLeftButton(text, null); - } + * @param context context + * @return List + */ + @NotNull + public static List getPhotoItem(@NotNull Context context) { + List items = new ArrayList<>(); + items.add(context.getString(R.string.camera)); + items.add(context.getString(R.string.album)); + return items; + } + + /** + * Describe:对话框建造者 + * Created by 吴天强 on 2018年9月27日 + */ + public static class Builder { + Context context; + /** + * 对话框类型 + */ + @DialogType.Type + int type = DialogType.DEFAULT; + /** + * 对话框Title + */ + String title; + /** + * 显示内容文字颜色 + */ + int contentTextColor = Color.BLACK; + /** + * 显示内容文字大小 + */ + float contentTextSize = 16; + /** + * 对话框内容 + */ + String content; + /** + * 左按钮文字 + */ + String letButtonText; + /** + * 右按钮文字 + */ + String rightButtonText; + /** + * 左按钮事件 + */ + OnButtonClickListener letButtonListener; + /** + * 右按钮事件 + */ + OnButtonClickListener rightButtonListener; + + /** + * 左按钮文字颜色 + */ + int leftButtonTextColor = Color.GRAY; + /** + * 右按钮文字颜色 + */ + int rightButtonTextColor = Color.parseColor("#0099FF"); + /** + * 左按钮文字大小 + */ + float leftButtonTextSize = 18; + /** + * 右按钮文字大小 + */ + float rightButtonTextSize = 18; + + /** + * 底部弹出多条目内容 + */ + List bottomItems; + /** + * 底部多条目点击事件 + */ + OnItemClickListener itemClickListener; + /** + * 底部弹出对话框标题文字 + */ + String bottomTitleText; + /** + * 底部弹出对话框取消按钮文字 + */ + String bottomCancelText; + /** + * 底部弹出对话框取消按钮文字颜色 + */ + int bottomCancelTextColor = Color.GRAY; + /** + * 底部弹出对话框Item文字颜色 + */ + int bottomItemTextColor = Color.BLACK; + /** + * 底部弹出对话框取消按钮文字大小 + */ + float bottomCancelTextSize = 18; + /** + * 底部弹出对话框Item文字大小 + */ + float bottomItemTextSize = 16; + + /** + * 输入框默认文字 + */ + String inputDefaultText; + /** + * 输入框hint文字 + */ + String inputHintText; + /** + * 输入框文字颜色 + */ + int inputTextColor = Color.BLACK; + /** + * 输入框Hint文字颜色 + */ + int inputHintTextColor = Color.GRAY; + /** + * 输入框文字大小 + */ + float inputTextSize = 16; + /** + * 输入框输入监听 + */ + TextWatcher textWatcher; + /** + * 替换整个Dialog内容的View + */ + View allDialogView; + /** + * 替换中间部分View + */ + View contentView; + /** + * 替换底部弹出View + */ + View bottomView; + + /** + * 是否单按钮 + */ + boolean isSingleButton; + + /** + * 是否可以取消 + */ + boolean cancelable = true; + + /** + * 点击对话框周围是否可取消 + */ + boolean canceledOnTouchOutside = true; + + /** + * 对话框消失监听 + */ + DialogInterface.OnDismissListener dialogDismissListener; + + /** + * 初始化 + * + * @param context 上下文 + */ + public Builder(Context context) { + this.context = context; + } + /** + * 设置对话框类型 + * + * @param type DialogType + * @return Builder + */ + public Builder setDialogType(@DialogType.Type int type) { + this.type = type; + return this; + } - /** - * 给右边按钮设置文字 事件 - * - * @param text 文字 - * @param listener 事件 - * @return AppDialog - */ - public AppDialog setRightButton(String text, OnButtonClickListener listener) { - this.rightListener = listener; - if (!TextUtils.isEmpty(text)) { - btnRight.setText(text); + /** + * 设置对话框标题 + * + * @param title 标题 + * @return Builder + */ + public Builder setTitle(String title) { + this.title = title; + return this; } - return this; - } - /** - * 给右边按钮设置文字 事件 - * - * @param listener 事件 - * @return AppDialog - */ - public AppDialog setRightButton(OnButtonClickListener listener) { - return setRightButton(null, listener); - } + /** + * 设置对话框内容 + * + * @param content 内容 + * @return Builder + */ + public Builder setContent(String content) { + this.content = content; + return this; + } - /** - * 给右边按钮设置文字 事件 - * - * @param text text - * @return AppDialog - */ - public AppDialog setRightButton(String text) { - return setRightButton(text, null); - } + /** + * 设置显示内容文字颜色 + * + * @param color 颜色 + * @return Builder + */ + public Builder setContentTextColor(@ColorInt int color) { + this.contentTextColor = color; + return this; + } - /** - * 左按钮文字颜色 - * - * @param color color - * @return AppDialog - */ - public AppDialog setLeftButtonTextColor(int color) { - btnLeft.setTextSize(mContext.getResources().getColor(color)); - return this; - } + /** + * 设置显示内容文字大小 + * + * @param contentTextSize 大小 + * @return Builder + */ + public Builder setContentTextSize(float contentTextSize) { + this.contentTextSize = contentTextSize; + return this; + } + ////////////////////////////////////////左按钮设置//////////////////////////////////////////// + + /** + * 设置左按钮 + * + * @param text 显示文字 + * @return Builder + */ + public Builder setLeftButton(String text) { + return setLeftButton(text, null); + } - /** - * 右按钮文字大小 - * - * @param color color - * @return AppDialog - */ - public AppDialog setRightButtonTextColor(int color) { - btnRight.setTextSize(mContext.getResources().getColor(color)); - return this; - } + /** + * 设置左按钮 + * + * @param listener 监听事件 + * @return Builder + */ + public Builder setLeftButton(OnButtonClickListener listener) { + return setLeftButton(null, listener); + } - /** - * 单按钮文字大小 - * - * @param color color - * @return AppDialog - */ - public AppDialog setSingleButtonTextColor(int color) { - return setRightButtonTextColor(color); - } + /** + * 设置左按钮 + * + * @param text 显示文字 + * @param listener 监听事件 + * @return Builder + */ + public Builder setLeftButton(String text, OnButtonClickListener listener) { + this.letButtonText = text; + this.letButtonListener = listener; + return this; + } + /** + * 设置左按钮文字颜色 + * + * @param color 颜色 + * @return Builder + */ + public Builder setLeftButtonTextColor(@ColorInt int color) { + this.leftButtonTextColor = color; + return this; + } - /** - * 单按钮 - * - * @param text text - * @param listener listener - * @return AppDialog - */ - public AppDialog setSingleButton(String text, OnButtonClickListener listener) { - this.rightListener = listener; - if (!TextUtils.isEmpty(text)) { - btnRight.setText(text); - } - btnLeft.setVisibility(View.GONE); - btnLine.setVisibility(View.GONE); - btnRight.setBackgroundResource(R.drawable.corners_white_gray_selecter); - return this; - } + /** + * 设置左按钮文字大小 + * + * @param size 大小 + * @return Builder + */ + public Builder setLeftButtonTextSize(float size) { + this.leftButtonTextSize = size; + return this; + } - /** - * 单按钮 - * - * @param listener listener - * @return AppDialog - */ - public AppDialog setSingleButton(OnButtonClickListener listener) { - return setSingleButton(null, listener); - } + ////////////////////////////////////////右按钮设置//////////////////////////////////////////// - /** - * 单按钮 - * - * @param text listener - * @return AppDialog - */ - public AppDialog setSingleButton(String text) { - return setSingleButton(text, null); - } + /** + * 设置右按钮 + * + * @param text 显示文字 + * @return Builder + */ + public Builder setRightButton(String text) { + return setRightButton(text, null); + } - /** - * 单按钮 - * - * @return AppDialog - */ - public AppDialog setSingleButton() { - return setSingleButton(null, null); - } + /** + * 设置右按钮 + * + * @param listener 监听事件 + * @return Builder + */ + public Builder setRightButton(OnButtonClickListener listener) { + return setRightButton(null, listener); + } - /** - * 设置底部弹出对话框的条目 - * - * @param items 条目名称 - * @param listener listener - * @return AppDialog - */ - public AppDialog setBottomItems(List items, OnItemClickListener listener) { - this.itemClickListener = listener; - setItems(items); - return this; - } + /** + * 设置右按钮 + * + * @param text 显示文字 + * @param listener 监听事件 + * @return Builder + */ + public Builder setRightButton(String text, OnButtonClickListener listener) { + this.rightButtonText = text; + this.rightButtonListener = listener; + return this; + } - /** - * 设置底部弹出对话框的取消文字 - * - * @param text text - * @return AppDialog - */ - public AppDialog setBottomCancelText(String text) { - if (!TextUtils.isEmpty(text)) { - tvCancel.setText(text); + /** + * 设置右按钮文字颜色 + * + * @param color 颜色 + * @return Builder + */ + public Builder setRightButtonTextColor(@ColorInt int color) { + this.rightButtonTextColor = color; + return this; } - return this; - } - /** - * 设置底部弹出对话框的取消文字颜色 - * - * @param color text - * @return AppDialog - */ - public AppDialog setBottomCancelTextColor(int color) { - tvCancel.setTextColor(mContext.getResources().getColor(color)); - return this; - } + /** + * 设置右按钮文字大小 + * + * @param size 大小 + * @return Builder + */ + public Builder setRightButtonTextSize(float size) { + this.rightButtonTextSize = size; + return this; + } + ////////////////////////////////////////单按钮设置//////////////////////////////////////////// + + /** + * 单按钮设置 + * + * @param text 显示文字 + * @return Builder + */ + public Builder setSingleButton(String text) { + return setSingleButton(text, null); + } + /** + * 单按钮设置 + * + * @param listener 事件监听 + * @return Builder + */ + public Builder setSingleButton(OnButtonClickListener listener) { + return setSingleButton(null, listener); + } - /** - * 给整个Dialog添加View - * - * @param view view - * @return AppDialog - */ - public AppDialog addDialogView(View view) { - dialogLayout.removeAllViews(); - dialogLayout.addView(view); - return this; - } + /** + * 单按钮设置 + * + * @param text 显示文字 + * @param listener 事件监听 + * @return Builder + */ + public Builder setSingleButton(String text, OnButtonClickListener listener) { + this.isSingleButton = true; + return setRightButton(text, listener); + } - /** - * 中间弹出对话框添加View - * - * @param view view - * @return AppDialog - */ - public AppDialog addContentView(View view) { - contentLayout.removeAllViews(); - contentLayout.addView(view); - return this; - } + /** + * 设置单按钮文字颜色 + * + * @param color 颜色 + * @return Builder + */ + public Builder setSingleButtonTextColor(@ColorInt int color) { + return setRightButtonTextColor(color); + } - /** - * 底部弹出对话框添加View - * - * @param view view - * @param itemSize 条目数量 - * @return AppDialog - */ - public AppDialog addItemView(View view, int itemSize) { - llContext.removeAllViews(); - llContext.addView(view); - setItemScrollViewHeight(itemSize); - return this; - } + /** + * 设置单按钮文字大小 + * + * @param size 大小 + * @return Builder + */ + public Builder setSingleButtonTextSize(float size) { + return setRightButtonTextSize(size); + } + ////////////////////////////////////////多条目设置//////////////////////////////////////////// + + /** + * 当type = 底部弹出的时候,设置弹出条目及监听 + * + * @param items 弹出条目 + * @param listener 监听事件 + * @return Builder + */ + public Builder setBottomItems(List items, OnItemClickListener listener) { + this.bottomItems = items; + this.itemClickListener = listener; + return this; + } - @OnClick({R2.id.btn_left, R2.id.btn_right, R2.id.minus, R2.id.plus, R2.id.tv_cancel}) - public void onClick(View v) { - if (v.getId() == R.id.btn_left) { - onButtonClick(leftListener); - } else if (v.getId() == R.id.btn_right) { - onButtonClick(rightListener); - } else if (v.getId() == R.id.minus) { - //减少 - int count = getCountEdtValue(); - if (getCountEdtValue() > minCount) { - edtCount.setText(String.valueOf(--count)); - } - judgeTheViews(count); - } else if (v.getId() == R.id.plus) { - //增加 - int count = getCountEdtValue(); - if (count < maxCount) { - edtCount.setText(String.valueOf(++count)); - } - judgeTheViews(count); - } else if (v.getId() == R.id.tv_cancel) { - dismiss(); + /** + * 设置底部弹出对话框取消按钮文字 + * + * @param text 显示文字 + * @return Builder + */ + public Builder setBottomCancelText(String text) { + this.bottomCancelText = text; + return this; } - } - /** - * 加减模式下点击结束结算值 - */ - private void judgeTheViews(int count) { - if (count == minCount) { - ivMinus.setImageResource(R.drawable.input_minus_disabled); - } else { - ivMinus.setImageResource(R.drawable.input_minus_default); + /** + * 设置底部弹出对话框标题文字 + * + * @param text 显示文字 + * @return Builder + */ + public Builder setBottomTitleText(String text) { + this.bottomTitleText = text; + return this; } - if (count == maxCount) { - ivPlus.setImageResource(R.drawable.input_add_disabled); - } else { - ivPlus.setImageResource(R.drawable.input_add_default); + + /** + * 设置底部弹出对话框取消按钮文字颜色 + * + * @param color 颜色 + * @return Builder + */ + public Builder setBottomCancelTextColor(@ColorInt int color) { + this.bottomCancelTextColor = color; + return this; } - } - /** - * 给点击事件设置数据 - * - * @param listener listener - */ - private void onButtonClick(OnButtonClickListener listener) { + /** + * 设置底部弹出对话框Item文字颜色 + * + * @param color 颜色 + * @return Builder + */ + public Builder setBottomItemTextColor(@ColorInt int color) { + this.bottomItemTextColor = color; + return this; + } - if (type == DialogType.COUNT) { - if (getCountEdtValue() >= minCount) { - if (listener != null) { - listener.onClick(String.valueOf(getCountEdtValue())); - } - } - KeyboardUtils.hideKeyboard(edtCount); - } else if (type == DialogType.INPUT) { - if (listener != null) { - listener.onClick(edtInput.getText().toString().trim()); - } - KeyboardUtils.hideKeyboard(edtInput); - } else { - if (listener != null) { - listener.onClick(tvContent.getText().toString()); - } + /** + * 设置底部弹出对话框取消按钮文字大小 + * + * @param size 大小 + * @return Builder + */ + public Builder setBottomCancelTextSize(float size) { + this.bottomCancelTextSize = size; + return this; } - dismiss(); - } - /** - * 底部弹出对话框添加条目 - * - * @param items items - */ - private void setItems(List items) { - if (items != null && items.size() > 0) { - int size = items.size(); - setItemScrollViewHeight(size); - // 循环添加条目 - for (int i = 0; i <= size - 1; i++) { - View v = View.inflate(mContext, R.layout.layout_item_of_dialog_bottom_in, null); - TextView item = v.findViewById(R.id.tv_text); - item.setText(items.get(i)); - item.setTag(i); - item.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - if (itemClickListener != null) { - itemClickListener.onItemClick((int) v.getTag()); - } - dismiss(); - } - }); - llContext.addView(v); - } + /** + * 设置底部弹出对话框item文字大小 + * + * @param size 大小 + * @return Builder + */ + public Builder setBottomItemTextSize(float size) { + this.bottomItemTextSize = size; + return this; } - } - /** - * 设置底部弹出带条目的ScrollView的高度 - * - * @param size 条目数量 - */ - private void setItemScrollViewHeight(int size) { - // 添加条目过多的时候控制高度 - if (size >= 7) { - LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) sLayoutContent.getLayoutParams(); - params.height = PxUtils.getScreenHeight(mContext) / 2; - sLayoutContent.setLayoutParams(params); + ////////////////////////////////////////输入框设置//////////////////////////////////////////// + + /** + * 设置输入框默认文字 + * + * @param text 默认文字 + * @return Builder + */ + public Builder setInputDefaultText(String text) { + this.inputDefaultText = text; + return this; } - } - /** - * 得到 加减模式下 输入框的值 - * - * @return int - */ - private int getCountEdtValue() { - int count = 0; - String text = edtCount.getText().toString().trim(); - if (!TextUtils.isEmpty(text)) { - count = Integer.parseInt(text); + /** + * 设置Hint文字 + * + * @param text Hint 文字 + * @return Builder + */ + public Builder setInputHintText(String text) { + this.inputHintText = text; + return this; } - return count; - } - /** - * 加减模式下输入框的监听 - */ - private TextWatcher textWatcher = new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { + /** + * 设置输入框文字颜色 + * + * @param color 文字颜色 + * @return Builder + */ + public Builder setInputTextColor(@ColorInt int color) { + this.inputTextColor = color; + return this; + } + /** + * 设置输入框Hint文字颜色 + * + * @param color Hint文字颜色 + * @return Builder + */ + public Builder setInputHintTextColor(@ColorInt int color) { + this.inputHintTextColor = color; + return this; } - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { + /** + * 设置输入框文字大小 + * + * @param size 大小 + * @return Builder + */ + public Builder setInputTextSize(float size) { + this.inputTextSize = size; + return this; + } + /** + * 设置输入框输入监听 + * + * @param textWatcher 监听 + * @return Builder + */ + public Builder setTextWatcher(TextWatcher textWatcher) { + this.textWatcher = textWatcher; + return this; + } + ////////////////////////////////////////其他设置//////////////////////////////////////////// + + /** + * 替换整个Dialog 内容 + * + * @param view view + * @return Builder + */ + public Builder addAllDialogView(View view) { + this.allDialogView = view; + this.type = DialogType.REPLACE_ALL; + return this; } - @Override - public void afterTextChanged(Editable s) { - if (!TextUtils.isEmpty(s.toString().trim())) { - edtCount.removeTextChangedListener(textWatcher); - int text = Integer.parseInt(s.toString()); - if (text < minCount) { - edtCount.setText(String.valueOf(minCount)); - } else if (text > maxCount) { - edtCount.setText(String.valueOf(maxCount)); - } - edtCount.setSelection(edtCount.getText().length()); - edtCount.addTextChangedListener(textWatcher); - judgeTheViews(Integer.parseInt(edtCount.getText().toString().trim())); - } else { - //删光了 减 按钮不可点击 - ivMinus.setImageResource(R.drawable.input_minus_disabled); - } + /** + * 替换中间部分View + * + * @param view view + * @return Builder + */ + public Builder addContentView(View view) { + this.contentView = view; + this.type = DialogType.REPLACE_CONTENT; + return this; } - }; - /** - * 按钮被点击事件回调 - */ - public interface OnButtonClickListener { - void onClick(String val); - } + /** + * 替换底部弹出的View + * + * @param view view + * @return Builder + */ + public Builder setBottomView(View view) { + this.bottomView = view; + this.type = DialogType.REPLACE_BOTTOM; + return this; + } - /** - * 底部弹出对话框条目被点击 - */ - public interface OnItemClickListener { - void onItemClick(int position); + /** + * 是否可取消 + * + * @param cancelable 可取消 + * @return Builder + */ + public Builder setCancelable(boolean cancelable) { + this.cancelable = cancelable; + return this; + } + + /** + * 点击对话框周围是否可取消 + * + * @param canceledOnTouchOutside 可取消 + * @return Builder + */ + public Builder setCanceledOnTouchOutside(boolean canceledOnTouchOutside) { + this.canceledOnTouchOutside = canceledOnTouchOutside; + return this; + } + + /** + * 对话框消失监听 + * + * @param dialogDismissListener 监听 + * @return Builder + */ + public Builder setDialogDismissListener(DialogInterface.OnDismissListener dialogDismissListener) { + this.dialogDismissListener = dialogDismissListener; + return this; + } + + /** + * 创建对话框 + * + * @return AppDialog + */ + public AppDialog create() { + return new AppDialog(this); + } } + } \ No newline at end of file diff --git a/common_base/src/main/java/com/wss/common/widget/dialog/DateDialog.java b/common_base/src/main/java/com/wss/common/widget/dialog/DateDialog.java new file mode 100644 index 0000000..4587935 --- /dev/null +++ b/common_base/src/main/java/com/wss/common/widget/dialog/DateDialog.java @@ -0,0 +1,261 @@ +package com.wss.common.widget.dialog; + +import android.annotation.SuppressLint; +import android.app.Dialog; +import android.content.Context; +import android.view.Gravity; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; + +import com.bigkoo.pickerview.adapter.ArrayWheelAdapter; +import com.contrarywind.view.WheelView; +import com.wss.common.base.R; +import com.wss.common.base.R2; +import com.wss.common.utils.DateUtils; +import com.wss.common.utils.PxUtils; +import com.wss.common.utils.ValidUtils; + +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; + +import butterknife.BindView; +import butterknife.ButterKnife; +import butterknife.OnClick; + + +/** + * Describe:自定义选择日期对话框,适用于在PopupWindow之上弹出 + * Created by 吴天强 on 2019年7月27日18:13:09 + */ +@SuppressLint("DefaultLocale") +public class DateDialog { + + + private static final int DEFAULT_START_YEAR = 1900; + private static final int DEFAULT_END_YEAR = 2100; + + + @BindView(R2.id.wv_year) + WheelView wvYear; + + @BindView(R2.id.wv_month) + WheelView wvMonth; + + @BindView(R2.id.wv_day) + WheelView wvDay; + + private Dialog dialog; + private int startYear = DEFAULT_START_YEAR; + private int endYear = DEFAULT_END_YEAR; + private List yearList = new ArrayList<>(); + private List monthList = new ArrayList<>(); + private List dayList = new ArrayList<>(); + /** + * 当前年份下标 + */ + private int yearPosition = 0; + /** + * 当前月份下标 + */ + private int monthPosition = 0; + /** + * 当前日下标 + */ + private int dayPosition = 0; + /** + * 默认显示的日期 yyyy-MM-dd + */ + private String defaultDate = DateUtils.getCurrentDateStr(); + private OnDateSelectListener dateSelectListener; + /** + * 切换过日期 + */ + private boolean changeDay = false; + + public DateDialog(Context context) { + View dialogView = View.inflate(context, R.layout.dailog_date, null); + ButterKnife.bind(this, dialogView); + //底部弹出对话框 + dialog = new Dialog(context, R.style.ActionSheetDialogStyle); + dialogView.setMinimumWidth(PxUtils.getScreenWidth(context)); + dialog.setContentView(dialogView); + Window window = dialog.getWindow(); + if (window != null) { + window.getAttributes().gravity = Gravity.BOTTOM; + WindowManager.LayoutParams lp = window.getAttributes(); + lp.x = 0; + lp.y = 0; + window.setAttributes(lp); + } + } + + /** + * 日期选择回调 + */ + public DateDialog setOnDateSelectListener(OnDateSelectListener dateSelectListener) { + this.dateSelectListener = dateSelectListener; + return this; + } + + /** + * 设置开始 结束年份 + */ + public DateDialog setYearStartEnd(int startYear, int endYear) { + this.startYear = startYear; + this.endYear = endYear; + return this; + } + + /** + * 设置当前日期 格式yyyy-MM-dd + */ + public DateDialog setCurrentDate(String date) { + if (ValidUtils.isValid(date)) { + this.defaultDate = date; + } + return this; + } + + private void initView() { + initData(); + //设置"年"的显示数据 + wvYear.setAdapter(new ArrayWheelAdapter<>(yearList)); + // 初始化时显示的数据 + wvYear.setCurrentItem(yearPosition); + wvYear.setOnItemSelectedListener(index -> { + yearPosition = index; + initDayDate(); + }); + wvMonth.setAdapter(new ArrayWheelAdapter<>(monthList)); + wvMonth.setCurrentItem(monthPosition); + wvMonth.setOnItemSelectedListener(index -> { + monthPosition = index; + initDayDate(); + }); + initDayDate(); + } + + /** + * 初始化年份 月份数据 + */ + private void initData() { + yearList.clear(); + monthList.clear(); + String year = DateUtils.getFormatDate(defaultDate, "yyyy"); + String month = DateUtils.getFormatDate(defaultDate, "MM"); + int yearIndex = 0; + for (int i = startYear; i < endYear + 1; i++) { + yearList.add(String.format("%s年", i)); + if (i == Integer.parseInt(year)) { + yearPosition = yearIndex; + } + yearIndex++; + } + for (int i = 1; i < 12 + 1; i++) { + monthList.add(String.format("%02d月", i)); + if (i == Integer.parseInt(month)) { + monthPosition = i - 1; + } + } + } + + /** + * 初始化日数据 + */ + private void initDayDate() { + dayList.clear(); + int maxDay = 31; + String monthString = monthList.get(monthPosition); + switch (Integer.parseInt(monthString.substring(0, monthString.length() - 1))) { + case 2: + String yearString = yearList.get(yearPosition); + int year = Integer.parseInt(yearString.substring(0, yearString.length() - 1)); + maxDay = isLeapYear(year) ? 28 : 29; + break; + case 4: + case 5: + case 6: + case 8: + case 9: + case 11: + maxDay = 30; + break; + default: + break; + } + String day = DateUtils.getFormatDate(defaultDate, "dd"); + for (int i = 1; i < maxDay + 1; i++) { + dayList.add(String.format("%02d日", i)); + if (!changeDay && i == Integer.parseInt(day)) { + dayPosition = i - 1; + } + } + wvDay.setAdapter(new ArrayWheelAdapter<>(dayList)); + wvDay.setCurrentItem(dayPosition); + wvDay.setOnItemSelectedListener(index -> { + changeDay = true; + dayPosition = index; + }); + } + + /** + * 是否闰年 + * + * @param year 年份 + * @return boolean + */ + @Contract(pure = true) + private boolean isLeapYear(int year) { + return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0; + } + + private boolean isShowing() { + return dialog != null && dialog.isShowing(); + } + + /** + * 显示对话框 + */ + public void show() { + if (!isShowing()) { + initView(); + dialog.show(); + } + } + + + @OnClick({R2.id.btnCancel, R2.id.btnSubmit}) + public void onViewClicked(@NotNull View view) { + if (view.getId() == R.id.btnSubmit) { + if (dateSelectListener != null) { + String yearString = yearList.get(yearPosition); + String monthString = monthList.get(monthPosition); + String dayString = dayList.get(dayPosition); + dateSelectListener.selectDate( + yearString.substring(0, yearString.length() - 1), + monthString.substring(0, monthString.length() - 1), + dayString.substring(0, dayString.length() - 1)); + } + + } + dialog.dismiss(); + } + + /** + * 日期选择监听器 + */ + public interface OnDateSelectListener { + /** + * 日期选择了 + * + * @param year 年 + * @param month 月 + * @param day 日 + */ + void selectDate(String year, String month, String day); + } +} \ No newline at end of file diff --git a/common_base/src/main/java/com/wss/common/widget/dialog/DialogType.java b/common_base/src/main/java/com/wss/common/widget/dialog/DialogType.java index 05bbb0b..cd8de09 100644 --- a/common_base/src/main/java/com/wss/common/widget/dialog/DialogType.java +++ b/common_base/src/main/java/com/wss/common/widget/dialog/DialogType.java @@ -1,25 +1,48 @@ package com.wss.common.widget.dialog; -import android.support.annotation.IntDef; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import androidx.annotation.IntDef; + /** * Describe:对话框类型 * Created by 吴天强 on 2018/10/26. */ - public interface DialogType { - @IntDef({DEFAULT, INPUT, COUNT, NO_TITLE, BOTTOM_IN}) + @IntDef({DEFAULT, NO_TITLE, INPUT, BOTTOM_IN, REPLACE_ALL, REPLACE_CONTENT, REPLACE_BOTTOM}) @Retention(RetentionPolicy.SOURCE) @interface Type { } + /** + * 常规 + */ int DEFAULT = 0; - int INPUT = 1; - int COUNT = 2; - int NO_TITLE = 3; - int BOTTOM_IN = 4; + /** + * 没有Title + */ + int NO_TITLE = 1; + /** + * 带输入框 + */ + int INPUT = 2; + /** + * 底部进来 + */ + int BOTTOM_IN = 3; + /** + * 替换全部 + */ + int REPLACE_ALL = 4; + /** + * 替换content + */ + int REPLACE_CONTENT = 5; + /** + * 替换底部弹出 + */ + int REPLACE_BOTTOM = 6; } diff --git a/common_base/src/main/java/com/wss/common/widget/dialog/LoadingDialog.java b/common_base/src/main/java/com/wss/common/widget/dialog/LoadingDialog.java index f29a77b..0ed0be5 100644 --- a/common_base/src/main/java/com/wss/common/widget/dialog/LoadingDialog.java +++ b/common_base/src/main/java/com/wss/common/widget/dialog/LoadingDialog.java @@ -11,7 +11,7 @@ /** - * 等待对话框 + * 加载框 * Created by wtq on 2016/3/14. */ public class LoadingDialog { @@ -19,7 +19,7 @@ public class LoadingDialog { private LVCircularRing mLoadingView; private Dialog mLoadingDialog; private Context context; - private String msg = "加载中···"; + private String msg = "加载中…"; private boolean cancelable = true; private boolean isShow; @@ -29,6 +29,9 @@ public LoadingDialog(Context context) { /** * 设置提示信息 + * + * @param msg 提示信息 + * @return dialog */ public LoadingDialog setTitleText(String msg) { this.msg = msg; @@ -36,7 +39,10 @@ public LoadingDialog setTitleText(String msg) { } /** - * 返回键是否可用 + * 设置dialog是否可以取消 + * + * @param cancelable 是否可取消 + * @return dialog */ public LoadingDialog setCancelable(boolean cancelable) { this.cancelable = cancelable; diff --git a/common_base/src/main/java/com/wss/common/widget/dialog/OnButtonClickListener.java b/common_base/src/main/java/com/wss/common/widget/dialog/OnButtonClickListener.java new file mode 100644 index 0000000..4f30a70 --- /dev/null +++ b/common_base/src/main/java/com/wss/common/widget/dialog/OnButtonClickListener.java @@ -0,0 +1,15 @@ +package com.wss.common.widget.dialog; + +/** + * Describe:对话框按钮被点击事件 + * Created by 吴天强 on 2019/3/31. + */ +public interface OnButtonClickListener { + + /** + * 点击事件 + * + * @param val 值 + */ + void onClick(String val); +} diff --git a/common_base/src/main/java/com/wss/common/widget/dialog/OnItemClickListener.java b/common_base/src/main/java/com/wss/common/widget/dialog/OnItemClickListener.java new file mode 100644 index 0000000..7047091 --- /dev/null +++ b/common_base/src/main/java/com/wss/common/widget/dialog/OnItemClickListener.java @@ -0,0 +1,16 @@ +package com.wss.common.widget.dialog; + +/** + * Describe:多条目对话框Item被点击事件 + * Created by 吴天强 on 2019/3/31. + */ +public interface OnItemClickListener { + + /** + * 点击事件 + * + * @param position position + * @param val 值 + */ + void onItemClick(int position, String val); +} diff --git a/common_base/src/main/java/com/wss/common/widget/manager/ScrollSpeedLinearLayoutManger.java b/common_base/src/main/java/com/wss/common/widget/manager/ScrollSpeedLinearLayoutManger.java new file mode 100644 index 0000000..9dd5957 --- /dev/null +++ b/common_base/src/main/java/com/wss/common/widget/manager/ScrollSpeedLinearLayoutManger.java @@ -0,0 +1,79 @@ +package com.wss.common.widget.manager; + +import android.content.Context; +import android.graphics.PointF; +import android.util.DisplayMetrics; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.LinearSmoothScroller; +import androidx.recyclerview.widget.RecyclerView; + +/** + * Describe:带效果的RecyclerView LinearLayoutManager滚动指定位置 + * Created by 吴天强 on 2019/5/14. + */ +public class ScrollSpeedLinearLayoutManger extends LinearLayoutManager { + + /** + * 滚动速度因子 + */ + private float speed = 0.3f; + + public ScrollSpeedLinearLayoutManger(Context context) { + super(context, VERTICAL, false); + } + + public ScrollSpeedLinearLayoutManger(Context context, int orientation, boolean reverseLayout) { + super(context, orientation, reverseLayout); + } + + /** + * 设置滚动速度因子 越大越快 越小越慢 取值在0.1~1.0之间即可 + * + * @param speed 速度因子 + */ + public ScrollSpeedLinearLayoutManger setSpeed(float speed) { + if (speed < 0 && speed < 1) { + this.speed = speed; + } + return this; + } + + @Override + public void smoothScrollToPosition(@NonNull RecyclerView recyclerView, RecyclerView.State state, int position) { + RecyclerView.SmoothScroller smoothScroller = new CenterSmoothScroller(recyclerView.getContext()); + smoothScroller.setTargetPosition(position); + startSmoothScroll(smoothScroller); + } + + private class CenterSmoothScroller extends LinearSmoothScroller { + + CenterSmoothScroller(Context context) { + super(context); + } + + @Nullable + @Override + public PointF computeScrollVectorForPosition(int targetPosition) { + return ScrollSpeedLinearLayoutManger.this.computeScrollVectorForPosition(targetPosition); + } + + @Override + public int calculateDtToFit(int viewStart, int viewEnd, int boxStart, int boxEnd, int snapPreference) { + return (boxStart + (boxEnd - boxStart) / 2) - (viewStart + (viewEnd - viewStart) / 2); + } + + @Override + protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) { + return speed; + } + + @Override + protected int getVerticalSnapPreference() { + return SNAP_TO_START; + } + } + +} \ No newline at end of file diff --git a/common_base/src/main/java/com/wss/common/widget/pulltorefresh/IRefreshView.java b/common_base/src/main/java/com/wss/common/widget/pulltorefresh/IRefreshView.java deleted file mode 100644 index 5a7367e..0000000 --- a/common_base/src/main/java/com/wss/common/widget/pulltorefresh/IRefreshView.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.wss.common.widget.pulltorefresh; - -import android.view.View; - -/** - * 刷新view - */ -public interface IRefreshView { - - /** - * 开始下拉 - */ - void begin(); - - /** - * 回调的精度,单位为px - * - * @param progress 当前高度 - * @param all 总高度 为默认高度的2倍 - */ - void progress(float progress, float all); - - void finishing(float progress, float all); - - /** - * 下拉完毕 - */ - void loading(); - - /** - * 看不见的状态 - */ - void normal(); - - /** - * 返回当前视图 - */ - View getView(); - - void setType(boolean refresh); - -} diff --git a/common_base/src/main/java/com/wss/common/widget/pulltorefresh/OnPullRefreshListener.java b/common_base/src/main/java/com/wss/common/widget/pulltorefresh/OnPullRefreshListener.java deleted file mode 100644 index 932f21d..0000000 --- a/common_base/src/main/java/com/wss/common/widget/pulltorefresh/OnPullRefreshListener.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.wss.common.widget.pulltorefresh; - - -/** - * 刷新 加载监听 - */ -public interface OnPullRefreshListener { - - - /** - * 刷新 - */ - void onRefresh(); - - /** - * 加载更多 - */ - void onLoadMore(); -} diff --git a/common_base/src/main/java/com/wss/common/widget/pulltorefresh/PullToRefreshLayout.java b/common_base/src/main/java/com/wss/common/widget/pulltorefresh/PullToRefreshLayout.java deleted file mode 100644 index 7f04698..0000000 --- a/common_base/src/main/java/com/wss/common/widget/pulltorefresh/PullToRefreshLayout.java +++ /dev/null @@ -1,578 +0,0 @@ -package com.wss.common.widget.pulltorefresh; - -import android.animation.ValueAnimator; -import android.content.Context; -import android.content.res.TypedArray; -import android.support.v4.view.ViewCompat; -import android.util.AttributeSet; -import android.view.Gravity; -import android.view.LayoutInflater; -import android.view.MotionEvent; -import android.view.View; -import android.view.ViewConfiguration; -import android.view.ViewGroup; -import android.widget.FrameLayout; - -import com.wss.common.base.R; -import com.wss.common.utils.PxUtils; - - -/** - * 下拉刷新 上拉加载更多控件 - */ -public class PullToRefreshLayout extends FrameLayout { - - private IRefreshView mHeaderView; - private IRefreshView mFooterView; - private View mChildView; - - private static final long ANIM_TIME = 300; - private static int HEAD_HEIGHT = 60; - private static int FOOT_HEIGHT = 60; - - private static int head_height; - private static int head_height_2; - private static int foot_height; - private static int foot_height_2; - - private float mTouchY; - private float mCurrentY; - - private boolean canLoadMore = true; - private boolean canRefresh = true; - private boolean isRefresh; - private boolean isLoadMore; - - //滑动的最小距离 - private int mTouchSlope; - - private OnPullRefreshListener refreshListener; - - - private View loadingView, errorView, emptyView; - private int loading = R.layout.layout_loading, empty = R.layout.layout_empty, error = R.layout.layout_error; - - public void setOnPullRefreshListener(OnPullRefreshListener refreshListener) { - this.refreshListener = refreshListener; - } - - public PullToRefreshLayout(Context context) { - this(context, null); - } - - public PullToRefreshLayout(Context context, AttributeSet attrs) { - this(context, attrs, 0); - } - - public PullToRefreshLayout(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - - TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PullToRefreshLayout, defStyleAttr, 0); - error = a.getResourceId(R.styleable.PullToRefreshLayout_view_error, error); - loading = a.getResourceId(R.styleable.PullToRefreshLayout_view_loading, loading); - empty = a.getResourceId(R.styleable.PullToRefreshLayout_view_empty, empty); - a.recycle(); - init(); - } - - private void init() { - head_height = PxUtils.dp2px(getContext(), HEAD_HEIGHT); - foot_height = PxUtils.dp2px(getContext(), FOOT_HEIGHT); - head_height_2 = PxUtils.dp2px(getContext(), HEAD_HEIGHT * 2); - foot_height_2 = PxUtils.dp2px(getContext(), FOOT_HEIGHT * 2); - - mTouchSlope = ViewConfiguration.get(getContext()).getScaledTouchSlop(); - } - - @Override - protected void onFinishInflate() { - super.onFinishInflate(); - mChildView = getChildAt(0); - addHeadView(); - addFooterView(); - } - - @Override - protected void onAttachedToWindow() { - super.onAttachedToWindow(); - - } - - private void addHeadView() { - if (mHeaderView == null) { - mHeaderView = new RefreshView(getContext()); - mHeaderView.setType(true); - } else { - removeView(mHeaderView.getView()); - } - LayoutParams layoutParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0); - mHeaderView.getView().setLayoutParams(layoutParams); - if (mHeaderView.getView().getParent() != null) - ((ViewGroup) mHeaderView.getView().getParent()).removeAllViews(); - addView(mHeaderView.getView(), 0); - } - - private void addFooterView() { - if (mFooterView == null) { - mFooterView = new RefreshView(getContext()); - mFooterView.setType(false); - } else { - removeView(mFooterView.getView()); - } - LayoutParams layoutParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0); - layoutParams.gravity = Gravity.BOTTOM; - mFooterView.getView().setLayoutParams(layoutParams); - if (mFooterView.getView().getParent() != null) - ((ViewGroup) mFooterView.getView().getParent()).removeAllViews(); - addView(mFooterView.getView()); - } - - @Override - public boolean onInterceptTouchEvent(MotionEvent ev) { - if (!canLoadMore && !canRefresh) return super.onInterceptTouchEvent(ev); - switch (ev.getAction()) { - case MotionEvent.ACTION_DOWN: - mTouchY = ev.getY(); - mCurrentY = mTouchY; - break; - case MotionEvent.ACTION_MOVE: - float currentY = ev.getY(); - float dy = currentY - mCurrentY; - if (canRefresh) { - boolean canChildScrollUp = canChildScrollUp(); - if (dy > mTouchSlope && !canChildScrollUp) { - mHeaderView.begin(); - return true; - } - } - if (canLoadMore) { - boolean canChildScrollDown = canChildScrollDown(); - if (dy < -mTouchSlope && !canChildScrollDown) { - mFooterView.begin(); - return true; - } - } - } - return super.onInterceptTouchEvent(ev); - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - if (isRefresh || isLoadMore) return true; - switch (event.getAction()) { - case MotionEvent.ACTION_MOVE: - mCurrentY = event.getY(); - float dura = (mCurrentY - mTouchY) / 3.0f; - if (dura > 0 && canRefresh) { - dura = Math.min(head_height_2, dura); - dura = Math.max(0, dura); - mHeaderView.getView().getLayoutParams().height = (int) dura; - ViewCompat.setTranslationY(mChildView, dura); - requestLayout(); - mHeaderView.progress(dura, head_height); - } else { - if (canLoadMore) { - dura = Math.min(foot_height_2, Math.abs(dura)); - dura = Math.max(0, Math.abs(dura)); - mFooterView.getView().getLayoutParams().height = (int) dura; - ViewCompat.setTranslationY(mChildView, -dura); - requestLayout(); - mFooterView.progress(dura, foot_height); - } - } - return true; - case MotionEvent.ACTION_UP: - case MotionEvent.ACTION_CANCEL: - float currentY = event.getY(); - final int dy1 = (int) (currentY - mTouchY) / 3; - if (dy1 > 0 && canRefresh) { - if (dy1 >= head_height) { - createAnimatorTranslationY(State.REFRESH, - dy1 > head_height_2 ? head_height_2 : dy1, head_height, - new CallBack() { - @Override - public void onSuccess() { - isRefresh = true; - if (refreshListener != null) { - refreshListener.onRefresh(); - } - mHeaderView.loading(); - } - }); - } else if (dy1 > 0 && dy1 < head_height) { - setFinish(dy1, State.REFRESH); - mHeaderView.normal(); - } - } else { - if (canLoadMore) { - if (Math.abs(dy1) >= foot_height) { - createAnimatorTranslationY(State.LOAD_MORE, Math.abs(dy1) > foot_height_2 ? foot_height_2 : Math.abs(dy1), foot_height, new CallBack() { - @Override - public void onSuccess() { - isLoadMore = true; - if (refreshListener != null) { - refreshListener.onLoadMore(); - } - mFooterView.loading(); - } - }); - } else { - setFinish(Math.abs(dy1), State.LOAD_MORE); - mFooterView.normal(); - } - } - } - break; - } - return super.onTouchEvent(event); - } - - private boolean canChildScrollDown() { - return mChildView != null && ViewCompat.canScrollVertically(mChildView, 1); - } - - private boolean canChildScrollUp() { - return mChildView != null && ViewCompat.canScrollVertically(mChildView, -1); - } - - /** - * 创建动画 - */ - public void createAnimatorTranslationY(@State.REFRESH_STATE final int state, final int start, - final int purpose, final CallBack callBack) { - final ValueAnimator anim; - anim = ValueAnimator.ofInt(start, purpose); - anim.setDuration(ANIM_TIME); - anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { - @Override - public void onAnimationUpdate(ValueAnimator valueAnimator) { - int value = (int) valueAnimator.getAnimatedValue(); - if (state == State.REFRESH) { - mHeaderView.getView().getLayoutParams().height = value; - ViewCompat.setTranslationY(mChildView, value); - if (purpose == 0) { //代表结束加载 - mHeaderView.finishing(value, head_height_2); - } else { - mHeaderView.progress(value, head_height); - } - } else { - mFooterView.getView().getLayoutParams().height = value; - ViewCompat.setTranslationY(mChildView, -value); - if (purpose == 0) { //代表结束加载 - mFooterView.finishing(value, head_height_2); - } else { - mFooterView.progress(value, foot_height); - } - } - if (value == purpose) { - if (callBack != null) - callBack.onSuccess(); - } - requestLayout(); - - - } - - }); - anim.start(); - } - - /** - * 结束下拉刷新 - */ - private void setFinish(int height, @State.REFRESH_STATE final int state) { - createAnimatorTranslationY(state, height, 0, new CallBack() { - @Override - public void onSuccess() { - if (state == State.REFRESH) { - isRefresh = false; - mHeaderView.normal(); - - } else { - isLoadMore = false; - mFooterView.normal(); - } - } - }); - } - - private void setFinish(@State.REFRESH_STATE int state) { - if (state == State.REFRESH) { - if (mHeaderView != null && mHeaderView.getView().getLayoutParams().height > 0 && isRefresh) { - setFinish(head_height, state); - } - } else { - if (mFooterView != null && mFooterView.getView().getLayoutParams().height > 0 && isLoadMore) { - setFinish(foot_height, state); - } - } - } - - public interface CallBack { - void onSuccess(); - } - - private void showLoadingView() { - if (loadingView == null) { - loadingView = LayoutInflater.from(getContext()).inflate(loading, null); - LayoutParams layoutParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.MATCH_PARENT); - addView(loadingView, layoutParams); - } else { - loadingView.setVisibility(VISIBLE); - } - } - - private void showEmptyView() { - if (emptyView == null) { - emptyView = LayoutInflater.from(getContext()).inflate(empty, null); - LayoutParams layoutParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.MATCH_PARENT); - addView(emptyView, layoutParams); - } else { - emptyView.setVisibility(VISIBLE); - } - } - - private void showErrorView() { - if (errorView == null) { - errorView = LayoutInflater.from(getContext()).inflate(error, null); - LayoutParams layoutParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.MATCH_PARENT); - addView(errorView, layoutParams); - } else { - errorView.setVisibility(VISIBLE); - } - } - - private void hideView(View view) { - if (view != null) - view.setVisibility(GONE); - } - - private void switchView(int status) { - switch (status) { - case ViewStatus.CONTENT_STATUS: - hideView(loadingView); - hideView(emptyView); - hideView(errorView); - - mChildView.setVisibility(VISIBLE); - break; - case ViewStatus.LOADING_STATUS: - hideView(mChildView); - hideView(emptyView); - hideView(errorView); - - showLoadingView(); - break; - case ViewStatus.EMPTY_STATUS: - hideView(mChildView); - hideView(loadingView); - hideView(errorView); - - showEmptyView(); - break; - case ViewStatus.ERROR_STATUS: - hideView(mChildView); - hideView(loadingView); - hideView(emptyView); - - showErrorView(); - break; - default: - hideView(loadingView); - hideView(emptyView); - hideView(errorView); - - mChildView.setVisibility(VISIBLE); - break; - } - } - - /** - * 设置展示view (error,empty,loading) - */ - public void showView(@ViewStatus.VIEW_STATUS int status) { - switchView(status); - } - - /** - * 获取view (error,empty,loading) - */ - public View getView(@ViewStatus.VIEW_STATUS int status) { - switch (status) { - case ViewStatus.EMPTY_STATUS: - return emptyView; - case ViewStatus.LOADING_STATUS: - return loadingView; - case ViewStatus.ERROR_STATUS: - return errorView; - case ViewStatus.CONTENT_STATUS: - return mChildView; - } - return null; - } - - public void autoRefresh() { - createAnimatorTranslationY(State.REFRESH, - 0, head_height, - new CallBack() { - @Override - public void onSuccess() { - isRefresh = true; - if (refreshListener != null) { - refreshListener.onRefresh(); - } - mHeaderView.loading(); - } - }); - } - - /** - * 结束刷新 - */ - public void finishRefresh() { - setFinish(State.REFRESH); - } - - /** - * 结束加载更多 - */ - public void finishLoadMore() { - setFinish(State.LOAD_MORE); - } - - /** - * 设置是否启用加载更多 - */ - public void setCanLoadMore(boolean canLoadMore) { - this.canLoadMore = canLoadMore; - } - - /** - * 设置是否启用下拉刷新 - */ - public void setCanRefresh(boolean canRefresh) { - this.canRefresh = canRefresh; - } - - /** - * 设置是下拉刷新头部 - * - * @param mHeaderView 需实现 HeadView 接口 - */ - public void setHeaderView(IRefreshView mHeaderView) { - this.mHeaderView = mHeaderView; - addHeadView(); - } - - /** - * 设置是下拉刷新尾部 - * - * @param mFooterView 需实现 IRefreshView 接口 - */ - public void setFooterView(IRefreshView mFooterView) { - this.mFooterView = mFooterView; - addFooterView(); - } - - - /** - * 设置刷新控件的高度 - * - * @param dp 单位为dp - */ - public void setHeadHeight(int dp) { - head_height = PxUtils.dp2px(getContext(), dp); - } - - /** - * 设置加载更多控件的高度 - * - * @param dp 单位为dp - */ - public void setFootHeight(int dp) { - foot_height = PxUtils.dp2px(getContext(), dp); - } - - /** - * 同时设置加载更多控件和刷新控件的高度 - * - * @param dp 单位为dp - */ - public void setAllHeight(int dp) { - head_height = PxUtils.dp2px(getContext(), dp); - foot_height = PxUtils.dp2px(getContext(), dp); - } - - /** - * 同时设置加载更多控件和刷新控件的高度 - * - * @param refresh 刷新控件的高度 单位为dp - * @param loadMore 加载控件的高度 单位为dp - */ - public void setAllHeight(int refresh, int loadMore) { - head_height = PxUtils.dp2px(getContext(), refresh); - foot_height = PxUtils.dp2px(getContext(), loadMore); - } - - /** - * 设置刷新控件的下拉的最大高度 且必须大于本身控件的高度 最佳为2倍 - * - * @param dp 单位为dp - */ - public void setMaxHeadHeight(int dp) { - if (head_height >= PxUtils.dp2px(getContext(), dp)) { - return; - } - head_height_2 = PxUtils.dp2px(getContext(), dp); - } - - /** - * 设置加载更多控件的上拉的最大高度 且必须大于本身控件的高度 最佳为2倍 - * - * @param dp 单位为dp - */ - public void setMaxFootHeight(int dp) { - if (foot_height >= PxUtils.dp2px(getContext(), dp)) { - return; - } - foot_height_2 = PxUtils.dp2px(getContext(), dp); - } - - /** - * 同时设置加载更多控件和刷新控件的最大高度 且必须大于本身控件的高度 最佳为2倍 - * - * @param dp 单位为dp - */ - public void setAllMaxHeight(int dp) { - if (head_height >= PxUtils.dp2px(getContext(), dp)) { - return; - } - if (foot_height >= PxUtils.dp2px(getContext(), dp)) { - return; - } - head_height_2 = PxUtils.dp2px(getContext(), dp); - foot_height_2 = PxUtils.dp2px(getContext(), dp); - } - - /** - * 同时设置加载更多控件和刷新控件的最大高度 且必须大于本身控件的高度 最佳为2倍 - * - * @param refresh 刷新控件下拉的最大高度 单位为dp - * @param loadMore 加载控件上拉的最大高度 单位为dp - */ - public void setAllMaxHeight(int refresh, int loadMore) { - if (head_height >= PxUtils.dp2px(getContext(), refresh)) { - return; - } - if (foot_height >= PxUtils.dp2px(getContext(), loadMore)) { - return; - } - head_height_2 = PxUtils.dp2px(getContext(), refresh); - foot_height_2 = PxUtils.dp2px(getContext(), loadMore); - } - - -} diff --git a/common_base/src/main/java/com/wss/common/widget/pulltorefresh/RefreshView.java b/common_base/src/main/java/com/wss/common/widget/pulltorefresh/RefreshView.java deleted file mode 100644 index 2c340e3..0000000 --- a/common_base/src/main/java/com/wss/common/widget/pulltorefresh/RefreshView.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.wss.common.widget.pulltorefresh; - -import android.content.Context; -import android.util.AttributeSet; -import android.view.View; -import android.widget.FrameLayout; -import android.widget.ImageView; -import android.widget.TextView; - -import com.wss.common.base.R; -import com.wss.common.widget.LVCircularRing; - - -/** - * 刷新控件 - */ -public class RefreshView extends FrameLayout implements IRefreshView { - - private TextView tv; - private ImageView arrow; - // private ProgressBar progressBar; - private LVCircularRing lvCircularRing; - private boolean refresh = false;//是否是刷新 - - public RefreshView(Context context) { - this(context, null); - } - - public RefreshView(Context context, AttributeSet attrs) { - this(context, attrs, 0); - } - - public RefreshView(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - init(context); - } - - @Override - public void setType(boolean refresh) { - this.refresh = refresh; - } - - - private void init(Context context) { - View childView = View.inflate(context, R.layout.layout_refresh_view, null); - addView(childView); - tv = childView.findViewById(R.id.header_tv); - arrow = childView.findViewById(R.id.header_arrow); - lvCircularRing = childView.findViewById(R.id.header_progress); - } - - @Override - public void begin() { - - } - - @Override - public void progress(float progress, float all) { - float s = progress / all; - if (s >= 0.9f) { - arrow.setRotation(180); - } else { - arrow.setRotation(0); - } - if (progress >= all - 10) { - tv.setText(refresh ? R.string.pull_loose_refreshing : R.string.pull_loose_load_more); - } else { - tv.setText(refresh ? R.string.pull_down_refresh : R.string.pull_up_loading); - } - } - - @Override - public void finishing(float progress, float all) { - lvCircularRing.stopAnim(); - } - - @Override - public void loading() { - arrow.setVisibility(GONE); - lvCircularRing.setVisibility(VISIBLE); - lvCircularRing.startAnim(); - tv.setText(R.string.loading); - } - - @Override - public void normal() { - arrow.setVisibility(VISIBLE); - lvCircularRing.setVisibility(GONE); - lvCircularRing.stopAnim(); - tv.setText(refresh ? R.string.pull_down_refresh : R.string.pull_up_loading); - } - - @Override - public View getView() { - return this; - } -} diff --git a/common_base/src/main/java/com/wss/common/widget/pulltorefresh/State.java b/common_base/src/main/java/com/wss/common/widget/pulltorefresh/State.java deleted file mode 100644 index a7d0efb..0000000 --- a/common_base/src/main/java/com/wss/common/widget/pulltorefresh/State.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.wss.common.widget.pulltorefresh; - -import android.support.annotation.IntDef; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - - -/** - * 刷新状态 - */ -interface State { - - - @IntDef({REFRESH, LOAD_MORE}) - @Retention(RetentionPolicy.SOURCE) - @interface REFRESH_STATE { - } - - int REFRESH = 10; - int LOAD_MORE = 11; -} diff --git a/common_base/src/main/java/com/wss/common/widget/pulltorefresh/ViewStatus.java b/common_base/src/main/java/com/wss/common/widget/pulltorefresh/ViewStatus.java deleted file mode 100644 index 8dc43e6..0000000 --- a/common_base/src/main/java/com/wss/common/widget/pulltorefresh/ViewStatus.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.wss.common.widget.pulltorefresh; - -import android.support.annotation.IntDef; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - - -/** - * 加载状态 - */ -interface ViewStatus { - - @IntDef({CONTENT_STATUS, LOADING_STATUS, EMPTY_STATUS, ERROR_STATUS}) - @Retention(RetentionPolicy.SOURCE) - @interface VIEW_STATUS { - - } - - int CONTENT_STATUS = 0; - int LOADING_STATUS = 1; - int EMPTY_STATUS = 2; - int ERROR_STATUS = 3; - -} diff --git a/common_base/src/main/java/com/wss/common/widget/scaleImg/ImageViewer.java b/common_base/src/main/java/com/wss/common/widget/scaleImg/ImageViewer.java deleted file mode 100644 index 875225f..0000000 --- a/common_base/src/main/java/com/wss/common/widget/scaleImg/ImageViewer.java +++ /dev/null @@ -1,300 +0,0 @@ -package com.wss.common.widget.scaleImg; - -import android.annotation.SuppressLint; -import android.app.Activity; -import android.app.Dialog; -import android.net.Uri; -import android.provider.MediaStore; -import android.support.v4.view.ViewPager; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ImageView; -import android.widget.RelativeLayout; -import android.widget.TextView; - -import com.bumptech.glide.Glide; -import com.bumptech.glide.request.target.Target; -import com.davemorrissey.labs.subscaleview.ImageSource; -import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView; -import com.hjq.permissions.Permission; -import com.orhanobut.logger.Logger; -import com.wss.common.base.R; -import com.wss.common.utils.PermissionsUtils; -import com.wss.common.utils.ToastUtils; - -import java.io.File; -import java.io.FileNotFoundException; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.ExecutionException; - -/** - * Describe:图片查看器 - * Created by 吴天强 on 2018年11月16日17:02:05 - */ - -@SuppressLint("StaticFieldLeak") -public class ImageViewer { - - private static final byte URLS = 0; - private static final byte FILES = 1; - private byte mStatus; - - private Activity mActivity; - - //图片下载器 - private ImageDownloader mImageDownloader = (url, activity) -> { - File file = null; - try { - file = Glide.with(activity) - .load(url) - .downloadOnly(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL) - .get(); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - Logger.e("下载图片异常" + e.getMessage()); - } - return file; - }; - - private List mUrls = new ArrayList<>(); - private List mFiles = new ArrayList<>(); - private List mDownloadFiles = new ArrayList<>(); - - private int mSelectedPosition; - - private Dialog mDialog; - - private ImageView imDelete; - private ImageView imDownload; - private TextView tvImageCount; - private ViewPager mViewPager; - - private List mViews; - private ImageViewerAdapter mAdapter; - - private OnDeleteItemListener mListener; - private int mStartPosition = 0;//图片起始位置 - private static ImageViewer completeImageView; - - public static ImageViewer create(Activity activity) { - if (completeImageView == null) { - completeImageView = new ImageViewer(activity); - } - return completeImageView; - } - - private ImageViewer(Activity activity) { - mActivity = activity; - } - - /** - * 设置图片下载器 - * - * @param imageDownloader 图片下载器 - * @return ImageViewer - */ - public ImageViewer setImageDownloader(ImageDownloader imageDownloader) { - mImageDownloader = imageDownloader; - return this; - } - - /** - * 加载网络图片 - * - * @param urls 图片 - * @return ImageViewer - */ - public ImageViewer setUrls(List urls) { - mUrls.addAll(urls); - mStatus = URLS; - return this; - } - - /** - * 加载网络图片 - * - * @param url 图片 - * @return ImageViewer - */ - public ImageViewer setUrl(String url) { - List urls = new ArrayList<>(); - urls.add(url); - return setUrls(urls); - } - - /** - * 设置图片起始位置 - * - * @param position 起始位置 - * @return ImageViewer - */ - public ImageViewer setPosition(int position) { - this.mStartPosition = position; - return this; - } - - /** - * 加载本地图片 - * - * @param files 图片 - * @return ImageViewer - */ - public ImageViewer setFiles(List files) { - mFiles.addAll(files); - mStatus = FILES; - return this; - } - - /** - * 加载本地图片 - * - * @param file 图片 - * @return ImageViewer - */ - public ImageViewer setFiles(File file) { - List files = new ArrayList<>(); - files.add(file); - return setFiles(files); - } - - /** - * 删除图片监听 - * - * @param listener listener - * @return ImageViewer - */ - public ImageViewer setOnDeleteItemListener(OnDeleteItemListener listener) { - mListener = listener; - return this; - } - - private void init() { - RelativeLayout relativeLayout = (RelativeLayout) View.inflate(mActivity, R.layout.dialog_scale_image, null); - ImageView close = relativeLayout.findViewById(R.id.scale_image_close); - imDelete = relativeLayout.findViewById(R.id.scale_image_delete); - imDownload = relativeLayout.findViewById(R.id.scale_image_save); - tvImageCount = relativeLayout.findViewById(R.id.scale_image_count); - mViewPager = relativeLayout.findViewById(R.id.scale_image_view_pager); - mDialog = new Dialog(mActivity, R.style.DialogFullscreen); - mDialog.setContentView(relativeLayout); - close.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - mDialog.dismiss(); - } - }); - imDelete.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - int size = mViews.size(); - mFiles.remove(mSelectedPosition); - if (mListener != null) { - mListener.onDelete(mSelectedPosition); - } - mViewPager.removeView(mViews.remove(mSelectedPosition)); - if (mSelectedPosition != size) { - int position = mSelectedPosition + 1; - String text = position + "/" + mViews.size(); - tvImageCount.setText(text); - } - mAdapter.notifyDataSetChanged(); - } - }); - imDownload.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - - PermissionsUtils.checkPermissions(mActivity, Permission.WRITE_EXTERNAL_STORAGE).subscribe(r -> { - if (r) { - try { - MediaStore.Images.Media.insertImage(mActivity.getContentResolver(), - mDownloadFiles.get(mSelectedPosition).getAbsolutePath(), - mDownloadFiles.get(mSelectedPosition).getName(), null); - } catch (FileNotFoundException e) { - e.printStackTrace(); - } - ToastUtils.show(mActivity, "图片保存成功"); - } - }); - } - }); - mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { - @Override - public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { - } - - @Override - public void onPageSelected(int position) { - mSelectedPosition = position; - String text = ++position + "/" + mViews.size(); - tvImageCount.setText(text); - } - - @Override - public void onPageScrollStateChanged(int state) { - } - }); - - if (mStatus == URLS) { - imDelete.setVisibility(View.GONE); - } else { - imDownload.setVisibility(View.GONE); - } - } - - public void build() { - if (mImageDownloader == null) { - return; - } - init(); - mDialog.show(); - mViews = new ArrayList<>(); - mAdapter = new ImageViewerAdapter(mViews, mDialog); - if (mStatus == URLS) { - for (final String url : mUrls) { - final SubsamplingScaleImageView scaleImageView = new SubsamplingScaleImageView(mActivity); - scaleImageView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.MATCH_PARENT)); - - IOThread.getSingleThread().execute(new Runnable() { - @Override - public void run() { - final File downLoadFile; - try { - downLoadFile = mImageDownloader.downLoad(url, mActivity); - mDownloadFiles.add(downLoadFile); - mActivity.runOnUiThread(new Runnable() { - @Override - public void run() { - scaleImageView.setImage(ImageSource.uri(Uri.fromFile(downLoadFile))); - } - }); - } catch (Exception e) { - e.printStackTrace(); - Logger.e("加载图片异常" + e.getMessage()); - } - } - }); - mViews.add(scaleImageView); - } - mViewPager.setAdapter(mAdapter); - } else if (mStatus == FILES) { - for (File file : mFiles) { - final SubsamplingScaleImageView scaleImageView = new SubsamplingScaleImageView(mActivity); - scaleImageView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.MATCH_PARENT)); - scaleImageView.setImage(ImageSource.uri(Uri.fromFile(file))); - mViews.add(scaleImageView); - } - mViewPager.setAdapter(mAdapter); - } - mViewPager.setCurrentItem(mStartPosition); - tvImageCount.setText(String.format("%s/%s", mStartPosition + 1, mUrls.size())); - } - - public interface OnDeleteItemListener { - void onDelete(int position); - } - -} \ No newline at end of file diff --git a/common_base/src/main/res/color/selector_text_color.xml b/common_base/src/main/res/color/selector_text_color.xml new file mode 100644 index 0000000..4f9bfb5 --- /dev/null +++ b/common_base/src/main/res/color/selector_text_color.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/common_base/src/main/res/color/tab_text_color.xml b/common_base/src/main/res/color/tab_text_color.xml new file mode 100644 index 0000000..8cc3e47 --- /dev/null +++ b/common_base/src/main/res/color/tab_text_color.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/common_base/src/main/res/drawable-xxhdpi/bg_of_color_f5_4radius.xml b/common_base/src/main/res/drawable-xxhdpi/bg_of_color_f5_4radius.xml new file mode 100644 index 0000000..f633d90 --- /dev/null +++ b/common_base/src/main/res/drawable-xxhdpi/bg_of_color_f5_4radius.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/common_base/src/main/res/drawable-xxhdpi/header_load_default.png b/common_base/src/main/res/drawable-xxhdpi/header_load_default.png new file mode 100644 index 0000000000000000000000000000000000000000..26c21f0a27c1b4c5f5a1f222e1a29609bbbbbf0f GIT binary patch literal 9374 zcmV;PBw^c$P)005u}1^@s6i_d2*001OqNkl*$RxtU=}U~uxeQyuqwd>6h`_uXC?i+e>}AGp8d z=H|9z$uyfGh+_!K8~~eDT{o6Ej16PNSluh;0*xh1WA5Mc0!Q%zKT!&BR`e$rGscc< zaId7gB;DUxt&PyBRC0x`Q`sYMZSECTCUk$!%ggJ@DlA;*6p)MdQd}dh71!)uc_+7` zqN0Do%hY+KRL^=It{rpWCc(iiKR>@AtEE-E2qpCpJi}gsxxk#b$*AL2SXlTfPk4xu zJXnQ!(jk~5Hz{@C&GO{#;z_P>!)6gg%+W5l_biWd@mHS6xjdmy-Ei65pJMJXhi;PW zXdIC3#&>hF8>CuG#AM8+nz^Wp~4T!_kat!9&O`bNU*NG=2#|?(VAK)tMprLipv&jZ(uMfb^!u4p zqF+pi6TiE9=>pxkd4n|R>8=9deXNbEXEeGf(aTLuxl3^;j?k~`R?v^r18MHaK{RPV zR~psrBO2P_J@ReWjD~#DTy!7)JAOC%i?$Tx-JKQ$_|Urf)9ApiEp$EcvMYGWU0gN3 z=gl@pxl$(k<{yc4a(_6jnm&Oh_WO*6f7XiOYEFLb-)7L>X6TxWfBSsgj0PKY{0{%; z%Rmn0*P{D!59r>G76%TaV`0D0t?Sp+Y8PUSyj=~xK)$eNN|@j?Cl1rkvnEkspH2cY zbD-JUeRQ9P9yIU^+VNvB-Mn^HjSyn30$st={S()$Eq3;VYSPmv_UHjxG`9C}epuLPl63N^L+FfkNx}xR zYEHcPyBgK<2311nY{_@)`X97@;dJu%YN>S|91NZ@i8z66&8Yohs+5GPv-zAkVbKTo z(q#5xl>nZhG#uLDUD~*KHYMLpQX7bYYJtz&Sq=wca=)xyL4Ftwc;`+y4d1aYLx{CkLNTdR>iLl3n)LPOs#d+0;)cUI zy-&-(A43<;#45I)&}l`jx-xpFRWff|vCw7V(=U2}c`>4MYX&iZ5@L=kva;IY<^9n8 z&fLR+EJr|(b}prQEyWITv!P;V+2m1NP;o?2HX>MXs6D9Lz2>wF-V^eZD1WLC@EMbc zJ_uwFA4n0K*HF@}n@X_N7kr~CGywezP^)V?sMzz8<#I^f*R z*`of+?`LV`=WWEqy8*1}IiuEb2#2P|_G~XS#m=9X^4=B41-I+$7!VwCqlB|sut8`j z7aP|QQy1|0b$EvZ)N7TpRw1=5HfX5S1Hm^enjvCeZt(N~PSxsc4v46c4&sJN|`N=e6US~{2KC{wBXii2&x~EPmX7I>mj_cLItn?e?*_48Ze@Tf4SJL7Uz37{d-eeG)x{O5p zwyk9;IQGj=De3ktrEX#hw^sfBU1^UzjpHNLa44iX+i&29Z_wtMLy7K1Q(4LpI=y2a z&HSdb023gp7reLl+L~D92@m08KTaK1>_(Q%qXIq7%INKpAvpqNOOEX7q5Y8hGbL&bhv5IM|S>zLKhCF9kYhefYwbcdc!-o z{7S)x9F4Fh_IFlk17AHS$YKTb*R5WsvwMPx@_4&y#tCiDIw?SWntX^ZMgBl5#(qVk zy0qkld|gOJC4x7g^&8^n)c&6e@Ur99@eOs5F7BCc5kSlljwey_li#hWdQsfK7f3ThR4mtBLNPdJdq}ArW0du2ieB zIRL*`T;@ZQP7B8Ph{-h#;F~n|i#C*Tb{m5hQxiaa5LqGu#;11=QBw4J+P!!T%^&)O zct1ddB&`eQ1)nE?#z~xuNy+x_Hsfh02^Z^}d z&4m7Rc;z^{6gr*4xZE*#$uL;)4uLt)}g{2&F0;5I4?)R zYBz?p~~B#LZXpozxF4fOA0sN@fwD3;m~eoJz~t!EdK$D1`v#aHDeo& z+9`3s8C==1aEz~66%47cdh#IS_Mbf+K%zsM!ghq(#%BXi{DkDx9H+|U14MViv>g%* zk_=$sC+xS>ecIncoeJp|VI6SBI)CQ6NdwJFK+MrxR>2txe|Qd9GZuWFt<(W8{cfaL zCj{y){D*N2icA1n3uyWgJ+Q*<1IyaZKu0bMFmD6$94!v?SHtmcvyBy=#wm5cYY>Jp zBLU$-#_gD|l~#@bQ0i%i>lQlw&XV-E?K3TgVSbu9QSktRHADOFZ%QpZMc>Vj&@xwk zh5x$~#qqLiR|aq|r5yj!>^vY4z4PZ~YB=h*49w|gKfIJY;OK)9Vzaf63F(Idgn~pi z?z5s?7eH3?g%`Gxf5&%?hKNKe?$dYZc;p_nJo>>)F^3IV>esLSk4AQFW3(6nHqoSh zpU{)r2ki5JRRmzkAG>JESM813fdCNuWUy^j4FFa<%!p~+tn>lT82Xjby}-!tE*;f} zLnnt_9>DUOyJ^Mf-bTyKFgG{_Axpto5CaLgSw8@sp!5N6=Li28+Y5}`>9#rk_QwEK z1E3bdU2}$tYpwwx&&`$}7OLsFBMJH*aK6$993Oq0eA~CEVF#iL=E&M9+E|?<;d3;A zA{4WqqSj0j*KC;P8^(6 zywkSF^58Wibdw!zpY*f`K*S8$qZL^Y5u~;uFs(U2=ebb9+aMc)?8r>-PMm4^m7bun*D>y5I?RExp{nzby*Ny%B_;K7!MP}=-QE= z=+fRF#QO{X2-m7{q~xrH(G~!8X}99U9d!5T3c4J+fUZU?qMZ2kRB>yMbue-;`u5@F zG`!Qh)v98=KWs{S7WfN5DdPZ_pGB!c5`sN=z`n{JXeJe9ULqnqRewU%vZta;CrSyL6^BMFnD+`n%uX&$mK5d>mdqOC--a5^@9EAIzw5N>5vOR zhA-{p&lK{#H%;!-j%E$=qJ^A4p6~m)@M>p&^BKjg52B~nf302xW8`!0omo#4dV10z zohHCsjPQD&G|@k6B`YLs`aXJ;c3ushu&?5_U)C68Rw`9yYD=h)n+=)fQzZqF7o9es z6BTpefY~Y-jt`>zYRgPNn)v0%bbS3ZN;|t%yswmh|M*5ErJUJJ`&hz`@8L;d%f?fA z+EIqE_5eO(sTR9&3I+1#Zky>#w~j2QhZnX`DHkS`B<`ea1}c8*bfH3*j_5%J=eL-a zg#7!GtGj5%z>ZZpVbl|@`))w>95d&Q%aae&z07o_OTb{ohhQFNUVU!gv6M@W*`V9` z)|8F$*SQL&yB0ok5{u!z!NscchIFHBNK535;k4j=Sy5G$(@^8du^~b-rk>txxwOj? zfGo`b+YcZKUpo5J1Z^>cDNmSH^&-D7#I<7% zhH&~ViPf_BoN9JvB;{#tDnAs%iQzCM53(fVx91)%Lsr2*cLxX1RF-_x26|EGGAoJ@ zGPM%$$*ujCq2fvx)D@OPYiov!pCeOHh6= zn*T^tG=Lft0M?=-46}Vj5C!=3q0xhT(^!7ILHPRF?CeBYc06hWAVXJiJB+R#T1k7? zOr_Xe3#bsAkF1rD)jn&l`QlcVfREFDQ#yc&05C8A^jNqJ~Z;1UVN(6SSn`Q&*n;LO8{~_ z@S)~^N(V5-LurQ)8TR7Li|n1sm}X=3n|mdUf<_Lk0&oliIPbfmRB+9PO-;4}$c{zX zjXktv$}k4LulU~aL-E~x>CVYD)xFr-0?430V-=mNxvg{?FwaA2$8Z?-2U)k|+v}n0 z$asXWn?>Vz@c{!sJhFYE?e&B<0$9pU!_q1K0y-^#{b=kE1~7W9ya2KXTzdByWoK%X z4q&O`0lb%$PUV>#2fQCE>z4}^w7$F>vH$F^LMO|R2;#IIV7=7*enJ=*zFiiOKFic7az)3)A4ls&6y3y(aP__cqz1p-Mhg;zB!iFqO zIYGG@chpprng|sfua*HzP6^U;Wm)l@B{{8)6FN&OIvGGnyYl2C4BknRcFWGvkeb#K z>;b@|DjRfFjUXJ9qKu2Od&!Ci@UAu!@*wjDSG=T(k~KB1A=pDPLa0gyFM3htmHG)F zSG%Z5-I^#y2vx<7ICK3m0L-nQ0OnhXlZGsNfKM~IYC8XP{Q&T;c7O0A%|+D%D7Iy)Wn;S83(5SSb39>Z0LYn> z%B1}qeo0e1fcdIAn!~I&#k;>MGoo!PrBW+^Z2y&{sbBq8JDNl7p%`u5;04ErW1InC z`T=&lZn}c~w^=pEvsvei+@)vPa!Wxj(b60>-BURSdwY-ZerJ#T@bLp{N>ifLm~yjt zJe!x=F9_xPB^sHXku1(L=U*}1b2$xo@2v5jbwvZs~gGB^?PNI+yhGzTePbHgR1UyVb`mHwCpn`{dXOjl;d%CnOWW%`A8>;n+$ zSuQ&eCtjtVQcIPyeUE8S>Vsha^*`u#D!IRwd`Mqm$3+zdY{Q9CE?=H3+%L8T;c6OO>eyx#TLzm875f$F(Z; zfz|fM1~asU3bK}K9oK@0&VbOJP;Hk>>PcQN@9iy2zwA=*=>TkO_NnP=&kNTGcyiLd z3_;=CSoNghvJP{()frLg<4S8$E&pq(afEt=tKD^ZY!6mu#K`|J!@2;FLoTIhF&wJM zbUEnG(<2@!0Wp~B72U8x_w!FN&o~}3vT1j|Qd+NR%j)`0VvdveT9zv*6*bP9d6rd+8p7HD$oqOLlldfj%_W!fc8zYow6zr#75$UnT;j?TBUCaUZ=r?I zLC=aqg$y1flX{%(y%ciw`2|B@$-|z;ahp}HK0!Iz>3kA@tmQ|2nFKJxpz8&b#Sv_b(wszX$rTC>>J-2*(JMIB_9!1G13acDPo4+}IZ*3r5bpAjtLds_p1RQ8 zNo<=?adEL&{KAI?RCfOljtQQ$0YX~<1bCrb*~|xs^Rtg1KFFhjhlS$1(MwB95vX+~ z_?}vTt*dx6%V-^N3#FQ6O`-<(hrM`MK=VYpx_}rEOd2M-^a1yAa@DeyBnIa%!+j=Fi&W#cc2 zRP~9ftZE-Weryp4Nh0d^@<*Apd;5C&qI-Ah-KRJ8>C=b$_C@b2dLRCKuim|=U%!6z z+qrY}xTwg=?ilcbJL?aJJG&LP&6c=}f7A%-gpMB;<|NZZOXxOk}^x(k*Aqi~( zkn@>TQBfg488vF8NeCqX6BDmcd3m{2--8?C(4m9$;fJkxjE(5+x0};PA9<3eXB%qM z=0ob=|0`OtVmX~UbxJrOk&PFy0e^9h(%?%-NT6A> zX3{60v=a*_^>^QWhXH&^s5eNc)YMcHo^Z_$n-TD#KYR9!PMXi&Hrvy4MGV-sY6AtUcH*GT)EDwP1<)vH%o)h?heT{;VCVYqlrn!HYLyz#nNJV3Z`;X;v#utr4!A_+i11r_e^ zKTJqFLjZg9=uTU=ZV}QCuZQF`1v+d$+z0~(d@ZCO#`fNO?^45tFNzyRQo+W$Bo*;} zkjTz(TCnzDz{8o1b^knPf|s72PTRL{7m`QcZqo0NF8}$@OT4Hp#Q#Gbw`-bkjT zVy|AkglbMnNpYmzH_yY_4Z5H6n6b`rFye&mBrSre1$yV5w}o*J@TA{E;=s7Sd-rZt z49=94(uYs717U;t`uYgqBmm)<1O|@B!c<8>bYo#3*oG%hMu{5%@ac~kV}1GM|5}94 z7>NG<{%nTCJ7SYjti$a-GXd%sctH0ZC-u^3)25Box$|chr34n`_17BsuLvoKo5U6f(J>$0 zx^<=9yLZgY*US6(nHuS?WFau!!p_u{@pab|BGp5&oPXh4GH=9y}2LG~X2b#O-+O=y- zYu2o;i?B^G*4jgfja5$Xa|(3vx5jD}2% z0SFa*=g#dKDj1=eY15{P&(T-Gk_`y>5S-qzV+Vh4OOs=Ut=gc$KdD)>x9kE?>Igr< zR+Z7|D90LmD7o=Ky?LO|*08hmd&`#Zi?9kZ4u%i{ z7()Qj&YnHXz*P@M14bX8!2(V|sxJXyOX7D36Mgz=`)c;6F{%B+3;zl0F)ran9iR+U)yyE^iWgdisQv{z_(}5 z9%|qI6T9HULc^GU|NVEZdOsk9V*#}bNeIhZ-MYHO^e{=|ddP#gG=ANBI;WVa#Sym>RBeyx3v zSDK6tOn@W=n@r?m_r zgz+989xiM>2_k&}p_*aq8Owy=cTls}uU{8xmo+g(M@I`=%o_M4iG{I31zYtH+_4xVPYmM0^d{g9H5$2Gx5Qa_w zJY(d14Q)B7)7!Ui3vb*QfRYr1(}V`Khu0Ykxfly1V=Ne#RFohWfYNuYT)EO(ha=F# zm72~wF1MzVB{(?PZpmkC(g760F>po@Tu#l78kSOm%hJO4xj`6A^ned=CHsP>{$Hg!maA9#$>>XUq{n@hhAWQxXhP z4mSk88*xg2hl~v*vy>N>^ZNDYAtWTkWRO|$aXvXRCZ^JMDE1sZdZcX9&)NGKO}r67=4Q>_bP9m*@W+oIpTnV|P9E;2E$=^g z@L&wonxg@Pdj0pmUl1`vOW!R8s1StG&mIqTL^8a;YcG44=DEX;EN8(0OPK0v5NG;}(w4>q?JLFPB!c+FwpVNNl(8#itY zs@E#lQe#!zi1%yk!^RKr`G zA?A`Dr+t`PH(^$`h=_=8fq{X^*kshUZQD9qAb6t4lGsywhu3%Q`ngqhU(I5J*KEpD z+g=OUR&3A;3>=#r5fR$WO_UvtYv=yDZQGW)qeqV}t*hWP0?+{Pop)N;1t9jDAd6vZ zonq6bO+@&oE^aE!70=mI%pK;?O;Rn}@#DuEFI%>37l#fiFu8Ir7Qh35um$Y_5T*XM z*pJftkdKzD+)C=08_W^r3UlTrN9Gn26Z0zPi9`JShL(NtMYmc9aU}rZ1)Hl-HVfLZ!qQpbAq|S9JxuUV^cg7eHJyt{roLxxk#b$#8Jvs*Zp12A|-mQ>W(j?b}F*f75* z^XJcr!q{;Q?v-?nRNr3?A3ofUHyq7gv}jQrZ^0}ZFkpbl>jD7O?x7^>g%=uF9TSvb zvc{X$mu|1T^0M%pkci(e)uj#F+)Xqtiv7pp#S1*AOqt@#W%a>q_-`IOcyO4v_rPOZNs`dL zd-p_6y``|^%;R3#wykF=+j4mfTT0iiT@&#dycX}_?U|eL8JyepU9)D5CqCOf!`0jW Y16Lr+p!U}*ZvX%Q07*qoM6N<$f(KPM@&Et; literal 0 HcmV?d00001 diff --git a/common_base/src/main/res/drawable-xxhdpi/icon_back.png b/common_base/src/main/res/drawable-xxhdpi/icon_back.png new file mode 100644 index 0000000000000000000000000000000000000000..e395a62989c6957e4ff4deeba44e2949e6137ef1 GIT binary patch literal 612 zcmV-q0-ODbP)Px%9!W$&R9Fe^m`y~bVHC%E`ICsMRteC9oHgduDF4%2(weQU(Vg^~msD6>7DN zNCg~;8T}r>y85UGL_kh*2~q6)QIMx+|f#EgCo4OaQ897Jm19Hg!o>Q$ju%ZL=i zrI^t#pw=p1or6qgNY0Ht>QKu7gg(QmGmF;^z0vXvbrwREa2ywO?GC=GgDnFPDu+Xm zdSGa=JVTv@P$}$#)DuIiI@mG*A@{D{6+^oF8{BSrhB^zOLf8Q*_Ytd09c&qZP(Eyl zA>B##TArcKLMRtDAzc0HV9Nl^a$r4d$UJCyhB^zOELim7mR%2#Fq=K#e{j3Co9Yib4vc zv@b%FB19uf&`N?nl$h!vEA63g!=mQb!@d`8XZAVwoI7{UDd-RPX|281|9|$``>eg! z?dbR)*+3`G#kIH>gIJH3@C?>qC9cA0=&YLa2%sAa@Fc!f4ByuT_oJt3AtzxSekmv- z4L{)#oLIJyV{3^IwMj@4f8cQ(GuA>naR+`FBOyr~z~T%()36qsa7|G$6Y)Y062H|F zEE5*~`NFH&gQ++Z^D!W76nS3Pb(j$0^j^a6lDuMiu{$H-Uw9r@Vq(Du)s4&XdJ|E* zF}-2j)QHdOJPBuGe@3D$IJ=05j9h2owTxV!VMfjOl!$$>S%TgSF`r{zJA_2?ULk$^ z9}?D1F+swbNqfzW5I_P_-}Na0o|M%sUF49+`k0NvE|Dr~ZmK zXF~iEXCUcxS;Xn(ia2M&$UAMAnRGf_=+7kI%h?t2jzVYvB(XQmc`)L;m&*(PQ@IdA$%(y z#)moMt!$f+h_J=@DhH8vV2?7Y6ruGpVC?=P^NldO%|DuL7B&g1j658+iXkjl(swRP zSSQZIgZQ|BfMKDeTCU{AS|MNtF2(J_=CB4&2o34`a5LuN_;%<18@uDC_Q-;*A^-pY M07*qoM6N<$g8sGm2LJ#7 literal 0 HcmV?d00001 diff --git a/common_base/src/main/res/drawable/browser_progress_bg.xml b/common_base/src/main/res/drawable/browser_progress_bg.xml new file mode 100644 index 0000000..d887fed --- /dev/null +++ b/common_base/src/main/res/drawable/browser_progress_bg.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/common_base/src/main/res/drawable/corners_black_shape.xml b/common_base/src/main/res/drawable/corners_black_shape.xml new file mode 100644 index 0000000..695d250 --- /dev/null +++ b/common_base/src/main/res/drawable/corners_black_shape.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/common_base/src/main/res/drawable/corners_theme_shape_45.xml b/common_base/src/main/res/drawable/corners_theme_shape_45.xml new file mode 100644 index 0000000..e85348d --- /dev/null +++ b/common_base/src/main/res/drawable/corners_theme_shape_45.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/common_base/src/main/res/drawable/stroke_gray_white_shape.xml b/common_base/src/main/res/drawable/stroke_gray_white_shape.xml new file mode 100644 index 0000000..8125cfd --- /dev/null +++ b/common_base/src/main/res/drawable/stroke_gray_white_shape.xml @@ -0,0 +1,12 @@ + + + + + + + + + + \ No newline at end of file diff --git a/common_base/src/main/res/layout/action_bar.xml b/common_base/src/main/res/layout/action_bar.xml index 85fd5c6..9da3300 100644 --- a/common_base/src/main/res/layout/action_bar.xml +++ b/common_base/src/main/res/layout/action_bar.xml @@ -7,12 +7,12 @@ + android:paddingStart="@dimen/title_bar_padding" + android:paddingEnd="6dp" /> diff --git a/common_base/src/main/res/layout/activity_base.xml b/common_base/src/main/res/layout/activity_base.xml index d37ca85..79d7212 100644 --- a/common_base/src/main/res/layout/activity_base.xml +++ b/common_base/src/main/res/layout/activity_base.xml @@ -2,15 +2,20 @@ + android:layout_height="@dimen/title_bar_height" + android:background="@color/white" + android:visibility="gone" /> - + + + diff --git a/common_base/src/main/res/layout/activity_browser.xml b/common_base/src/main/res/layout/activity_browser.xml new file mode 100644 index 0000000..ea06bb1 --- /dev/null +++ b/common_base/src/main/res/layout/activity_browser.xml @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/common_base/src/main/res/layout/activity_horizontal_tab.xml b/common_base/src/main/res/layout/activity_horizontal_tab.xml index 8c026bc..6e353e7 100644 --- a/common_base/src/main/res/layout/activity_horizontal_tab.xml +++ b/common_base/src/main/res/layout/activity_horizontal_tab.xml @@ -13,16 +13,16 @@ android:background="@color/white" app:pstsBold="true" app:pstsHasTopLine="false" - app:pstsIndicatorColor="@color/blue" + app:pstsIndicatorColor="@color/theme" app:pstsIndicatorHeight="1.5dp" app:pstsShouldExpand="true" app:pstsTextDefaultColor="@color/black" - app:pstsTextSelectedColor="@color/blue" + app:pstsTextSelectedColor="@color/theme" app:pstsTextSize="14sp" app:pstsUnderlineColor="@color/gray" app:pstsUnderlineHeight="1px" /> - diff --git a/common_base/src/main/res/layout/activity_image_gallery.xml b/common_base/src/main/res/layout/activity_image_gallery.xml new file mode 100644 index 0000000..fa58373 --- /dev/null +++ b/common_base/src/main/res/layout/activity_image_gallery.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/common_base/src/main/res/layout/activity_scan.xml b/common_base/src/main/res/layout/activity_scan.xml new file mode 100644 index 0000000..c6f24c3 --- /dev/null +++ b/common_base/src/main/res/layout/activity_scan.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/module_main/src/main/res/layout/main_fragment_center.xml b/common_base/src/main/res/layout/activity_select_file.xml similarity index 65% rename from module_main/src/main/res/layout/main_fragment_center.xml rename to common_base/src/main/res/layout/activity_select_file.xml index f6d11cb..1936a51 100644 --- a/module_main/src/main/res/layout/main_fragment_center.xml +++ b/common_base/src/main/res/layout/activity_select_file.xml @@ -1,14 +1,13 @@ - - + android:layout_marginStart="5dp" + android:layout_marginEnd="5dp" /> + \ No newline at end of file diff --git a/common_base/src/main/res/layout/activity_springboard.xml b/common_base/src/main/res/layout/activity_springboard.xml new file mode 100644 index 0000000..8e17cb3 --- /dev/null +++ b/common_base/src/main/res/layout/activity_springboard.xml @@ -0,0 +1,6 @@ + + diff --git a/common_base/src/main/res/layout/activity_webview.xml b/common_base/src/main/res/layout/activity_webview.xml deleted file mode 100644 index 5a638d0..0000000 --- a/common_base/src/main/res/layout/activity_webview.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - diff --git a/common_base/src/main/res/layout/base_tablayout_child.xml b/common_base/src/main/res/layout/base_tablayout_child.xml new file mode 100644 index 0000000..ab0e0dd --- /dev/null +++ b/common_base/src/main/res/layout/base_tablayout_child.xml @@ -0,0 +1,13 @@ + + + \ No newline at end of file diff --git a/common_base/src/main/res/layout/dailog_date.xml b/common_base/src/main/res/layout/dailog_date.xml new file mode 100644 index 0000000..0ed6397 --- /dev/null +++ b/common_base/src/main/res/layout/dailog_date.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + diff --git a/common_base/src/main/res/layout/dialog_app.xml b/common_base/src/main/res/layout/dialog_app.xml index a15c600..54c0709 100644 --- a/common_base/src/main/res/layout/dialog_app.xml +++ b/common_base/src/main/res/layout/dialog_app.xml @@ -7,12 +7,13 @@ + android:paddingTop="15dp" + android:visibility="gone"> - - - - - + android:layout_height="wrap_content"> - - - - - - - + android:id="@+id/ll_content_layout" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:gravity="center" + android:orientation="vertical" + android:paddingLeft="10dp" + android:paddingRight="10dp"> - + - - - - - - - - - - + android:visibility="gone" /> - + + android:layout_marginTop="15dp"> - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/common_base/src/main/res/layout/empty_layout.xml b/common_base/src/main/res/layout/empty_layout.xml deleted file mode 100644 index cec4857..0000000 --- a/common_base/src/main/res/layout/empty_layout.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - diff --git a/common_base/src/main/res/layout/item_of_load_all_data.xml b/common_base/src/main/res/layout/item_of_load_all_data.xml new file mode 100644 index 0000000..e72aab4 --- /dev/null +++ b/common_base/src/main/res/layout/item_of_load_all_data.xml @@ -0,0 +1,17 @@ + + + + + \ No newline at end of file diff --git a/common_base/src/main/res/layout/item_of_select_file.xml b/common_base/src/main/res/layout/item_of_select_file.xml new file mode 100644 index 0000000..6986840 --- /dev/null +++ b/common_base/src/main/res/layout/item_of_select_file.xml @@ -0,0 +1,27 @@ + + + + + + + + \ No newline at end of file diff --git a/common_base/src/main/res/layout/item_of_select_image.xml b/common_base/src/main/res/layout/item_of_select_image.xml new file mode 100644 index 0000000..ac480ff --- /dev/null +++ b/common_base/src/main/res/layout/item_of_select_image.xml @@ -0,0 +1,26 @@ + + + + + + + + \ No newline at end of file diff --git a/common_base/src/main/res/layout/item_of_selector_pop.xml b/common_base/src/main/res/layout/item_of_selector_pop.xml new file mode 100644 index 0000000..79adb8e --- /dev/null +++ b/common_base/src/main/res/layout/item_of_selector_pop.xml @@ -0,0 +1,21 @@ + + + + + + + diff --git a/common_base/src/main/res/layout/layout_banner_img.xml b/common_base/src/main/res/layout/layout_banner_img.xml index f9f2372..ac220c5 100644 --- a/common_base/src/main/res/layout/layout_banner_img.xml +++ b/common_base/src/main/res/layout/layout_banner_img.xml @@ -9,7 +9,7 @@ android:id="@+id/image" android:layout_width="match_parent" android:layout_height="match_parent" - android:scaleType="centerCrop" /> + android:scaleType="fitXY" /> diff --git a/common_base/src/main/res/layout/fragment_base.xml b/common_base/src/main/res/layout/layout_base.xml similarity index 86% rename from common_base/src/main/res/layout/fragment_base.xml rename to common_base/src/main/res/layout/layout_base.xml index 15cc49e..9919d9a 100644 --- a/common_base/src/main/res/layout/fragment_base.xml +++ b/common_base/src/main/res/layout/layout_base.xml @@ -2,13 +2,14 @@ + android:layout="@layout/layout_empty" /> + android:id="@+id/iv_empty" + android:layout_width="wrap_content" + android:layout_height="wrap_content" /> + android:layout_marginTop="19dp" + android:textColor="@color/color_999999" + android:textSize="14sp" /> + + + - \ No newline at end of file + diff --git a/common_base/src/main/res/layout/layout_error.xml b/common_base/src/main/res/layout/layout_error.xml deleted file mode 100644 index 8f580bc..0000000 --- a/common_base/src/main/res/layout/layout_error.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/common_base/src/main/res/layout/layout_item_of_dialog_bottom_in.xml b/common_base/src/main/res/layout/layout_item_of_dialog_bottom_in.xml index ed06b47..a7c33fd 100644 --- a/common_base/src/main/res/layout/layout_item_of_dialog_bottom_in.xml +++ b/common_base/src/main/res/layout/layout_item_of_dialog_bottom_in.xml @@ -8,10 +8,10 @@ android:id="@+id/tv_text" style="@style/TextStyle" android:layout_width="match_parent" - android:layout_height="50dp" - android:gravity="center" /> + android:layout_height="wrap_content" + android:gravity="center" + android:minHeight="45dp" /> - diff --git a/common_base/src/main/res/layout/layout_loading.xml b/common_base/src/main/res/layout/layout_loading.xml deleted file mode 100644 index 773706a..0000000 --- a/common_base/src/main/res/layout/layout_loading.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/common_base/src/main/res/layout/layout_nothing.xml b/common_base/src/main/res/layout/layout_nothing.xml new file mode 100644 index 0000000..4ce1eae --- /dev/null +++ b/common_base/src/main/res/layout/layout_nothing.xml @@ -0,0 +1,5 @@ + + + diff --git a/common_base/src/main/res/layout/layout_refresh.xml b/common_base/src/main/res/layout/layout_refresh.xml index c29def5..e0845be 100644 --- a/common_base/src/main/res/layout/layout_refresh.xml +++ b/common_base/src/main/res/layout/layout_refresh.xml @@ -1,13 +1,15 @@ - + android:layout_height="match_parent" + android:background="@color/bg" + android:fillViewport="true"> - + android:layout_height="match_parent" + android:background="@color/bg" /> - - + diff --git a/common_base/src/main/res/layout/layout_refresh_view.xml b/common_base/src/main/res/layout/layout_refresh_view.xml deleted file mode 100644 index b1a4130..0000000 --- a/common_base/src/main/res/layout/layout_refresh_view.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/common_base/src/main/res/layout/layout_search.xml b/common_base/src/main/res/layout/layout_search.xml new file mode 100644 index 0000000..4eeffa7 --- /dev/null +++ b/common_base/src/main/res/layout/layout_search.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/common_base/src/main/res/layout/pop_date_range.xml b/common_base/src/main/res/layout/pop_date_range.xml new file mode 100644 index 0000000..a58e5ce --- /dev/null +++ b/common_base/src/main/res/layout/pop_date_range.xml @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module_main/src/main/res/layout/main_activity_scale_image.xml b/common_base/src/main/res/layout/pop_selector.xml similarity index 56% rename from module_main/src/main/res/layout/main_activity_scale_image.xml rename to common_base/src/main/res/layout/pop_selector.xml index 0c3e47f..d1a280c 100644 --- a/module_main/src/main/res/layout/main_activity_scale_image.xml +++ b/common_base/src/main/res/layout/pop_selector.xml @@ -2,18 +2,19 @@ -