Commit e47f8554b12ecef9419fe96acf2461ab8a2f97c6

Authored by 韩亚云
2 parents e9d55089 d6c3ecde

Merge branch 'master' of bj.gitlab.cnlive.com:cnlive-team/newModuleStrike

Showing 37 changed files with 3571 additions and 457 deletions

Too many changes to show.

To preserve performance only 37 of 470 files are displayed.

app/strike/build.gradle
@@ -159,6 +159,7 @@ dependencies { @@ -159,6 +159,7 @@ dependencies {
159 implementation project(path: ':cloud:user') 159 implementation project(path: ':cloud:user')
160 160
161 implementation project(path: ':core:imageload') 161 implementation project(path: ':core:imageload')
  162 + compile project(path: ':module:xiaojiasoundbox')
162 // implementation project(path: ':core:util') 163 // implementation project(path: ':core:util')
163 // implementation project(path: ':core:encipher') 164 // implementation project(path: ':core:encipher')
164 // implementation project(path: ':cloud:user') 165 // implementation project(path: ':cloud:user')
cloud/user/src/main/java/com/cnlive/strike/user/network/api/BaseRequest.java renamed to app/strike/src/BaseRequest.java
app/strike/src/main/java/com/cnlive/strike/MainActivity.java
@@ -9,7 +9,9 @@ import android.util.AttributeSet; @@ -9,7 +9,9 @@ import android.util.AttributeSet;
9 import android.util.Log; 9 import android.util.Log;
10 import android.view.View; 10 import android.view.View;
11 11
  12 +import com.cnlive.strike.demo.activity.DemoActivity;
12 import com.cnlive.strike.imgutil.ImgActivity; 13 import com.cnlive.strike.imgutil.ImgActivity;
  14 +import com.cnlive.strike.user.ui.activity.LoginActivity;
13 15
14 import androidx.annotation.NonNull; 16 import androidx.annotation.NonNull;
15 import androidx.annotation.Nullable; 17 import androidx.annotation.Nullable;
@@ -22,6 +24,7 @@ public class MainActivity extends AppCompatActivity { @@ -22,6 +24,7 @@ public class MainActivity extends AppCompatActivity {
22 protected void onCreate(@Nullable Bundle savedInstanceState) { 24 protected void onCreate(@Nullable Bundle savedInstanceState) {
23 super.onCreate(savedInstanceState); 25 super.onCreate(savedInstanceState);
24 setContentView(R.layout.activity_main); 26 setContentView(R.layout.activity_main);
  27 + findViewById(R.id.go_to).setOnClickListener(view -> startActivity(new Intent(this, DemoActivity.class)) );
25 findViewById(R.id.to_img).setOnClickListener(view -> startActivity(new Intent(this, ImgActivity.class)) ); 28 findViewById(R.id.to_img).setOnClickListener(view -> startActivity(new Intent(this, ImgActivity.class)) );
26 } 29 }
27 30
app/strike/src/main/java/com/cnlive/strike/MyActivity.java
1 package com.cnlive.strike; 1 package com.cnlive.strike;
2 2
3 3
  4 +import android.content.Intent;
  5 +import android.text.TextUtils;
  6 +
4 import com.cnlive.core.libs.base.frame.activity.BaseActivity; 7 import com.cnlive.core.libs.base.frame.activity.BaseActivity;
  8 +import com.cnlive.strike.user.auth.UserService;
  9 +import com.cnlive.strike.xiaojiaspeaker.commonInfo.XiaoJIaCommInfo;
  10 +import com.cnlive.strike.xiaojiaspeaker.ui.activity.AllDeviceActivity;
5 11
6 12
7 public class MyActivity extends BaseActivity { 13 public class MyActivity extends BaseActivity {
@@ -13,11 +19,35 @@ public class MyActivity extends BaseActivity { @@ -13,11 +19,35 @@ public class MyActivity extends BaseActivity {
13 19
14 @Override 20 @Override
15 protected void initView() { 21 protected void initView() {
16 - setOpenSwipBack(true);  
17 - getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new MyFragment()).commitAllowingStateLoss(); 22 +// getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new MyFragment()).commitAllowingStateLoss();
  23 + initXiaoJiaSoundBoxData();
  24 + startActivity(new Intent(MyActivity.this,AllDeviceActivity.class));
18 } 25 }
19 26
20 @Override 27 @Override
21 protected void initData() { 28 protected void initData() {
22 } 29 }
  30 +
  31 + /**
  32 + * 初始化小家音箱数据
  33 + */
  34 + private void initXiaoJiaSoundBoxData() {
  35 +// XiaoJIaCommInfo.setUserId(this, "10514333");
  36 +// XiaoJIaCommInfo.setUserPhone(this, "18301489586");
  37 + if (!TextUtils.isEmpty(UserService.getUid(this))) {
  38 + XiaoJIaCommInfo.setUserId(this, UserService.getUid(this));
  39 + }
  40 + if (null == UserService.getInstance(this).getAppAccount()) {
  41 + return;
  42 + }
  43 + if (null != UserService.getInstance(this).getAppAccount().getMobile() && !TextUtils.isEmpty(UserService.getInstance(this).getAppAccount().getMobile())) {
  44 + XiaoJIaCommInfo.setUserPhone(this, UserService.getInstance(this).getAppAccount().getMobile());
  45 + }
  46 + if (!TextUtils.isEmpty(UserService.getInstance(this).getAppAccount().getFaceUrl())) {
  47 + XiaoJIaCommInfo.setUserIcon(this, UserService.getInstance(this).getAppAccount().getFaceUrl());
  48 + }
  49 + if (!TextUtils.isEmpty(UserService.getInstance(this).getAppAccount().getNickName())) {
  50 + XiaoJIaCommInfo.setUserNickName(this, UserService.getInstance(this).getAppAccount().getNickName());
  51 + }
  52 + }
23 } 53 }
app/strike/src/main/java/com/cnlive/strike/MyFragment.java
@@ -4,9 +4,7 @@ package com.cnlive.strike; @@ -4,9 +4,7 @@ package com.cnlive.strike;
4 import android.Manifest; 4 import android.Manifest;
5 import android.os.Bundle; 5 import android.os.Bundle;
6 import android.util.Log; 6 import android.util.Log;
7 -import android.view.LayoutInflater;  
8 import android.view.View; 7 import android.view.View;
9 -import android.view.ViewGroup;  
10 import android.widget.TextView; 8 import android.widget.TextView;
11 9
12 import com.cnlive.core.libs.base.frame.fragment.BaseFragment; 10 import com.cnlive.core.libs.base.frame.fragment.BaseFragment;
@@ -15,13 +13,12 @@ import com.cnlive.core.network.BaseResult; @@ -15,13 +13,12 @@ import com.cnlive.core.network.BaseResult;
15 import com.cnlive.core.network.HttpConn; 13 import com.cnlive.core.network.HttpConn;
16 import com.cnlive.core.network.NetCallBack; 14 import com.cnlive.core.network.NetCallBack;
17 import com.cnlive.core.libs.base.util.StatusBarConfig; 15 import com.cnlive.core.libs.base.util.StatusBarConfig;
18 -import com.cnlive.strike.network.BaseRequest; 16 +import com.cnlive.core.network.request.BaseRequest;
19 import com.cnlive.strike.network.api.ApiService; 17 import com.cnlive.strike.network.api.ApiService;
20 import com.cnlive.strike.network.bean.LetHimNoSeeBean; 18 import com.cnlive.strike.network.bean.LetHimNoSeeBean;
21 import com.cnlive.strike.network.bean.TestBean; 19 import com.cnlive.strike.network.bean.TestBean;
22 -  
23 -import androidx.annotation.NonNull;  
24 -import androidx.annotation.Nullable; 20 +import com.me.yokeyword.fragmentation.anim.DefaultVerticalAnimator;
  21 +import com.me.yokeyword.fragmentation.anim.FragmentAnimator;
25 22
26 import java.util.HashMap; 23 import java.util.HashMap;
27 import java.util.Map; 24 import java.util.Map;
@@ -31,23 +28,21 @@ import io.reactivex.functions.Function; @@ -31,23 +28,21 @@ import io.reactivex.functions.Function;
31 28
32 29
33 public class MyFragment extends BaseFragment<MyFragmentView, MyPresenter> { 30 public class MyFragment extends BaseFragment<MyFragmentView, MyPresenter> {
34 - private View view;  
35 public TextView textView; 31 public TextView textView;
36 32
37 - @Nullable  
38 @Override 33 @Override
39 - public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {  
40 - view = inflater.inflate(R.layout.activity_main1, container, false);  
41 - textView = view.findViewById(R.id.tv1);  
42 - return view; 34 + protected int getViewLayoutId() {
  35 + return R.layout.activity_main1;
43 } 36 }
44 37
45 @Override 38 @Override
46 protected void initView() { 39 protected void initView() {
47 super.initView(); 40 super.initView();
  41 + setSwipeBackEnable(true);
48 setStatusBarColor(R.color.green, 0); 42 setStatusBarColor(R.color.green, 0);
49 setStatusBarTextColor(StatusBarConfig.BLACK); 43 setStatusBarTextColor(StatusBarConfig.BLACK);
50 - view.findViewById(R.id.btn_test2).setOnClickListener(new View.OnClickListener() { 44 + textView = baseView.findViewById(R.id.tv1);
  45 + baseView.findViewById(R.id.btn_test2).setOnClickListener(new View.OnClickListener() {
51 @Override 46 @Override
52 public void onClick(View v) { 47 public void onClick(View v) {
53 requestPermission(010001, "测试", new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, new OnPermissionResponseListener() { 48 requestPermission(010001, "测试", new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, new OnPermissionResponseListener() {
@@ -63,23 +58,24 @@ public class MyFragment extends BaseFragment&lt;MyFragmentView, MyPresenter&gt; { @@ -63,23 +58,24 @@ public class MyFragment extends BaseFragment&lt;MyFragmentView, MyPresenter&gt; {
63 }); 58 });
64 } 59 }
65 }); 60 });
66 - view.findViewById(R.id.btn_test1).setOnClickListener(new View.OnClickListener() { 61 + baseView.findViewById(R.id.btn_test1).setOnClickListener(new View.OnClickListener() {
67 @Override 62 @Override
68 public void onClick(View v) { 63 public void onClick(View v) {
69 - requestPermission(new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, new OnPermissionResponseListener() {  
70 - @Override  
71 - public void onSuccess(String[] permissions) {  
72 - Log.e(TAG, "onSuccess: ");  
73 - }  
74 -  
75 - @Override  
76 - public void onFail() {  
77 - Log.e(TAG, "onFail: ");  
78 - }  
79 - }); 64 +// requestPermission(new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, new OnPermissionResponseListener() {
  65 +// @Override
  66 +// public void onSuccess(String[] permissions) {
  67 +// Log.e(TAG, "onSuccess: ");
  68 +// }
  69 +//
  70 +// @Override
  71 +// public void onFail() {
  72 +// Log.e(TAG, "onFail: ");
  73 +// }
  74 +// });
  75 + startForResult(new MyFragment1(),1001);
80 } 76 }
81 }); 77 });
82 - view.findViewById(R.id.btn_test).setOnClickListener(new View.OnClickListener() { 78 + baseView.findViewById(R.id.btn_test).setOnClickListener(new View.OnClickListener() {
83 @Override 79 @Override
84 public void onClick(View v) { 80 public void onClick(View v) {
85 //单个请求 81 //单个请求
@@ -144,4 +140,17 @@ public class MyFragment extends BaseFragment&lt;MyFragmentView, MyPresenter&gt; { @@ -144,4 +140,17 @@ public class MyFragment extends BaseFragment&lt;MyFragmentView, MyPresenter&gt; {
144 getPresenter().setData("hha"); 140 getPresenter().setData("hha");
145 getMvpView().setData("test"); 141 getMvpView().setData("test");
146 } 142 }
  143 +
  144 + @Override
  145 + public FragmentAnimator onCreateFragmentAnimator() {
  146 + return new DefaultVerticalAnimator();
  147 + }
  148 +
  149 + @Override
  150 + public void onFragmentResult(int requestCode, int resultCode, Bundle data) {
  151 + super.onFragmentResult(requestCode, resultCode, data);
  152 + if (requestCode==1001){
  153 + setStatusBarColor(R.color.green,0);
  154 + }
  155 + }
147 } 156 }
app/strike/src/main/java/com/cnlive/strike/MyFragment1.java
1 package com.cnlive.strike; 1 package com.cnlive.strike;
2 2
3 3
4 -import android.os.Bundle;  
5 -import android.view.LayoutInflater; 4 +import android.util.Log;
6 import android.view.View; 5 import android.view.View;
7 -import android.view.ViewGroup;  
8 -  
9 -import androidx.annotation.NonNull;  
10 -import androidx.annotation.Nullable;  
11 6
12 import com.cnlive.core.libs.base.frame.fragment.BaseFragment; 7 import com.cnlive.core.libs.base.frame.fragment.BaseFragment;
13 import com.cnlive.core.libs.base.util.StatusBarConfig; 8 import com.cnlive.core.libs.base.util.StatusBarConfig;
  9 +import com.cnlive.core.network.HttpConn;
  10 +import com.cnlive.core.network.NetCallBack;
  11 +import com.cnlive.core.network.request.BaseRequest;
  12 +import com.cnlive.strike.network.api.ApiService;
  13 +import com.cnlive.strike.network.bean.TestBean;
14 14
15 15
16 public class MyFragment1 extends BaseFragment { 16 public class MyFragment1 extends BaseFragment {
17 - private View view;  
18 17
19 - @Nullable 18 +
20 @Override 19 @Override
21 - public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {  
22 - view = inflater.inflate(R.layout.fragment_main1, container, false);  
23 - return view; 20 + protected int getViewLayoutId() {
  21 + return R.layout.fragment_main1;
24 } 22 }
25 23
26 @Override 24 @Override
@@ -28,5 +26,33 @@ public class MyFragment1 extends BaseFragment { @@ -28,5 +26,33 @@ public class MyFragment1 extends BaseFragment {
28 super.initView(); 26 super.initView();
29 setStatusBarColor(R.color.qmui_config_color_red, 0); 27 setStatusBarColor(R.color.qmui_config_color_red, 0);
30 setStatusBarTextColor(StatusBarConfig.BLACK); 28 setStatusBarTextColor(StatusBarConfig.BLACK);
  29 + baseView.findViewById(R.id.btn_test).setOnClickListener(new View.OnClickListener() {
  30 + @Override
  31 + public void onClick(View v) {
  32 + //单个请求
  33 + HttpConn.action(
  34 + BaseRequest
  35 + .init()
  36 + .setUrl("http://gank.io/api/data/")
  37 + .service(ApiService.class)
  38 + .getTest(), new NetCallBack<TestBean>() {
  39 + @Override
  40 + public void onRequestState(int state) {
  41 +
  42 + }
  43 +
  44 + @Override
  45 + public void onSuccess(TestBean data) {
  46 + Log.e(TAG, "onSuccess: " + data.getResults().size());
  47 + }
  48 +
  49 + @Override
  50 + public void onFailure(String errCode, String errMsg) {
  51 + Log.e(TAG, "onFailure: " + errMsg);
  52 + }
  53 +
  54 + });
  55 + }
  56 + });
31 } 57 }
32 } 58 }
app/strike/src/main/java/com/cnlive/strike/demo/activity/DemoActivity.java
@@ -7,7 +7,9 @@ import android.view.View; @@ -7,7 +7,9 @@ import android.view.View;
7 import com.cnlive.core.libs.base.frame.activity.BaseActivity; 7 import com.cnlive.core.libs.base.frame.activity.BaseActivity;
8 import com.cnlive.core.libs.base.interfaces.OnPermissionResponseListener; 8 import com.cnlive.core.libs.base.interfaces.OnPermissionResponseListener;
9 import com.cnlive.core.libs.base.util.StatusBarConfig; 9 import com.cnlive.core.libs.base.util.StatusBarConfig;
  10 +import com.cnlive.strike.MyFragment;
10 import com.cnlive.strike.R; 11 import com.cnlive.strike.R;
  12 +import com.cnlive.strike.base.BuildConfig;
11 13
12 /** 14 /**
13 * 继承BaseActivity 15 * 继承BaseActivity
@@ -19,10 +21,10 @@ public class DemoActivity extends BaseActivity { @@ -19,10 +21,10 @@ public class DemoActivity extends BaseActivity {
19 * 21 *
20 * @return 22 * @return
21 */ 23 */
22 - @Override  
23 - protected int getViewLayoutId() {  
24 - return R.layout.activity_demo_main;  
25 - } 24 +// @Override
  25 +// protected int getViewLayoutId() {
  26 +// return R.layout.activity_demo_main;
  27 +// }
26 28
27 /** 29 /**
28 * 设置binding布局 30 * 设置binding布局
@@ -30,16 +32,16 @@ public class DemoActivity extends BaseActivity { @@ -30,16 +32,16 @@ public class DemoActivity extends BaseActivity {
30 * 32 *
31 * @return 33 * @return
32 */ 34 */
33 - @Override  
34 - protected int getBindLayoutId() {  
35 - return super.getBindLayoutId();  
36 - } 35 +// @Override
  36 +// protected int getBindLayoutId() {
  37 +// return super.getBindLayoutId();
  38 +// }
37 39
38 - @Override  
39 - protected void initBindingData() {  
40 - super.initBindingData();  
41 -// binding=(你的bingding)baseBinding;  
42 - } 40 +// @Override
  41 +// protected void initBindingData() {
  42 +// super.initBindingData();
  43 +//// binding=(你的bingding)baseBinding;
  44 +// }
43 45
44 /** 46 /**
45 * 初始化intent传递参数 47 * 初始化intent传递参数
@@ -55,8 +57,8 @@ public class DemoActivity extends BaseActivity { @@ -55,8 +57,8 @@ public class DemoActivity extends BaseActivity {
55 @Override 57 @Override
56 protected void initView() { 58 protected void initView() {
57 super.initView(); 59 super.initView();
58 - //是指是否可以侧滑返回,默认禁用  
59 - setOpenSwipBack(true); 60 + //是指是否可以侧滑返回,默认禁用d
  61 +// setSwipeBackEnable(true);
60 //设置状态栏字体颜色 62 //设置状态栏字体颜色
61 setStatusBarTextColor(StatusBarConfig.WHITE); 63 setStatusBarTextColor(StatusBarConfig.WHITE);
62 //设置状态栏颜色 64 //设置状态栏颜色
@@ -75,6 +77,8 @@ public class DemoActivity extends BaseActivity { @@ -75,6 +77,8 @@ public class DemoActivity extends BaseActivity {
75 //px2dp 77 //px2dp
76 px2dp(10); 78 px2dp(10);
77 79
  80 + loadRootFragment(new MyFragment());
  81 +
78 // String[] permissions = new String[]{Manifest.permission.ACCESS_FINE_LOCATION, 82 // String[] permissions = new String[]{Manifest.permission.ACCESS_FINE_LOCATION,
79 // Manifest.permission.ACCESS_COARSE_LOCATION}; 83 // Manifest.permission.ACCESS_COARSE_LOCATION};
80 // //请求权限(默认提示语的) 84 // //请求权限(默认提示语的)
@@ -114,39 +118,30 @@ public class DemoActivity extends BaseActivity { @@ -114,39 +118,30 @@ public class DemoActivity extends BaseActivity {
114 // } 118 // }
115 // }); 119 // });
116 120
117 - findViewById(R.id.go_to1).setOnClickListener(new View.OnClickListener() {  
118 - @Override  
119 - public void onClick(View v) {  
120 - logError("Ada");  
121 - requestPermission(new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, new OnPermissionResponseListener() {  
122 - @Override  
123 - public void onSuccess(String[] permissions) {  
124 - Log.e(TAG, "onSuccess: ");  
125 - }  
126 -  
127 - @Override  
128 - public void onFail() {  
129 - Log.e(TAG, "onFail: ");  
130 - }  
131 - });  
132 - }  
133 - });  
134 - findViewById(R.id.go_to2).setOnClickListener(new View.OnClickListener() {  
135 - @Override  
136 - public void onClick(View v) {  
137 - requestPermission(10010, "拒绝我了", new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, new OnPermissionResponseListener() {  
138 - @Override  
139 - public void onSuccess(String[] permissions) {  
140 - Log.e(TAG, "onSuccess: ");  
141 - }  
142 -  
143 - @Override  
144 - public void onFail() {  
145 - Log.e(TAG, "onFail: ");  
146 - }  
147 - });  
148 - }  
149 - }); 121 +// findViewById(R.id.go_to1).setOnClickListener(new View.OnClickListener() {
  122 +// @Override
  123 +// public void onClick(View v) {
  124 +// logError("Ada");
  125 +// loadRootFragment(R.id.fl_container,new MyFragment());
  126 +//// start(new MyFragment());
  127 +// }
  128 +// });
  129 +// findViewById(R.id.go_to2).setOnClickListener(new View.OnClickListener() {
  130 +// @Override
  131 +// public void onClick(View v) {
  132 +// requestPermission(10010, "拒绝我了", new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, new OnPermissionResponseListener() {
  133 +// @Override
  134 +// public void onSuccess(String[] permissions) {
  135 +// Log.e(TAG, "onSuccess: ");
  136 +// }
  137 +//
  138 +// @Override
  139 +// public void onFail() {
  140 +// Log.e(TAG, "onFail: ");
  141 +// }
  142 +// });
  143 +// }
  144 +// });
150 } 145 }
151 146
152 /** 147 /**
@@ -157,5 +152,4 @@ public class DemoActivity extends BaseActivity { @@ -157,5 +152,4 @@ public class DemoActivity extends BaseActivity {
157 super.initData(); 152 super.initData();
158 } 153 }
159 154
160 -  
161 } 155 }
app/strike/src/main/res/values/styles.xml
@@ -2,6 +2,7 @@ @@ -2,6 +2,7 @@
2 2
3 <!-- Base application theme. --> 3 <!-- Base application theme. -->
4 <style name="AppTheme" parent="QMUI.Compat.NoActionBar"> 4 <style name="AppTheme" parent="QMUI.Compat.NoActionBar">
  5 + <item name="android:windowIsTranslucent">true</item>
5 <!-- Customize your theme here. --> 6 <!-- Customize your theme here. -->
6 <item name="colorPrimary">@color/colorPrimary</item> 7 <item name="colorPrimary">@color/colorPrimary</item>
7 <item name="colorPrimaryDark">@color/colorPrimaryDark</item> 8 <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
build.gradle
@@ -14,7 +14,6 @@ buildscript { @@ -14,7 +14,6 @@ buildscript {
14 } 14 }
15 dependencies { 15 dependencies {
16 classpath 'com.android.tools.build:gradle:3.5.1' 16 classpath 'com.android.tools.build:gradle:3.5.1'
17 -  
18 // NOTE: Do not place your application dependencies here; they belong 17 // NOTE: Do not place your application dependencies here; they belong
19 // in the individual module build.gradle files 18 // in the individual module build.gradle files
20 classpath "com.alibaba:arouter-register:1.0.2" 19 classpath "com.alibaba:arouter-register:1.0.2"
@@ -110,6 +109,7 @@ allprojects { @@ -110,6 +109,7 @@ allprojects {
110 109
111 //Tripartite Base 110 //Tripartite Base
112 for (String moudle : base_librarys) imput('implementation', project, moudle) 111 for (String moudle : base_librarys) imput('implementation', project, moudle)
  112 +// for (String moudle : base_librarys) imput('api', project, moudle)
113 for (String moudle : base_compilers) imput('annotationProcessor', project, moudle) 113 for (String moudle : base_compilers) imput('annotationProcessor', project, moudle)
114 114
115 } 115 }
@@ -118,13 +118,37 @@ allprojects { @@ -118,13 +118,37 @@ allprojects {
118 google() 118 google()
119 jcenter() 119 jcenter()
120 maven { 120 maven {
121 - url mixedUrl  
122 - credentials { username = mavenUsername; password = mavenPassword } 121 + url maven.mixedUrl
  122 + credentials { username = nexusId; password = nexusPw }
  123 + }
  124 + //------------------ 资源库配置 END------------------
  125 + maven {
  126 + url 'https://dl.bintray.com/granzon/cnlive'
  127 + }
  128 + maven {
  129 + url 'https://dl.bintray.com/granzon/cnliveLibs'
  130 + }
  131 + maven {
  132 + url "https://jitpack.io"
  133 + }
  134 + maven {
  135 + url 'http://developer.huawei.com/repo'
123 } 136 }
124 - maven { url 'https://jitpack.io' }  
125 - maven { url 'http://developer.huawei.com/repo' }  
126 } 137 }
127 } 138 }
128 task clean(type: Delete) { 139 task clean(type: Delete) {
129 delete rootProject.buildDir 140 delete rootProject.buildDir
130 } 141 }
  142 +
  143 +//配置全局变量
  144 +ext {
  145 + libEmoj = '2.0.9'
  146 + libMediaPicker = '1.5.8'
  147 + // loading动画
  148 + avi = "2.1.3"
  149 + //蓝牙
  150 + BleLib="2.3.4"
  151 + //动画大全
  152 + viewAnimationsEasing='2.0@aar'
  153 + viewAnimationsAndroid='2.3@aar'
  154 +}
cloud/user/build.gradle
@@ -46,7 +46,8 @@ dependencies { @@ -46,7 +46,8 @@ dependencies {
46 androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' 46 androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
47 47
48 implementation project(path: ':core:network') 48 implementation project(path: ':core:network')
49 -// implementation project(path: ':core:base') 49 + implementation "com.cnlive.libs:emoj:$rootProject.libEmoj"
  50 + //图片选择器
  51 + implementation "com.cnlive.libs:mediapicker:$rootProject.libMediaPicker"
50 52
51 - implementation 'com.cnlive.libs:emoj:2.0.9'  
52 } 53 }
cloud/user/src/main/java/com/cnlive/strike/user/UserUtilAction.java
@@ -7,17 +7,21 @@ import android.text.TextUtils; @@ -7,17 +7,21 @@ import android.text.TextUtils;
7 import com.cnlive.core.libs.base.application.AppConfig; 7 import com.cnlive.core.libs.base.application.AppConfig;
8 import com.cnlive.core.network.BaseResult; 8 import com.cnlive.core.network.BaseResult;
9 import com.cnlive.core.network.HttpConn; 9 import com.cnlive.core.network.HttpConn;
10 -import com.cnlive.strike.user.network.api.ApiBaseServiceOpen;  
11 -import com.cnlive.strike.user.network.api.BaseRequest;  
12 -import com.cnlive.strike.user.network.model.TokenData;  
13 -import com.cnlive.strike.user.network.model.UserData; 10 +import com.cnlive.core.network.UserData;
  11 +import com.cnlive.core.network.api.ApiBaseServiceOpen;
  12 +import com.cnlive.core.network.request.BaseRequest;
  13 +import com.cnlive.core.network.FaceData;
  14 +import com.cnlive.core.network.TokenData;
14 15
15 import java.io.File; 16 import java.io.File;
  17 +import java.util.ArrayList;
16 import java.util.HashMap; 18 import java.util.HashMap;
  19 +import java.util.List;
17 import java.util.Map; 20 import java.util.Map;
18 21
19 import io.reactivex.Observable; 22 import io.reactivex.Observable;
20 import okhttp3.MediaType; 23 import okhttp3.MediaType;
  24 +import okhttp3.MultipartBody;
21 import okhttp3.RequestBody; 25 import okhttp3.RequestBody;
22 26
23 27
@@ -239,35 +243,34 @@ public class UserUtilAction { @@ -239,35 +243,34 @@ public class UserUtilAction {
239 return BaseRequest.init().service(ApiBaseServiceOpen.class).accessToken(map); 243 return BaseRequest.init().service(ApiBaseServiceOpen.class).accessToken(map);
240 } 244 }
241 245
242 -// /**  
243 -// * 上传头像  
244 -// *  
245 -// * @param context  
246 -// * @param uid 用户ID  
247 -// * @param face 头像文件  
248 -// * @param token 平台TOKEN  
249 -// * @param access_token  
250 -// * @return  
251 -// */  
252 -// public static Disposable updateUserFace(Context context, String uid, File face, String token, String access_token, DataCallback<BaseInfo<FaceData>> callback) {  
253 -// Map<String, RequestBody> params = new HashMap<>();  
254 -//  
255 -// if (TextUtils.isEmpty(token)) {  
256 -// callback.callback(TOKEN_ERROR_CODE, TOKEN_ERROR_MSG, null);  
257 -// }  
258 -//  
259 -// params.put("uid", getRequestString(uid));  
260 -// params.put("clientPlat", getRequestString("a"));  
261 -// params.put("token", getRequestString(token));  
262 -// params.put("access_token", getRequestString(access_token));  
263 -//  
264 -// RequestBody requestFace = RequestBody.create(MediaType.parse("multipart/form-data"), face);  
265 -// MultipartBody.Part faceBody = MultipartBody.Part.createFormData("face", face.getName(), requestFace);  
266 -//  
267 -// List<MultipartBody.Part> parts = new ArrayList<>();  
268 -// parts.add(faceBody);  
269 -//  
270 -// 246 + /**
  247 + * 上传头像
  248 + *
  249 + * @param context
  250 + * @param uid 用户ID
  251 + * @param face 头像文件
  252 + * @param token 平台TOKEN
  253 + * @param access_token
  254 + * @return
  255 + */
  256 + public static Observable<BaseResult<FaceData>> updateUserFace(Context context, String uid, File face, String token, String access_token) {
  257 + Map<String, RequestBody> params = new HashMap<>();
  258 +
  259 + if (TextUtils.isEmpty(token)) {
  260 + HttpConn.error(TOKEN_ERROR_CODE, TOKEN_ERROR_MSG);
  261 + }
  262 + params.put("uid", getRequestString(uid));
  263 + params.put("clientPlat", getRequestString("a"));
  264 + params.put("token", getRequestString(token));
  265 + params.put("access_token", getRequestString(access_token));
  266 +
  267 + RequestBody requestFace = RequestBody.create(MediaType.parse("multipart/form-data"), face);
  268 + MultipartBody.Part faceBody = MultipartBody.Part.createFormData("face", face.getName(), requestFace);
  269 +
  270 + List<MultipartBody.Part> parts = new ArrayList<>();
  271 + parts.add(faceBody);
  272 +
  273 +
271 // Subscriber<BaseInfo<FaceData>> subscriber = new Subscriber<BaseInfo<FaceData>>(context, ApiBaseSubscriber.subscriberBuild) { 274 // Subscriber<BaseInfo<FaceData>> subscriber = new Subscriber<BaseInfo<FaceData>>(context, ApiBaseSubscriber.subscriberBuild) {
272 // @Override 275 // @Override
273 // public void onCompleted(String s, String s1, BaseInfo<FaceData> faceDataBaseInfo) { 276 // public void onCompleted(String s, String s1, BaseInfo<FaceData> faceDataBaseInfo) {
@@ -287,10 +290,11 @@ public class UserUtilAction { @@ -287,10 +290,11 @@ public class UserUtilAction {
287 // } 290 // }
288 // } 291 // }
289 // }; 292 // };
290 -//  
291 -// return ApiBaseRequest.subscribe(ApiBaseRequest.service(ApiBaseServiceOpen.class).updateUserFace(params, parts), subscriber);  
292 -//// return ApiBaseRequest.service(ApiBaseServiceOpen.class, service -> service.updateUserFace(params, parts)).subscribe(context, callback);  
293 -// } 293 +
  294 + return BaseRequest.init().service(ApiBaseServiceOpen.class).updateUserFace(params, parts);
  295 +// ApiBaseRequest.subscribe(ApiBaseRequest.service(ApiBaseServiceOpen.class).updateUserFace(params, parts), subscriber);
  296 +// return ApiBaseRequest.service(ApiBaseServiceOpen.class, service -> service.updateUserFace(params, parts)).subscribe(context, callback);
  297 + }
294 298
295 private static RequestBody getRequestString(String value) { 299 private static RequestBody getRequestString(String value) {
296 RequestBody requestString = RequestBody.create(MediaType.parse("text/plain"), value); 300 RequestBody requestString = RequestBody.create(MediaType.parse("text/plain"), value);
cloud/user/src/main/java/com/cnlive/strike/user/auth/UserService.java
@@ -13,7 +13,7 @@ import com.cnlive.core.libs.base.util.SharedPreferencesHelper; @@ -13,7 +13,7 @@ import com.cnlive.core.libs.base.util.SharedPreferencesHelper;
13 import com.cnlive.strike.user.R; 13 import com.cnlive.strike.user.R;
14 import com.cnlive.strike.user.model.CNLiveUserInfo; 14 import com.cnlive.strike.user.model.CNLiveUserInfo;
15 import com.cnlive.strike.user.model.CNLiveUserInfoExt; 15 import com.cnlive.strike.user.model.CNLiveUserInfoExt;
16 -import com.cnlive.strike.user.network.model.UserData; 16 +import com.cnlive.core.network.UserData;
17 import com.google.gson.Gson; 17 import com.google.gson.Gson;
18 18
19 import java.util.HashMap; 19 import java.util.HashMap;
cloud/user/src/main/java/com/cnlive/strike/user/frame/data/LoginData.java deleted 100644 → 0
1 -package com.cnlive.strike.user.frame.data;  
2 -  
3 -import androidx.databinding.BaseObservable;  
4 -import androidx.databinding.Bindable;  
5 -  
6 -import com.cnlive.core.network.HttpConn;  
7 -import com.cnlive.core.network.NetCallBack;  
8 -import com.cnlive.strike.user.BR;  
9 -  
10 -import static android.view.View.GONE;  
11 -import static android.view.View.VISIBLE;  
12 -  
13 -/**  
14 - * Created by xiansong on 2018/1/2.  
15 - */  
16 -@Deprecated  
17 -public class LoginData extends BaseObservable implements NetCallBack {  
18 - private String name = "";  
19 - private String password = "";  
20 - private int loadVisibility = GONE;  
21 -  
22 - @Bindable  
23 - public String getName() {  
24 - return name;  
25 - }  
26 -  
27 - public void setName(String name) {  
28 - this.name = name;  
29 - notifyPropertyChanged(BR.name);  
30 - }  
31 -  
32 - @Bindable  
33 - public String getPassword() {  
34 - return password;  
35 - }  
36 -  
37 - public void setPassword(String password) {  
38 - this.password = password;  
39 - notifyPropertyChanged(BR.password);  
40 - }  
41 -  
42 - @Bindable  
43 - public int getLoadVisibility() {  
44 - return loadVisibility;  
45 - }  
46 -  
47 - public void setLoadVisibility(int loadVisibility) {  
48 - this.loadVisibility = loadVisibility;  
49 - notifyPropertyChanged(BR.loadVisibility);  
50 - }  
51 -  
52 -// @Override  
53 -// public void onState(int state) {  
54 -// loadVisibility = state == Config.STATE_LOAD ? VISIBLE : GONE;  
55 -// }  
56 -  
57 - @Override  
58 - public void onRequestState(int state) {  
59 - loadVisibility = state == HttpConn.ON_START ? VISIBLE : GONE;  
60 - }  
61 -  
62 - @Override  
63 - public void onSuccess(Object data) {  
64 -  
65 - }  
66 -  
67 - @Override  
68 - public void onFailure(String errCode, String errMsg) {  
69 -  
70 - }  
71 -}  
cloud/user/src/main/java/com/cnlive/strike/user/frame/presenter/FirstLoginPresenter.java
@@ -11,11 +11,15 @@ import com.cnlive.strike.user.R; @@ -11,11 +11,15 @@ import com.cnlive.strike.user.R;
11 import com.cnlive.strike.user.UserUtilAction; 11 import com.cnlive.strike.user.UserUtilAction;
12 import com.cnlive.strike.user.auth.UserService; 12 import com.cnlive.strike.user.auth.UserService;
13 import com.cnlive.strike.user.frame.view.FirstLoginView; 13 import com.cnlive.strike.user.frame.view.FirstLoginView;
14 -import com.cnlive.strike.user.network.model.UserData; 14 +import com.cnlive.core.network.FaceData;
  15 +import com.cnlive.core.network.TokenData;
  16 +import com.cnlive.core.network.UserData;
  17 +import com.cnlive.strike.user.router.user.UserOfflineUtil;
15 18
16 import java.io.File; 19 import java.io.File;
17 20
18 import io.reactivex.ObservableSource; 21 import io.reactivex.ObservableSource;
  22 +import io.reactivex.disposables.Disposable;
19 import io.reactivex.functions.Function; 23 import io.reactivex.functions.Function;
20 24
21 25
@@ -24,6 +28,7 @@ import io.reactivex.functions.Function; @@ -24,6 +28,7 @@ import io.reactivex.functions.Function;
24 */ 28 */
25 29
26 public class FirstLoginPresenter extends BasePresenter<FirstLoginView> { 30 public class FirstLoginPresenter extends BasePresenter<FirstLoginView> {
  31 + private Disposable updateFaceEvent;
27 32
28 public void loadUserInfo(Context context) { 33 public void loadUserInfo(Context context) {
29 UserService userService = UserService.getInstance(context); 34 UserService userService = UserService.getInstance(context);
@@ -112,52 +117,60 @@ public class FirstLoginPresenter extends BasePresenter&lt;FirstLoginView&gt; { @@ -112,52 +117,60 @@ public class FirstLoginPresenter extends BasePresenter&lt;FirstLoginView&gt; {
112 ); 117 );
113 } 118 }
114 119
115 -// public void uploadFile(Context context, String filePath) {  
116 -// if (updateFaceEvent != null) updateFaceEvent.cencel();  
117 -// if (getView() == null) return;  
118 -// getView().showProgress(R.string.upload_image_dialog);  
119 -// File file = new File(filePath);  
120 -// UserService userService = UserService.getInstance(context);  
121 -// if (file.exists()) {  
122 -//  
123 -// updateFaceEvent = Logic.create()  
124 -// .action(UserUtilAction.accessToken(context))  
125 -// .action((BaseInfo<TokenData> data, DataCallback<BaseInfo<FaceData>> callback) -> {  
126 -// UserUtilAction.updateUserFace(context, UserService.getUid(context), file, userService.getAppAccount().getToken(), data.getData().getAccess_token(), callback);  
127 -// return null;  
128 -// })  
129 -// .<BaseInfo<FaceData>>event()  
130 -// .setStateCallback(state -> {  
131 -// if (getView() == null) return;  
132 -// if (state == STATE_LOAD) {  
133 -//  
134 -// } else if (state == STATE_IDLE) {  
135 -// getView().hideProgress();  
136 -// }  
137 -// })  
138 -// .setFailureCallback((state, message) -> {  
139 -// if (getView() == null) return;  
140 -// if (state == 8 || state == 9) {  
141 -//// UserOfflineUtil.userInvalid(context);  
142 -// HelperUtil.userInvalid(context);  
143 -// } else if (state == UserUtilAction.TOKEN_ERROR_CODE) {  
144 -// getView().showTokenErrorDialog();  
145 -// } else {  
146 -// getView().showToast(message);  
147 -// }  
148 -// })  
149 -// .setSuccessCallback(data -> {  
150 -// HelperUtil.modifyUserImage(context, data.getData().getFaceUrl());  
151 -//// LoginManager.modifyUserImage( UserService.getUid(context), data.getData().getFaceUrl());  
152 -// userService.setUserFaceUrl(data.getData().getFaceUrl(), data.getData().getBigFaceUrl());  
153 -// if (getView() == null) return;  
154 -// getView().photoChange(data.getData().getFaceUrl());  
155 -// })  
156 -// .start();  
157 -// } else {  
158 -// if (getView() != null) getView().showToast("文件不存在");  
159 -// }  
160 -// } 120 + public void uploadFile(Context context, String filePath) {
  121 + if (updateFaceEvent != null) {
  122 + updateFaceEvent.dispose();
  123 + updateFaceEvent = null;
  124 + }
  125 + ifViewAttached(view -> view.showProgress(R.string.upload_image_dialog));
  126 + File file = new File(filePath);
  127 + UserService userService = UserService.getInstance(context);
  128 + if (file.exists()) {
  129 + updateFaceEvent =
  130 + HttpConn.action(
  131 + UserUtilAction.accessToken(context)
  132 + .concatMap(new Function<BaseResult<TokenData>, ObservableSource<BaseResult<FaceData>>>() {
  133 + @Override
  134 + public ObservableSource<BaseResult<FaceData>> apply(BaseResult<TokenData> tokenDataBaseResult) throws Exception {
  135 + if (tokenDataBaseResult.isSuccess()) {
  136 + return UserUtilAction.updateUserFace(context, UserService.getUid(context), file, userService.getAppAccount().getToken(), tokenDataBaseResult.getData().getAccess_token());
  137 + }
  138 + return HttpConn.error(tokenDataBaseResult);
  139 + }
  140 + }), new NetCallBack<BaseResult<FaceData>>() {
  141 + @Override
  142 + public void onRequestState(int state) {
  143 + if (HttpConn.ON_END == state) {
  144 + ifViewAttached(view -> view.hideProgress());
  145 + }
  146 + }
  147 +
  148 + @Override
  149 + public void onSuccess(BaseResult<FaceData> data) {
  150 +// HelperUtil.modifyUserImage(context, data.getData().getFaceUrl());
  151 +// LoginManager.modifyUserImage( UserService.getUid(context), data.getData().getFaceUrl());
  152 + userService.setUserFaceUrl(data.getData().getFaceUrl(), data.getData().getBigFaceUrl());
  153 + ifViewAttached(view -> view.photoChange(data.getData().getFaceUrl()));
  154 + }
  155 +
  156 + @Override
  157 + public void onFailure(String errCode, String errMsg) {
  158 + if ("8".equals(errCode) || "9".equals(errCode)) {
  159 + UserOfflineUtil.userInvalid(context);
  160 +// HelperUtil.userInvalid(context);
  161 + } else if (UserUtilAction.TOKEN_ERROR_CODE.equals(errCode)) {
  162 + ifViewAttached(view -> view.showTokenErrorDialog());
  163 + } else {
  164 + ifViewAttached(view -> view.showToast(errMsg));
  165 + }
  166 + }
  167 + }
  168 + );
  169 +
  170 + } else {
  171 + ifViewAttached(view -> view.showToast("文件不存在"));
  172 + }
  173 + }
161 174
162 } 175 }
163 176
cloud/user/src/main/java/com/cnlive/strike/user/frame/presenter/QuickLoginPresenter.java
@@ -39,19 +39,18 @@ import io.reactivex.disposables.Disposable; @@ -39,19 +39,18 @@ import io.reactivex.disposables.Disposable;
39 public class QuickLoginPresenter extends BasePresenter<QuickLoginView> { 39 public class QuickLoginPresenter extends BasePresenter<QuickLoginView> {
40 private TimerUtil timerUtil; //计时工具类 40 private TimerUtil timerUtil; //计时工具类
41 41
42 - // private Event<CNLiveUserInfo> event; 42 + private Disposable event;
43 private Disposable sendMsgBefQuickLogin; 43 private Disposable sendMsgBefQuickLogin;
44 // private Event otherEvent; 44 // private Event otherEvent;
45 45
46 public void deleteUserInfo(Context context, String userName) { 46 public void deleteUserInfo(Context context, String userName) {
47 UserService.getInstance(context).removeUser(userName, future -> { 47 UserService.getInstance(context).removeUser(userName, future -> {
48 - if (getView() == null) return;  
49 //获取已登录用户列表 48 //获取已登录用户列表
50 Account[] accounts = UserService.getInstance(context).getUserList(); 49 Account[] accounts = UserService.getInstance(context).getUserList();
51 //倒序输出最近登录用户 50 //倒序输出最近登录用户
52 51
53 Collections.reverse(Arrays.asList(accounts)); 52 Collections.reverse(Arrays.asList(accounts));
54 - getView().uploadListData(accounts); 53 + ifViewAttached(view -> view.uploadListData(accounts));
55 }); 54 });
56 } 55 }
57 56
@@ -67,10 +66,10 @@ public class QuickLoginPresenter extends BasePresenter&lt;QuickLoginView&gt; { @@ -67,10 +66,10 @@ public class QuickLoginPresenter extends BasePresenter&lt;QuickLoginView&gt; {
67 String name = account == null ? "" : account.name; 66 String name = account == null ? "" : account.name;
68 //页面填充数据 67 //页面填充数据
69 if (!TextUtils.isEmpty(name)) { 68 if (!TextUtils.isEmpty(name)) {
70 - getView().uploadInputData(name); 69 + ifViewAttached(view -> view.uploadInputData(name));
71 } 70 }
72 if (null != accounts) { 71 if (null != accounts) {
73 - getView().uploadListData(accounts); 72 + ifViewAttached(view -> view.uploadListData(accounts));
74 } 73 }
75 } 74 }
76 75
@@ -84,29 +83,28 @@ public class QuickLoginPresenter extends BasePresenter&lt;QuickLoginView&gt; { @@ -84,29 +83,28 @@ public class QuickLoginPresenter extends BasePresenter&lt;QuickLoginView&gt; {
84 timerUtil.setTimerLiener(new TimerUtil.TimeListener() { 83 timerUtil.setTimerLiener(new TimerUtil.TimeListener() {
85 @Override 84 @Override
86 public void onFinish() { 85 public void onFinish() {
87 - if (getView() != null) getView().onTimerFinish(); 86 + ifViewAttached(view -> view.onTimerFinish());
88 } 87 }
89 88
90 @Override 89 @Override
91 public void onInterval(long remainTime) { 90 public void onInterval(long remainTime) {
92 - if (getView() != null) getView().onTimerInterval(remainTime / 1000); 91 + ifViewAttached(view -> view.onTimerInterval(remainTime / 1000));
93 } 92 }
94 }); 93 });
95 } 94 }
96 95
97 public void sendCode(Context context, String phone, String countryCode) { 96 public void sendCode(Context context, String phone, String countryCode) {
98 - if (getView() == null) return;  
99 if (TimeEvent.debounce(2_000)) return; 97 if (TimeEvent.debounce(2_000)) return;
100 if (TextUtils.isEmpty(phone)) { 98 if (TextUtils.isEmpty(phone)) {
101 - getView().showToast(context.getString(R.string.user_toast_quick_login_empty_phone)); 99 + ifViewAttached(view -> view.showToast(context.getString(R.string.user_toast_quick_login_empty_phone)));
102 return; 100 return;
103 } 101 }
104 if ("86".equals(countryCode) && !RegexUtils.isMobileSimple(phone)) { 102 if ("86".equals(countryCode) && !RegexUtils.isMobileSimple(phone)) {
105 - getView().showToast(context.getString(R.string.user_toast_quick_login_error_phone)); 103 + ifViewAttached(view -> view.showToast(context.getString(R.string.user_toast_quick_login_error_phone)));
106 return; 104 return;
107 } 105 }
108 if (sendMsgBefQuickLogin != null && !sendMsgBefQuickLogin.isDisposed()) { 106 if (sendMsgBefQuickLogin != null && !sendMsgBefQuickLogin.isDisposed()) {
109 - getView().showToast("处理中请稍后..."); 107 + ifViewAttached(view -> view.showToast("处理中请稍后..."));
110 } else { 108 } else {
111 sendMsgBefQuickLogin = HttpConn.action(UserUtilAction.sendMsgBefQuickLoginAction(context, phone, countryCode), new NetCallBack<BaseResult>() { 109 sendMsgBefQuickLogin = HttpConn.action(UserUtilAction.sendMsgBefQuickLoginAction(context, phone, countryCode), new NetCallBack<BaseResult>() {
112 @Override 110 @Override
@@ -137,7 +135,7 @@ public class QuickLoginPresenter extends BasePresenter&lt;QuickLoginView&gt; { @@ -137,7 +135,7 @@ public class QuickLoginPresenter extends BasePresenter&lt;QuickLoginView&gt; {
137 } else { 135 } else {
138 context.isLogin = true; 136 context.isLogin = true;
139 // UserAction.mobileLogin(context.getActivity(), data.getPhone(), data.getCode(), countryCode, initLoginEvent(context, true)); 137 // UserAction.mobileLogin(context.getActivity(), data.getPhone(), data.getCode(), countryCode, initLoginEvent(context, true));
140 - UserAction.mobileLogin(context.getActivity(), data.getPhone(), data.getCode(), countryCode, new UserAction.CallBack() { 138 + event = UserAction.mobileLogin(context.getActivity(), data.getPhone(), data.getCode(), countryCode, new UserAction.CallBack() {
141 @Override 139 @Override
142 public void callback(int state, String msg, Object object) { 140 public void callback(int state, String msg, Object object) {
143 initLoginEvent(context, state, msg, true, null); 141 initLoginEvent(context, state, msg, true, null);
@@ -229,7 +227,7 @@ public class QuickLoginPresenter extends BasePresenter&lt;QuickLoginView&gt; { @@ -229,7 +227,7 @@ public class QuickLoginPresenter extends BasePresenter&lt;QuickLoginView&gt; {
229 // } 227 // }
230 228
231 229
232 -// 230 + //
233 // private Event<CNLiveUserInfo> initLoginEvent(QuickLoginFragment context, Boolean retry, OtherUserInfo otherUserInfo) { 231 // private Event<CNLiveUserInfo> initLoginEvent(QuickLoginFragment context, Boolean retry, OtherUserInfo otherUserInfo) {
234 // return event = new Event<CNLiveUserInfo>() 232 // return event = new Event<CNLiveUserInfo>()
235 // .setStateCallback(state -> { 233 // .setStateCallback(state -> {
@@ -304,5 +302,12 @@ public class QuickLoginPresenter extends BasePresenter&lt;QuickLoginView&gt; { @@ -304,5 +302,12 @@ public class QuickLoginPresenter extends BasePresenter&lt;QuickLoginView&gt; {
304 // if (context != null) context.isLogin = false; 302 // if (context != null) context.isLogin = false;
305 // }); 303 // });
306 // } 304 // }
307 - 305 + public void cancelLoad() {
  306 + if (event != null) {
  307 + if (!event.isDisposed()) {
  308 + event.dispose();
  309 + }
  310 + event = null;
  311 + }
  312 + }
308 } 313 }
cloud/user/src/main/java/com/cnlive/strike/user/frame/view/FirstLoginView.java
@@ -63,8 +63,6 @@ public class FirstLoginView extends BaseView { @@ -63,8 +63,6 @@ public class FirstLoginView extends BaseView {
63 successInfo.setTagMsg(fragment.tagMsg); 63 successInfo.setTagMsg(fragment.tagMsg);
64 EventBus.getDefault().post(new UserEventMsg(UserEventMsg.LOGIN_SUCCESS, successInfo)); 64 EventBus.getDefault().post(new UserEventMsg(UserEventMsg.LOGIN_SUCCESS, successInfo));
65 65
66 -  
67 -  
68 // Intent intent = new Intent(getContext(), MainTestActivity.class); 66 // Intent intent = new Intent(getContext(), MainTestActivity.class);
69 // if (!TextUtils.isEmpty(fragment.tagMsg)) 67 // if (!TextUtils.isEmpty(fragment.tagMsg))
70 // intent.putExtra("classifyTagMsg", fragment.tagMsg); 68 // intent.putExtra("classifyTagMsg", fragment.tagMsg);
cloud/user/src/main/java/com/cnlive/strike/user/router/user/UserAction.java
@@ -5,21 +5,17 @@ import android.app.Activity; @@ -5,21 +5,17 @@ import android.app.Activity;
5 import android.content.Context; 5 import android.content.Context;
6 import android.net.Uri; 6 import android.net.Uri;
7 import android.text.TextUtils; 7 import android.text.TextUtils;
8 -import android.util.Log;  
9 8
10 import com.cnlive.core.network.BaseResult; 9 import com.cnlive.core.network.BaseResult;
11 import com.cnlive.core.network.HttpConn; 10 import com.cnlive.core.network.HttpConn;
12 import com.cnlive.core.network.NetCallBack; 11 import com.cnlive.core.network.NetCallBack;
13 -import com.cnlive.core.network.ServerException; 12 +import com.cnlive.core.network.UserData;
14 import com.cnlive.strike.user.UserUtilAction; 13 import com.cnlive.strike.user.UserUtilAction;
15 import com.cnlive.strike.user.auth.UserService; 14 import com.cnlive.strike.user.auth.UserService;
16 import com.cnlive.strike.user.model.CNLiveUserInfo; 15 import com.cnlive.strike.user.model.CNLiveUserInfo;
17 -import com.cnlive.strike.user.network.api.BaseRequest;  
18 -import com.cnlive.strike.user.network.model.UserData;  
19 16
20 import io.reactivex.Observable; 17 import io.reactivex.Observable;
21 -import io.reactivex.ObservableSource;  
22 -import io.reactivex.functions.Function; 18 +import io.reactivex.disposables.Disposable;
23 19
24 20
25 public class UserAction { 21 public class UserAction {
@@ -49,13 +45,13 @@ public class UserAction { @@ -49,13 +45,13 @@ public class UserAction {
49 // .start(event); 45 // .start(event);
50 // } 46 // }
51 47
52 - public static void mobileLogin(Context context, String phone, String code, String countryCode, CallBack callBack) { 48 + public static Disposable mobileLogin(Context context, String phone, String code, String countryCode, CallBack callBack) {
53 // Logic.create() 49 // Logic.create()
54 // .action(UserUtilAction.quickLoginAction(context, phone, code, countryCode)) 50 // .action(UserUtilAction.quickLoginAction(context, phone, code, countryCode))
55 // .action(loginAppAction(context, phone, code)) 51 // .action(loginAppAction(context, phone, code))
56 //// .action(loginIMAction()) 52 //// .action(loginIMAction())
57 // .start(event); 53 // .start(event);
58 - HttpConn.action( 54 + return HttpConn.action(
59 UserUtilAction.quickLoginAction(context, phone, code, countryCode) 55 UserUtilAction.quickLoginAction(context, phone, code, countryCode)
60 , new NetCallBack<BaseResult<UserData>>() { 56 , new NetCallBack<BaseResult<UserData>>() {
61 @Override 57 @Override
@@ -86,7 +82,7 @@ public class UserAction { @@ -86,7 +82,7 @@ public class UserAction {
86 if (null != callBack) { 82 if (null != callBack) {
87 callBack.callback(-5, "获取账户信息失败 请重试.", null); 83 callBack.callback(-5, "获取账户信息失败 请重试.", null);
88 } 84 }
89 - } else if (TextUtils.isEmpty(data.getData().getMobile())) { 85 + } else if (TextUtils.isEmpty(data.getData().getMobile())) {
90 callBack.callback(-5, "绑定手机号已失效..", null); 86 callBack.callback(-5, "绑定手机号已失效..", null);
91 } else { 87 } else {
92 //更新登录用户信息 88 //更新登录用户信息
cloud/user/src/main/java/com/cnlive/strike/user/router/user/UserOfflineUtil.java
@@ -5,9 +5,14 @@ import android.content.Context; @@ -5,9 +5,14 @@ import android.content.Context;
5 5
6 import androidx.appcompat.app.AppCompatActivity; 6 import androidx.appcompat.app.AppCompatActivity;
7 7
  8 +import com.cnlive.core.libs.base.ui.widget.BottomSheet;
8 import com.cnlive.core.libs.base.util.AlertUtil; 9 import com.cnlive.core.libs.base.util.AlertUtil;
  10 +import com.cnlive.core.libs.base.util.AppManager;
9 import com.cnlive.strike.user.auth.UserService; 11 import com.cnlive.strike.user.auth.UserService;
  12 +import com.cnlive.strike.user.ui.activity.LoginActivity;
10 import com.kongzue.dialog.interfaces.OnMenuItemClickListener; 13 import com.kongzue.dialog.interfaces.OnMenuItemClickListener;
  14 +import com.kongzue.dialog.util.DialogSettings;
  15 +import com.kongzue.dialog.util.TextInfo;
11 import com.kongzue.dialog.v3.BottomMenu; 16 import com.kongzue.dialog.v3.BottomMenu;
12 17
13 import org.greenrobot.eventbus.EventBus; 18 import org.greenrobot.eventbus.EventBus;
@@ -37,40 +42,44 @@ public class UserOfflineUtil { @@ -37,40 +42,44 @@ public class UserOfflineUtil {
37 } 42 }
38 43
39 public static void userInvalid(Context context) { 44 public static void userInvalid(Context context) {
40 - AlertUtil.showDeftToast(context, "用户 已失效."); 45 + AlertUtil.showDeftToast(context, "用户已失效.");
41 appLogout(context); 46 appLogout(context);
42 } 47 }
43 48
44 //todo BottomSheet 49 //todo BottomSheet
45 public static void logout(Context context) { 50 public static void logout(Context context) {
46 -  
47 - BottomMenu.show((AppCompatActivity) context, new String[]{"菜单1", "菜单2", "菜单3"}, new OnMenuItemClickListener() {  
48 - @Override  
49 - public void onClick(String text, int index) {  
50 - //返回参数 text 即菜单名称,index 即菜单索引  
51 - }  
52 - });  
53 -// new BottomSheet.BottomListSheetBuilder(context)  
54 -// .addItem("退出登录", "", true)  
55 -// .addItem("取消")  
56 -// .setOnSheetItemClickListener((dialog, itemView, position, tag) -> {  
57 -// switch (position) {  
58 -// case 0:  
59 -// appLogout(context);  
60 -// break;  
61 -// }  
62 -// dialog.dismiss(false);  
63 -// }).build().show(); 51 + DialogSettings.style = (DialogSettings.STYLE.STYLE_IOS);
  52 + TextInfo textInfo = new TextInfo();
  53 + textInfo.setFontSize(15);
  54 + DialogSettings.menuTextInfo = textInfo;
  55 +// BottomMenu.show((AppCompatActivity) context, new String[]{"退出登录"}, new OnMenuItemClickListener() {
  56 +// @Override
  57 +// public void onClick(String text, int index) {
  58 +// //返回参数 text 即菜单名称,index 即菜单索引
  59 +// }
  60 +// }).setCancelable(false);
  61 + new BottomSheet.BottomListSheetBuilder(context)
  62 + .addItem("退出登录", "", true)
  63 + .addItem("取消")
  64 + .setOnSheetItemClickListener((dialog, itemView, position, tag) -> {
  65 + switch (position) {
  66 + case 0:
  67 + appLogout(context);
  68 + break;
  69 + }
  70 + dialog.dismiss(false);
  71 + }).build().show();
64 } 72 }
65 73
66 public static void appLogout(Context context) { 74 public static void appLogout(Context context) {
67 String uid = UserService.getUid(context); 75 String uid = UserService.getUid(context);
68 UserService.getInstance(context).logoutAppAccount(); 76 UserService.getInstance(context).logoutAppAccount();
69 //退出登录 77 //退出登录
70 - 78 + AppManager.getInstance().killAllActivity();
  79 + LoginActivity.start(context);
71 // LoginManager.logout(uid, null, context); 80 // LoginManager.logout(uid, null, context);
72 // if (ActivityLifecycle.isActive()) { 81 // if (ActivityLifecycle.isActive()) {
73 -// LoginActivity.start(context); 82 +
74 // } else { 83 // } else {
75 // Log.e("FinishAllActivity", "FinishAllActivity-----logout"); 84 // Log.e("FinishAllActivity", "FinishAllActivity-----logout");
76 // FinishAllActivity.finish(context); 85 // FinishAllActivity.finish(context);
cloud/user/src/main/java/com/cnlive/strike/user/ui/activity/LoginActivity.java
@@ -19,8 +19,11 @@ import com.cnlive.strike.user.ui.fragment.QuickLoginFragment; @@ -19,8 +19,11 @@ import com.cnlive.strike.user.ui.fragment.QuickLoginFragment;
19 * @author Lynn 19 * @author Lynn
20 * @date 2017/12/22 20 * @date 2017/12/22
21 */ 21 */
22 -@Route(path = "/cnmain/LoginActivity") 22 +//@Route(path = "/cnmain/LoginActivity")
  23 +@Route(path = LoginActivity.PATH)
23 public class LoginActivity extends BaseActivity { 24 public class LoginActivity extends BaseActivity {
  25 + public static final String PATH = "/cloud/user/ui/activity/login";
  26 +
24 public static String FROM_TOKEN_ERROR = "from_token_error"; 27 public static String FROM_TOKEN_ERROR = "from_token_error";
25 public static String TAG_MSG = "tagMsg"; 28 public static String TAG_MSG = "tagMsg";
26 public static String TAG_SHARE = "tagValue"; 29 public static String TAG_SHARE = "tagValue";
cloud/user/src/main/java/com/cnlive/strike/user/ui/fragment/FirstLoginFragment.java
@@ -5,6 +5,7 @@ import android.app.Activity; @@ -5,6 +5,7 @@ import android.app.Activity;
5 import android.app.Dialog; 5 import android.app.Dialog;
6 import android.app.ProgressDialog; 6 import android.app.ProgressDialog;
7 import android.content.Intent; 7 import android.content.Intent;
  8 +import android.os.Environment;
8 import android.text.Editable; 9 import android.text.Editable;
9 import android.text.TextUtils; 10 import android.text.TextUtils;
10 import android.text.TextWatcher; 11 import android.text.TextWatcher;
@@ -14,9 +15,13 @@ import androidx.annotation.NonNull; @@ -14,9 +15,13 @@ import androidx.annotation.NonNull;
14 import androidx.appcompat.app.AppCompatActivity; 15 import androidx.appcompat.app.AppCompatActivity;
15 16
16 import com.cnlive.core.libs.base.frame.fragment.BaseFragment; 17 import com.cnlive.core.libs.base.frame.fragment.BaseFragment;
  18 +import com.cnlive.core.libs.base.interfaces.OnPermissionResponseListener;
17 import com.cnlive.core.libs.base.util.AlertUtil; 19 import com.cnlive.core.libs.base.util.AlertUtil;
18 import com.cnlive.core.libs.base.util.GlideUtil; 20 import com.cnlive.core.libs.base.util.GlideUtil;
19 import com.cnlive.core.libs.base.util.StatusBarConfig; 21 import com.cnlive.core.libs.base.util.StatusBarConfig;
  22 +import com.cnlive.media.picker.ImagePicker;
  23 +import com.cnlive.media.picker.PickerConfig;
  24 +import com.cnlive.media.picker.entity.Media;
20 import com.cnlive.strike.user.R; 25 import com.cnlive.strike.user.R;
21 import com.cnlive.strike.user.auth.UserService; 26 import com.cnlive.strike.user.auth.UserService;
22 import com.cnlive.strike.user.databinding.FragmentFirstLoginBinding; 27 import com.cnlive.strike.user.databinding.FragmentFirstLoginBinding;
@@ -28,6 +33,10 @@ import com.cnlive.strike.user.router.user.UserOfflineUtil; @@ -28,6 +33,10 @@ import com.cnlive.strike.user.router.user.UserOfflineUtil;
28 import com.cnlive.strike.user.ui.activity.FirstLoginActivity; 33 import com.cnlive.strike.user.ui.activity.FirstLoginActivity;
29 import com.cnlive.strike.user.ui.activity.LoginActivity; 34 import com.cnlive.strike.user.ui.activity.LoginActivity;
30 35
  36 +import java.util.List;
  37 +
  38 +import static com.cnlive.media.picker.ui.PickerActivity.REQUEST_CODE_PERMISSION_CAMERA;
  39 +
31 40
32 /** 41 /**
33 * Created by xiansong on 2018/1/19. 42 * Created by xiansong on 2018/1/19.
@@ -128,31 +137,37 @@ public class FirstLoginFragment extends BaseFragment&lt;FirstLoginView, FirstLoginP @@ -128,31 +137,37 @@ public class FirstLoginFragment extends BaseFragment&lt;FirstLoginView, FirstLoginP
128 137
129 138
130 public void selectPhoto(boolean fromResult) { 139 public void selectPhoto(boolean fromResult) {
131 -// boolean hasPermission = fromResult ? AppUtil.checkPermissions(getActivity(), PERMISSION) : PermissionChecker.checkPermissions(getActivity()  
132 -// , PERMISSION, REQUEST_CODE_PERMISSION_CAMERA, com.cnlive.media.picker.R.string.dialog_imagepicker_permission_sdcard_message);  
133 -//  
134 -// if (hasPermission) {  
135 -// ImagePicker imagePicker = new ImagePicker.Builder()  
136 -// //最大选择图片数目,默认40张  
137 -// .maxNum(1)  
138 -// .setSelectGif(false)  
139 -// //是否需要相机(默认false)  
140 -// .needCamera(true)  
141 -// //选择模式(默认PICKER_IMAGE_VIDEO) PICKER_IMAGE-->图片 PICKER_VIDEO-->视频 PICKER_IMAGE_VIDEO-->图片&视频  
142 -// .selectMode(PickerConfig.PICKER_IMAGE)  
143 -// //拍照或录像存储位置 默认Environment.getExternalStorageDirectory().getPath() + File.separator + "JCamera"  
144 -// .cachePath(Environment.getExternalStorageDirectory() + "/strike/file/")  
145 -// //是否为发朋友圈模式(默认false) true-->图片与视频不能同时选择  
146 -// .isFriendCircle(false)  
147 -// //裁剪 只有在单选模式下才可以使用  
148 -// .doCrop(1, 1, 300, 300)  
149 -// //是否开启单选模式(默认false)  
150 -// .isSinglePick(true)  
151 -// .builder();  
152 -//  
153 -// //跳转到图片选择页面 activity 请求码 结果码  
154 -// imagePicker.start(getActivity(), PickerConfig.PICKER_IMAGE, PickerConfig.DEFAULT_RESULT_CODE);  
155 -// } 140 + requestPermission(REQUEST_CODE_PERMISSION_CAMERA,
  141 + R.string.dialog_imagepicker_permission_sdcard_message,
  142 + PERMISSION, new OnPermissionResponseListener() {
  143 + @Override
  144 + public void onSuccess(String[] permissions) {
  145 + ImagePicker imagePicker = new ImagePicker.Builder()
  146 + //最大选择图片数目,默认40张
  147 + .maxNum(1)
  148 + .setSelectGif(false)
  149 + //是否需要相机(默认false)
  150 + .needCamera(true)
  151 + //选择模式(默认PICKER_IMAGE_VIDEO) PICKER_IMAGE-->图片 PICKER_VIDEO-->视频 PICKER_IMAGE_VIDEO-->图片&视频
  152 + .selectMode(PickerConfig.PICKER_IMAGE)
  153 + //拍照或录像存储位置 默认Environment.getExternalStorageDirectory().getPath() + File.separator + "JCamera"
  154 + .cachePath(Environment.getExternalStorageDirectory() + "/strike/file/")
  155 + //是否为发朋友圈模式(默认false) true-->图片与视频不能同时选择
  156 + .isFriendCircle(false)
  157 + //裁剪 只有在单选模式下才可以使用
  158 + .doCrop(1, 1, 300, 300)
  159 + //是否开启单选模式(默认false)
  160 + .isSinglePick(true)
  161 + .builder();
  162 + //跳转到图片选择页面 activity 请求码 结果码
  163 + imagePicker.start(getActivity(), PickerConfig.PICKER_IMAGE, PickerConfig.DEFAULT_RESULT_CODE);
  164 + }
  165 +
  166 + @Override
  167 + public void onFail() {
  168 +
  169 + }
  170 + });
156 171
157 } 172 }
158 173
@@ -163,31 +178,17 @@ public class FirstLoginFragment extends BaseFragment&lt;FirstLoginView, FirstLoginP @@ -163,31 +178,17 @@ public class FirstLoginFragment extends BaseFragment&lt;FirstLoginView, FirstLoginP
163 if (tokenErrorDialog != null) tokenErrorDialog.dismiss(); 178 if (tokenErrorDialog != null) tokenErrorDialog.dismiss();
164 } 179 }
165 180
166 - @Override  
167 - public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {  
168 - super.onRequestPermissionsResult(requestCode, permissions, grantResults);  
169 - Activity activity = getActivity();  
170 - if (activity == null) return;  
171 -// if (requestCode == REQUEST_CODE_PERMISSION_CAMERA) {  
172 -// boolean hasPermission = PermissionChecker.onRequestPermissionsResult(  
173 -// activity, requestCode, permissions, grantResults, false,  
174 -// com.cnlive.media.picker.R.string.dialog_imagepicker_permission_sdcard_message)[0];  
175 -// if (hasPermission) {  
176 -// selectPhoto(true);  
177 -// }  
178 -// }  
179 - }  
180 181
181 @Override 182 @Override
182 public void onActivityResult(int requestCode, int resultCode, Intent data) { 183 public void onActivityResult(int requestCode, int resultCode, Intent data) {
183 super.onActivityResult(requestCode, resultCode, data); 184 super.onActivityResult(requestCode, resultCode, data);
184 -// if (resultCode == PickerConfig.DEFAULT_RESULT_CODE) {  
185 -// List<Media> list = data.getParcelableArrayListExtra(PickerConfig.EXTRA_RESULT);  
186 -// if (list == null) return;  
187 -// if (getPresenter() == null) return;  
188 -// if (list.size() > 0 && list.get(0) != null && !TextUtils.isEmpty(list.get(0).path))  
189 -// getPresenter().uploadFile(FirstLoginFragment.this.getActivity(), list.get(0).path);  
190 -//  
191 -// } 185 + if (resultCode == PickerConfig.DEFAULT_RESULT_CODE) {
  186 + List<Media> list = data.getParcelableArrayListExtra(PickerConfig.EXTRA_RESULT);
  187 + if (list == null) return;
  188 + if (getPresenter() == null) return;
  189 + if (list.size() > 0 && list.get(0) != null && !TextUtils.isEmpty(list.get(0).path))
  190 + getPresenter().uploadFile(FirstLoginFragment.this.getActivity(), list.get(0).path);
  191 +
  192 + }
192 } 193 }
193 } 194 }
cloud/user/src/main/java/com/cnlive/strike/user/ui/fragment/QuickLoginFragment.java
@@ -114,7 +114,7 @@ public class QuickLoginFragment extends BaseFragment&lt;QuickLoginView, QuickLoginP @@ -114,7 +114,7 @@ public class QuickLoginFragment extends BaseFragment&lt;QuickLoginView, QuickLoginP
114 mProgressDialog.setMessage(getResources().getString(R.string.login_dialog)); 114 mProgressDialog.setMessage(getResources().getString(R.string.login_dialog));
115 mProgressDialog.setCanceledOnTouchOutside(false); 115 mProgressDialog.setCanceledOnTouchOutside(false);
116 mProgressDialog.setOnCancelListener(dialog -> { 116 mProgressDialog.setOnCancelListener(dialog -> {
117 -// getPresenter().cancelLoad(); 117 + getPresenter().cancelLoad();
118 }); 118 });
119 getMvpView().setAgreementText(); 119 getMvpView().setAgreementText();
120 binding.setClickListener(v -> onClick(v.getId())); 120 binding.setClickListener(v -> onClick(v.getId()));
config.gradle
1 ext { 1 ext {
2 - mixedUrl = "http://android.nexus.cnlive.com/repository/cnlive-mixed/"  
3 - mavenUsername = "developer"  
4 - mavenPassword = "android_2019" 2 + //Nexus 访问账号
  3 + nexusId = "developer"
  4 + nexusPw = "android_2019"
5 5
6 //Nexus 发布配置 6 //Nexus 发布配置
7 maven = [ 7 maven = [
@@ -25,7 +25,7 @@ ext { @@ -25,7 +25,7 @@ ext {
25 ] 25 ]
26 26
27 androidx = [ 27 androidx = [
28 - appcompat : "androidx.appcompat:appcompat:1.1.0+", 28 + appcompat : "androidx.appcompat:appcompat:1.1.0",
29 constraintlayout: "androidx.constraintlayout:constraintlayout:1.1.3", 29 constraintlayout: "androidx.constraintlayout:constraintlayout:1.1.3",
30 multidex : "androidx.multidex:multidex:2.0.1" 30 multidex : "androidx.multidex:multidex:2.0.1"
31 ] 31 ]
@@ -46,17 +46,34 @@ ext { @@ -46,17 +46,34 @@ ext {
46 espresso: 'androidx.test.espresso:espresso-core:3.2.0' 46 espresso: 'androidx.test.espresso:espresso-core:3.2.0'
47 ] 47 ]
48 48
  49 + //Maven Base库配置
  50 + moudle_cnlive_base = [
  51 + //编译方式
  52 + debug : false,
  53 + //版本号
  54 + version: "0.0.2",
  55 + //Lib库前缀
  56 + packeg : "com.cnlive.core",
  57 + //Lib库名称
  58 + name : "base"
  59 + ]
49 library = [ 60 library = [
  61 +
  62 + //fragment滑动返回( https://github.com/YoKeyword/Fragmentation ,源码导入修改)
  63 + fragmentation_swipeback : 'me.yokeyword:fragmentationx-swipeback:1.0.2',
  64 + //对fragment进行管理( https://github.com/YoKeyword/Fragmentation ,源码导入修改)
  65 + fragmentationx : 'me.yokeyword:fragmentationx:1.0.2',
  66 + //log日志
50 logger : 'com.orhanobut:logger:2.2.0', 67 logger : 'com.orhanobut:logger:2.2.0',
51 -// //空祖对话框 https://github.com/kongzue/DialogV3  
52 -// kongzueDailog : 'com.kongzue.dialog_v3x:dialog:3.1.6', 68 + //空祖对话框 https://github.com/kongzue/DialogV3 (源码导入,修改)
  69 + kongzueDailog : 'com.kongzue.dialog_v3x:dialog:3.1.6',
53 //视讯云加密 70 //视讯云加密
54 libCnencipher : 'com.cnlive:lib-cnencipher:1.1.1', 71 libCnencipher : 'com.cnlive:lib-cnencipher:1.1.1',
55 //视频库 72 //视频库
56 libVideoQiniu : 'com.cnlive.libs:video_qiniu:1.0.6', 73 libVideoQiniu : 'com.cnlive.libs:video_qiniu:1.0.6',
57 //视讯云播放器 74 //视讯云播放器
58 libCnVideo : 'com.cnlive:lib_cnvideo2.0:3.3.11', 75 libCnVideo : 'com.cnlive:lib_cnvideo2.0:3.3.11',
59 - //权限 76 +// //权限
60 easypermissions : 'pub.devrel:easypermissions:1.0.0', 77 easypermissions : 'pub.devrel:easypermissions:1.0.0',
61 //MVP 78 //MVP
62 mvp : 'com.hannesdorfmann.mosby3:mvp:3.0.4', 79 mvp : 'com.hannesdorfmann.mosby3:mvp:3.0.4',
@@ -96,14 +113,9 @@ ext { @@ -96,14 +113,9 @@ ext {
96 cardviewV7 : 'com.android.support:cardview-v7:28.0.0', 113 cardviewV7 : 'com.android.support:cardview-v7:28.0.0',
97 dataBinding : 'com.android.databinding.library:3.5.1' 114 dataBinding : 'com.android.databinding.library:3.5.1'
98 ] 115 ]
99 -// library_jar = [  
100 -// pinyin4j: ('libs/pinyin4j-2.5.0.jar')  
101 -// ]  
102 //基础三方库 116 //基础三方库
103 base_librarys = [ 117 base_librarys = [
104 library.logger, 118 library.logger,
105 - //对话框  
106 -// library.kongzueDailog,  
107 //视讯云加密库 119 //视讯云加密库
108 library.libCnencipher, 120 library.libCnencipher,
109 //视频库 121 //视频库
@@ -125,14 +137,6 @@ ext { @@ -125,14 +137,6 @@ ext {
125 //图片加载Glide 137 //图片加载Glide
126 glide.api, 138 glide.api,
127 glide.transformations, 139 glide.transformations,
128 - //兼容旧版  
129 -// library.supportV4,  
130 -// library.appcompatV7,  
131 -// library.design,  
132 -// library.supportV13,  
133 -// library.recyclerviewV7,  
134 -// library.cardviewV7,  
135 -// library.dataBinding,  
136 //使用androidx 140 //使用androidx
137 androidx.appcompat, 141 androidx.appcompat,
138 androidx.constraintlayout, 142 androidx.constraintlayout,
@@ -145,11 +149,9 @@ ext { @@ -145,11 +149,9 @@ ext {
145 library.retrofitAdapterRxjava2, 149 library.retrofitAdapterRxjava2,
146 library.okhttp, 150 library.okhttp,
147 library.okhttpLoggingInterceptor, 151 library.okhttpLoggingInterceptor,
  152 + //数据库
148 library.greendao, 153 library.greendao,
149 - //管理rxjava生命周期  
150 -// library.rx  
151 router.api, 154 router.api,
152 -  
153 test.junit, 155 test.junit,
154 test.runner, 156 test.runner,
155 test.espresso 157 test.espresso
@@ -162,10 +164,6 @@ ext { @@ -162,10 +164,6 @@ ext {
162 router.compiler 164 router.compiler
163 ] 165 ]
164 166
165 -// base_jar = [  
166 -// library_jar.pinyin4j  
167 -// ]  
168 -  
169 //正式签名配置 167 //正式签名配置
170 Properties properties = new Properties() 168 Properties properties = new Properties()
171 properties.load(project.rootProject.file('local.properties').newDataInputStream()) 169 properties.load(project.rootProject.file('local.properties').newDataInputStream())
core/base/base_maven_push.gradle 0 → 100644
  1 +apply plugin: 'maven'
  2 +
  3 +uploadArchives() {
  4 + repositories {
  5 + mavenDeployer {
  6 + def lib = moudle_cnlive_base
  7 + //发布环境(正式/测试)
  8 + android.defaultPublishConfig lib.debug ? "debug" : "release"
  9 + //发布渠道(地址/账号)
  10 + repository(url: maven.mixedUrl) {
  11 + authentication(userName: maven.username, password: maven.password)
  12 + }
  13 + //发布信息(包名/别名/版本)
  14 + pom.project {
  15 + groupId lib.packeg
  16 + artifactId lib.name
  17 + version = lib.debug ? lib.version.concat("-SNAPSHOT") : lib.version
  18 + }
  19 + pom.whenConfigured { pom ->
  20 + pom.dependencies.clear()
  21 + }
  22 +
  23 + }
  24 + }
  25 +}
0 \ No newline at end of file 26 \ No newline at end of file
core/base/build.gradle
1 apply plugin: 'com.android.library' 1 apply plugin: 'com.android.library'
2 - 2 +apply from: './base_maven_push.gradle'
3 android { 3 android {
4 // compileSdkVersion 29 4 // compileSdkVersion 29
5 // buildToolsVersion "29.0.2" 5 // buildToolsVersion "29.0.2"
@@ -27,6 +27,5 @@ android { @@ -27,6 +27,5 @@ android {
27 dependencies { 27 dependencies {
28 implementation fileTree(include: ['*.jar'], dir: 'libs') 28 implementation fileTree(include: ['*.jar'], dir: 'libs')
29 api files('libs/pinyin4j-2.5.0.jar') 29 api files('libs/pinyin4j-2.5.0.jar')
30 -  
31 implementation 'androidx.legacy:legacy-support-v4:1.0.0' 30 implementation 'androidx.legacy:legacy-support-v4:1.0.0'
32 } 31 }
core/base/src/main/java/androidx/fragment/app/FragmentationMagician.java 0 → 100644
  1 +package androidx.fragment.app;
  2 +
  3 +
  4 +import java.util.List;
  5 +
  6 +/**
  7 + * Created by YoKey on 16/1/22.
  8 + */
  9 +public class FragmentationMagician {
  10 +
  11 + public static boolean isStateSaved(FragmentManager fragmentManager) {
  12 + if (!(fragmentManager instanceof FragmentManagerImpl))
  13 + return false;
  14 + try {
  15 + FragmentManagerImpl fragmentManagerImpl = (FragmentManagerImpl) fragmentManager;
  16 + return fragmentManagerImpl.isStateSaved();
  17 + } catch (Exception e) {
  18 + e.printStackTrace();
  19 + }
  20 + return false;
  21 + }
  22 +
  23 + /**
  24 + * Like {@link FragmentManager#popBackStack()}} but allows the commit to be executed after an
  25 + * activity's state is saved. This is dangerous because the action can
  26 + * be lost if the activity needs to later be restored from its state, so
  27 + * this should only be used for cases where it is okay for the UI state
  28 + * to change unexpectedly on the user.
  29 + */
  30 + public static void popBackStackAllowingStateLoss(final FragmentManager fragmentManager) {
  31 + FragmentationMagician.hookStateSaved(fragmentManager, new Runnable() {
  32 + @Override
  33 + public void run() {
  34 + fragmentManager.popBackStack();
  35 + }
  36 + });
  37 + }
  38 +
  39 + /**
  40 + * Like {@link FragmentManager#popBackStackImmediate()}} but allows the commit to be executed after an
  41 + * activity's state is saved.
  42 + */
  43 + public static void popBackStackImmediateAllowingStateLoss(final FragmentManager fragmentManager) {
  44 + FragmentationMagician.hookStateSaved(fragmentManager, new Runnable() {
  45 + @Override
  46 + public void run() {
  47 + fragmentManager.popBackStackImmediate();
  48 + }
  49 + });
  50 + }
  51 +
  52 + /**
  53 + * Like {@link FragmentManager#popBackStackImmediate(String, int)}} but allows the commit to be executed after an
  54 + * activity's state is saved.
  55 + */
  56 + public static void popBackStackAllowingStateLoss(final FragmentManager fragmentManager, final String name, final int flags) {
  57 + FragmentationMagician.hookStateSaved(fragmentManager, new Runnable() {
  58 + @Override
  59 + public void run() {
  60 + fragmentManager.popBackStack(name, flags);
  61 + }
  62 + });
  63 + }
  64 +
  65 + /**
  66 + * Like {@link FragmentManager#executePendingTransactions()} but allows the commit to be executed after an
  67 + * activity's state is saved.
  68 + */
  69 + public static void executePendingTransactionsAllowingStateLoss(final FragmentManager fragmentManager) {
  70 + FragmentationMagician.hookStateSaved(fragmentManager, new Runnable() {
  71 + @Override
  72 + public void run() {
  73 + fragmentManager.executePendingTransactions();
  74 + }
  75 + });
  76 + }
  77 +
  78 + public static List<Fragment> getActiveFragments(FragmentManager fragmentManager) {
  79 + return fragmentManager.getFragments();
  80 + }
  81 +
  82 + private static void hookStateSaved(FragmentManager fragmentManager, Runnable runnable) {
  83 + if (!(fragmentManager instanceof FragmentManagerImpl)) return;
  84 +
  85 + FragmentManagerImpl fragmentManagerImpl = (FragmentManagerImpl) fragmentManager;
  86 + if (isStateSaved(fragmentManager)) {
  87 + boolean tempStateSaved = fragmentManagerImpl.mStateSaved;
  88 + boolean tempStopped = fragmentManagerImpl.mStopped;
  89 + fragmentManagerImpl.mStateSaved = false;
  90 + fragmentManagerImpl.mStopped = false;
  91 +
  92 + runnable.run();
  93 +
  94 + fragmentManagerImpl.mStopped = tempStopped;
  95 + fragmentManagerImpl.mStateSaved = tempStateSaved;
  96 + } else {
  97 + runnable.run();
  98 + }
  99 + }
  100 +}
0 \ No newline at end of file 101 \ No newline at end of file
core/base/src/main/java/com/cnlive/core/libs/base/arouter/QrService.java 0 → 100644
  1 +package com.cnlive.core.libs.base.arouter;
  2 +
  3 +import android.graphics.Bitmap;
  4 +
  5 +import androidx.annotation.Nullable;
  6 +
  7 +import com.alibaba.android.arouter.facade.template.IProvider;
  8 +
  9 +/**
  10 + * 作者: 吴奎庆
  11 + * <p>
  12 + * 时间: 2019/6/18
  13 + * <p>
  14 + * 简介: 生成二维码调用的服务
  15 + */
  16 +public interface QrService extends IProvider {
  17 + String PATH = "/app/qrservice";
  18 + String NAME = "app_qrservice";
  19 + String GROUP = "appqr";
  20 +
  21 + /**
  22 + * 生成二维码的逻辑(带图标)
  23 + *
  24 + * @param content
  25 + * @param size 宽高
  26 + * @param logoBitmap 图标的bitmap
  27 + * @param logoPercent 百分比
  28 + * @return
  29 + */
  30 + Bitmap createQrIconBitMap(String content, int size, @Nullable Bitmap logoBitmap, float logoPercent);
  31 +
  32 + /**
  33 + * 生成不带图标的二维码
  34 + *
  35 + * @param content 内容
  36 + * @param size 二维码大小 单位px
  37 + * @return
  38 + */
  39 + Bitmap createQRNoIconBitmap(@Nullable String content, int size);
  40 +
  41 +}
core/base/src/main/java/com/cnlive/core/libs/base/arouter/im/FriendListData.java 0 → 100644
  1 +package com.cnlive.core.libs.base.arouter.im;
  2 +
  3 +public class FriendListData {
  4 +
  5 + private String friendId;
  6 + private String friendFaceUrl;
  7 + private String friendNickName;
  8 + private String friendRemark;
  9 + private String friendCustomInfoJson;
  10 +
  11 + public String getFriendId() {
  12 + return friendId;
  13 + }
  14 +
  15 + public void setFriendId(String friendId) {
  16 + this.friendId = friendId;
  17 + }
  18 +
  19 + public String getFriendFaceUrl() {
  20 + return friendFaceUrl;
  21 + }
  22 +
  23 + public void setFriendFaceUrl(String friendFaceUrl) {
  24 + this.friendFaceUrl = friendFaceUrl;
  25 + }
  26 +
  27 + public String getFriendNickName() {
  28 + return friendNickName;
  29 + }
  30 +
  31 + public void setFriendNickName(String friendNickName) {
  32 + this.friendNickName = friendNickName;
  33 + }
  34 +
  35 + public String getFriendRemark() {
  36 + return friendRemark;
  37 + }
  38 +
  39 + public void setFriendRemark(String friendRemark) {
  40 + this.friendRemark = friendRemark;
  41 + }
  42 +
  43 + public String getFriendCustomInfoJson() {
  44 + return friendCustomInfoJson;
  45 + }
  46 +
  47 + public void setFriendCustomInfoJson(String friendCustomInfoJson) {
  48 + this.friendCustomInfoJson = friendCustomInfoJson;
  49 + }
  50 +}
core/base/src/main/java/com/cnlive/core/libs/base/arouter/im/ImOpenService.java 0 → 100644
  1 +package com.cnlive.core.libs.base.arouter.im;
  2 +
  3 +import com.alibaba.android.arouter.facade.template.IProvider;
  4 +
  5 +import java.util.List;
  6 +
  7 +/**
  8 + * IM相关的对外接口
  9 + */
  10 +public interface ImOpenService extends IProvider {
  11 + //获取好友列表
  12 + void getFriendList(CNValueCallBack<List<FriendListData>> callBack);
  13 +
  14 + //是否已经加入了群组,注:本地数据判断
  15 + boolean hasJoinGroup(String groupId);
  16 +
  17 + interface CNCallBack {
  18 + void onError(int errorCode, String errorMsg);
  19 +
  20 + void onSuccess();
  21 + }
  22 +
  23 + interface CNValueCallBack<T> {
  24 + void onError(int var1, String var2);
  25 +
  26 + void onSuccess(T var1);
  27 + }
  28 +
  29 +}
core/base/src/main/java/com/cnlive/core/libs/base/frame/activity/BaseActivity.java
1 package com.cnlive.core.libs.base.frame.activity; 1 package com.cnlive.core.libs.base.frame.activity;
2 2
3 3
  4 +import android.app.Activity;
4 import android.content.Context; 5 import android.content.Context;
5 import android.content.DialogInterface; 6 import android.content.DialogInterface;
6 import android.content.Intent; 7 import android.content.Intent;
@@ -14,21 +15,26 @@ import android.provider.Settings; @@ -14,21 +15,26 @@ import android.provider.Settings;
14 import android.text.TextUtils; 15 import android.text.TextUtils;
15 import android.util.DisplayMetrics; 16 import android.util.DisplayMetrics;
16 import android.view.Display; 17 import android.view.Display;
  18 +import android.view.MotionEvent;
17 import android.view.View; 19 import android.view.View;
18 import android.view.Window; 20 import android.view.Window;
19 import android.view.WindowManager; 21 import android.view.WindowManager;
20 import android.view.inputmethod.InputMethodManager; 22 import android.view.inputmethod.InputMethodManager;
21 23
22 import androidx.annotation.ColorRes; 24 import androidx.annotation.ColorRes;
  25 +import androidx.annotation.DrawableRes;
23 import androidx.annotation.IntRange; 26 import androidx.annotation.IntRange;
24 import androidx.annotation.NonNull; 27 import androidx.annotation.NonNull;
25 import androidx.annotation.Nullable; 28 import androidx.annotation.Nullable;
  29 +import androidx.annotation.StringRes;
26 import androidx.appcompat.app.AlertDialog; 30 import androidx.appcompat.app.AlertDialog;
27 import androidx.core.app.ActivityCompat; 31 import androidx.core.app.ActivityCompat;
28 import androidx.core.content.ContextCompat; 32 import androidx.core.content.ContextCompat;
29 import androidx.databinding.DataBindingUtil; 33 import androidx.databinding.DataBindingUtil;
30 import androidx.databinding.ViewDataBinding; 34 import androidx.databinding.ViewDataBinding;
31 35
  36 +import com.alibaba.android.arouter.launcher.ARouter;
  37 +import com.cnlive.core.libs.base.application.AppConfig;
32 import com.cnlive.core.libs.base.frame.presenter.BasePresenter; 38 import com.cnlive.core.libs.base.frame.presenter.BasePresenter;
33 import com.cnlive.core.libs.base.frame.view.BaseView; 39 import com.cnlive.core.libs.base.frame.view.BaseView;
34 import com.cnlive.core.libs.base.interfaces.OnPermissionResponseListener; 40 import com.cnlive.core.libs.base.interfaces.OnPermissionResponseListener;
@@ -37,27 +43,36 @@ import com.cnlive.core.libs.base.util.AppManager; @@ -37,27 +43,36 @@ import com.cnlive.core.libs.base.util.AppManager;
37 import com.cnlive.core.libs.base.util.ReflectUtil; 43 import com.cnlive.core.libs.base.util.ReflectUtil;
38 import com.cnlive.core.libs.base.util.StatusBarConfig; 44 import com.cnlive.core.libs.base.util.StatusBarConfig;
39 import com.cnlive.core.libs.base.util.StatusBarUtil; 45 import com.cnlive.core.libs.base.util.StatusBarUtil;
40 -import com.cnlive.core.libs.base.util.swipeback.util.SwipeBackActivityBase;  
41 -import com.cnlive.core.libs.base.util.swipeback.util.SwipeBackActivityHelper;  
42 -import com.cnlive.core.libs.base.util.swipeback.util.SwipeBackLayout;  
43 -import com.cnlive.core.libs.base.util.swipeback.util.SwipeBackUtil; 46 +import com.cnlive.strike.base.R;
44 import com.hannesdorfmann.mosby3.mvp.MvpActivity; 47 import com.hannesdorfmann.mosby3.mvp.MvpActivity;
  48 +import com.me.yokeyword.fragmentation.ExtraTransaction;
  49 +import com.me.yokeyword.fragmentation.Fragmentation;
  50 +import com.me.yokeyword.fragmentation.ISupportActivity;
  51 +import com.me.yokeyword.fragmentation.ISupportFragment;
  52 +import com.me.yokeyword.fragmentation.SupportActivityDelegate;
  53 +import com.me.yokeyword.fragmentation.SupportHelper;
  54 +import com.me.yokeyword.fragmentation.SwipeBackLayout;
  55 +import com.me.yokeyword.fragmentation.anim.FragmentAnimator;
  56 +import com.me.yokeyword.fragmentation_swipeback.core.ISwipeBackActivity;
  57 +import com.me.yokeyword.fragmentation_swipeback.core.SwipeBackActivityDelegate;
45 import com.orhanobut.logger.Logger; 58 import com.orhanobut.logger.Logger;
46 59
47 import java.lang.reflect.Field; 60 import java.lang.reflect.Field;
48 import java.util.ArrayList; 61 import java.util.ArrayList;
49 import java.util.List; 62 import java.util.List;
50 63
  64 +
51 /** 65 /**
52 * @author ys 66 * @author ys
53 * 基类 activity 67 * 基类 activity
  68 + * SwipeBackActivityBase,
54 */ 69 */
55 -public abstract class BaseActivity<V extends BaseView, P extends BasePresenter<V>> extends MvpActivity<V, P> implements SwipeBackActivityBase { 70 +public abstract class BaseActivity<V extends BaseView, P extends BasePresenter<V>> extends MvpActivity<V, P> implements ISupportActivity, ISwipeBackActivity {
56 private V view; 71 private V view;
57 private P presenter; 72 private P presenter;
58 public ViewDataBinding baseBinding; 73 public ViewDataBinding baseBinding;
59 //获取TAG的activity名称 74 //获取TAG的activity名称
60 - protected final String TAG = this.getClass().getSimpleName(); 75 + public final String TAG = this.getClass().getSimpleName();
61 //是否显示标题栏 76 //是否显示标题栏
62 private boolean isShowTitle = true; 77 private boolean isShowTitle = true;
63 //是否显示状态栏 78 //是否显示状态栏
@@ -74,9 +89,12 @@ public abstract class BaseActivity&lt;V extends BaseView, P extends BasePresenter&lt;V @@ -74,9 +89,12 @@ public abstract class BaseActivity&lt;V extends BaseView, P extends BasePresenter&lt;V
74 private int USER_SET_REQUEST_CODE_PERMISSION = -0x00099;//用户设置的权限请求码 89 private int USER_SET_REQUEST_CODE_PERMISSION = -0x00099;//用户设置的权限请求码
75 private String defaultDefinePermissionTip = "需要必要的权限才可以正常使用该功能,您已拒绝获得该权限。\n如果需要重新授权,您可以点击“允许”按钮进入系统设置进行授权";//默认拒绝的权限提示语 90 private String defaultDefinePermissionTip = "需要必要的权限才可以正常使用该功能,您已拒绝获得该权限。\n如果需要重新授权,您可以点击“允许”按钮进入系统设置进行授权";//默认拒绝的权限提示语
76 private String userSetDefinePermissionTip = "";//用户设置的权限提示语 91 private String userSetDefinePermissionTip = "";//用户设置的权限提示语
77 - private SwipeBackActivityHelper mHelper;//侧滑返回 92 + // private SwipeBackActivityHelper mHelper;//侧滑返回
78 private boolean isOpenSwipBack = false; 93 private boolean isOpenSwipBack = false;
79 - private AlertDialog alertDialog; 94 + //fragmnet管理
  95 + private final SupportActivityDelegate mDelegate = new SupportActivityDelegate(this);
  96 + //fragment侧滑
  97 + private final SwipeBackActivityDelegate mSwipeDelegate = new SwipeBackActivityDelegate(this);
80 98
81 @Override 99 @Override
82 protected void onCreate(@Nullable Bundle savedInstanceState) { 100 protected void onCreate(@Nullable Bundle savedInstanceState) {
@@ -86,9 +104,20 @@ public abstract class BaseActivity&lt;V extends BaseView, P extends BasePresenter&lt;V @@ -86,9 +104,20 @@ public abstract class BaseActivity&lt;V extends BaseView, P extends BasePresenter&lt;V
86 } else if (0 != getViewLayoutId()) { 104 } else if (0 != getViewLayoutId()) {
87 setContentView(getViewLayoutId()); 105 setContentView(getViewLayoutId());
88 } 106 }
  107 + //两种视图都没有设置,就加载默认跟视图,用于fragment切换
  108 + if (0 == getBindLayoutId() && 0 == getViewLayoutId()) {
  109 + setContentView(R.layout.base_activity_main);
  110 + }
89 context = this; 111 context = this;
90 me = this; 112 me = this;
  113 + //fragment管理
  114 + mDelegate.onCreate(savedInstanceState);
  115 + mSwipeDelegate.onCreate(savedInstanceState);
  116 + //是否开启滑动返回
  117 + setSwipeBackEnable(isOpenSwipBack);
91 this.savedInstanceState = savedInstanceState; 118 this.savedInstanceState = savedInstanceState;
  119 + //路由参数初始化
  120 + ARouter.getInstance().inject(this);
92 //activity管理 121 //activity管理
93 AppManager.getInstance().pushActivity(me); 122 AppManager.getInstance().pushActivity(me);
94 //创建订阅映射 123 //创建订阅映射
@@ -114,16 +143,11 @@ public abstract class BaseActivity&lt;V extends BaseView, P extends BasePresenter&lt;V @@ -114,16 +143,11 @@ public abstract class BaseActivity&lt;V extends BaseView, P extends BasePresenter&lt;V
114 initView(); 143 initView();
115 //设置数据 144 //设置数据
116 initData(); 145 initData();
117 - //是否开启滑动返回  
118 - if (isOpenSwipBack) {  
119 - mHelper = new SwipeBackActivityHelper(this);  
120 - mHelper.onActivityCreate();  
121 - }  
122 -  
123 - }  
124 -  
125 - protected void setOpenSwipBack(boolean isOpen) {  
126 - isOpenSwipBack = isOpen; 146 +// if (isOpenSwipBack) {
  147 +// mHelper = new SwipeBackActivityHelper(this);
  148 +// mHelper.onActivityCreate();
  149 +//
  150 +// }
127 } 151 }
128 152
129 153
@@ -147,6 +171,10 @@ public abstract class BaseActivity&lt;V extends BaseView, P extends BasePresenter&lt;V @@ -147,6 +171,10 @@ public abstract class BaseActivity&lt;V extends BaseView, P extends BasePresenter&lt;V
147 171
148 } 172 }
149 173
  174 + public boolean isOpenSwipBack() {
  175 + return isOpenSwipBack;
  176 + }
  177 +
150 /** 178 /**
151 * 设置是否显示标题栏 179 * 设置是否显示标题栏
152 * 180 *
@@ -238,13 +266,14 @@ public abstract class BaseActivity&lt;V extends BaseView, P extends BasePresenter&lt;V @@ -238,13 +266,14 @@ public abstract class BaseActivity&lt;V extends BaseView, P extends BasePresenter&lt;V
238 266
239 @Override 267 @Override
240 protected void onDestroy() { 268 protected void onDestroy() {
  269 + mDelegate.onDestroy();
241 super.onDestroy(); 270 super.onDestroy();
242 - if (null != alertDialog) {  
243 - alertDialog.dismiss(); 271 + if (null != baseBinding) {
  272 + baseBinding.unbind();
244 } 273 }
245 //activity管理 274 //activity管理
246 AppManager.getInstance().deleteActivity(me); 275 AppManager.getInstance().deleteActivity(me);
247 - //清除所有订阅 276 + //清除当前订阅
248 SubscriptionManager.getInstance().cancel(TAG); 277 SubscriptionManager.getInstance().cancel(TAG);
249 } 278 }
250 279
@@ -254,15 +283,23 @@ public abstract class BaseActivity&lt;V extends BaseView, P extends BasePresenter&lt;V @@ -254,15 +283,23 @@ public abstract class BaseActivity&lt;V extends BaseView, P extends BasePresenter&lt;V
254 * @param color 283 * @param color
255 * @param statusBarAlpha 284 * @param statusBarAlpha
256 */ 285 */
257 - protected void setStatusBarColor(@ColorRes int color,  
258 - @IntRange(from = 0, to = 255) int statusBarAlpha) { 286 + public void setStatusBarColor(@ColorRes int color,
  287 + @IntRange(from = 0, to = 255) int statusBarAlpha) {
259 StatusBarUtil.setColor(this, ContextCompat.getColor(this, color), statusBarAlpha); 288 StatusBarUtil.setColor(this, ContextCompat.getColor(this, color), statusBarAlpha);
260 } 289 }
261 290
  291 + public void setTransparentForWindow(Activity activity) {
  292 + StatusBarUtil.setTransparentForWindow(activity);
  293 + }
  294 +
  295 + public void addTranslucentView(Activity activity, @IntRange(from = 0, to = 255) int statusBarAlpha) {
  296 + StatusBarUtil.addTranslucentView(activity, statusBarAlpha);
  297 + }
  298 +
262 /** 299 /**
263 * 设置状态栏字体颜色 300 * 设置状态栏字体颜色
264 */ 301 */
265 - protected void setStatusBarTextColor(int type) { 302 + public void setStatusBarTextColor(int type) {
266 if (type == StatusBarConfig.BLACK) { 303 if (type == StatusBarConfig.BLACK) {
267 StatusBarUtil.setStatusBarWrite(this); 304 StatusBarUtil.setStatusBarWrite(this);
268 } else if (type == StatusBarConfig.WHITE) { 305 } else if (type == StatusBarConfig.WHITE) {
@@ -403,6 +440,29 @@ public abstract class BaseActivity&lt;V extends BaseView, P extends BasePresenter&lt;V @@ -403,6 +440,29 @@ public abstract class BaseActivity&lt;V extends BaseView, P extends BasePresenter&lt;V
403 } 440 }
404 441
405 /** 442 /**
  443 + * 请求权限
  444 + * <p>
  445 + * 警告:此处除了用户拒绝外,唯一可能出现无法获取权限或失败的情况是在AndroidManifest.xml中未声明权限信息
  446 + * Android6.0+即便需要动态请求权限(重点)但不代表着不需要在AndroidManifest.xml中进行声明。
  447 + *
  448 + * @param permissions 请求的权限
  449 + * @param onPermissionResponseListener 回调监听器
  450 + */
  451 + public void requestPermission(String[] permissions, String defineTip, OnPermissionResponseListener
  452 + onPermissionResponseListener) {
  453 + this.userSetDefinePermissionTip = defineTip;
  454 + this.onPermissionResponseListener = onPermissionResponseListener;
  455 + if (checkPermissions(permissions)) {
  456 + if (onPermissionResponseListener != null) {
  457 + onPermissionResponseListener.onSuccess(permissions);
  458 + }
  459 + } else {
  460 + List<String> needPermissions = getDeniedPermissions(permissions);
  461 + ActivityCompat.requestPermissions(this, needPermissions.toArray(new String[needPermissions.size()]), DEFAULT_REQUEST_CODE_PERMISSION);
  462 + }
  463 + }
  464 +
  465 + /**
406 * 自定义权限申请码 466 * 自定义权限申请码
407 * 467 *
408 * @param requestCode 468 * @param requestCode
@@ -446,6 +506,29 @@ public abstract class BaseActivity&lt;V extends BaseView, P extends BasePresenter&lt;V @@ -446,6 +506,29 @@ public abstract class BaseActivity&lt;V extends BaseView, P extends BasePresenter&lt;V
446 } 506 }
447 507
448 /** 508 /**
  509 + * 自定义权限申请码和提示信息
  510 + * 可传入string字符串
  511 + *
  512 + * @param requestCode
  513 + * @param permissions
  514 + * @param onPermissionResponseListener
  515 + */
  516 + public void requestPermission(int requestCode, @StringRes int defineTip, String[]
  517 + permissions, OnPermissionResponseListener onPermissionResponseListener) {
  518 + this.onPermissionResponseListener = onPermissionResponseListener;
  519 + this.USER_SET_REQUEST_CODE_PERMISSION = requestCode;
  520 + this.userSetDefinePermissionTip = getResources().getString(defineTip);
  521 + if (checkPermissions(permissions)) {
  522 + if (onPermissionResponseListener != null) {
  523 + onPermissionResponseListener.onSuccess(permissions);
  524 + }
  525 + } else {
  526 + List<String> needPermissions = getDeniedPermissions(permissions);
  527 + ActivityCompat.requestPermissions(this, needPermissions.toArray(new String[needPermissions.size()]), USER_SET_REQUEST_CODE_PERMISSION);
  528 + }
  529 + }
  530 +
  531 + /**
449 * 获取权限集中需要申请权限的列表 532 * 获取权限集中需要申请权限的列表
450 * 533 *
451 * @param permissions 534 * @param permissions
@@ -588,33 +671,36 @@ public abstract class BaseActivity&lt;V extends BaseView, P extends BasePresenter&lt;V @@ -588,33 +671,36 @@ public abstract class BaseActivity&lt;V extends BaseView, P extends BasePresenter&lt;V
588 @Override 671 @Override
589 protected void onPostCreate(Bundle savedInstanceState) { 672 protected void onPostCreate(Bundle savedInstanceState) {
590 super.onPostCreate(savedInstanceState); 673 super.onPostCreate(savedInstanceState);
591 - if (null != mHelper) {  
592 - mHelper.onPostCreate();  
593 - }  
594 - }  
595 -  
596 - @Override  
597 - public SwipeBackLayout getSwipeBackLayout() {  
598 - if (null != mHelper) {  
599 - return mHelper.getSwipeBackLayout();  
600 - }  
601 - return null;  
602 - }  
603 -  
604 - @Override  
605 - public void setSwipeBackEnable(boolean enable) {  
606 - if (null != getSwipeBackLayout()) {  
607 - getSwipeBackLayout().setEnableGesture(enable);  
608 - }  
609 - }  
610 -  
611 - @Override  
612 - public void scrollToFinishActivity() {  
613 - if (null != mHelper) {  
614 - SwipeBackUtil.convertActivityToTranslucent(this);  
615 - getSwipeBackLayout().scrollToFinishActivity();  
616 - }  
617 - } 674 +// if (null != mHelper) {
  675 +// mHelper.onPostCreate();
  676 +// }
  677 + mDelegate.onPostCreate(savedInstanceState);
  678 + mSwipeDelegate.onPostCreate(savedInstanceState);
  679 +
  680 + }
  681 +
  682 +// @Override
  683 +// public SwipeBackLayout getSwipeBackLayout() {
  684 +// if (null != mHelper) {
  685 +// return mHelper.getSwipeBackLayout();
  686 +// }
  687 +// return null;
  688 +// }
  689 +//
  690 +// @Override
  691 +// public void setSwipeBackEnable(boolean enable) {
  692 +// if (null != getSwipeBackLayout()) {
  693 +// getSwipeBackLayout().setEnableGesture(enable);
  694 +// }
  695 +// }
  696 +
  697 +// @Override
  698 +// public void scrollToFinishActivity() {
  699 +// if (null != mHelper) {
  700 +// SwipeBackUtil.convertActivityToTranslucent(this);
  701 +// getSwipeBackLayout().scrollToFinishActivity();
  702 +// }
  703 +// }
618 704
619 705
620 public void logError(Object info) { 706 public void logError(Object info) {
@@ -644,4 +730,288 @@ public abstract class BaseActivity&lt;V extends BaseView, P extends BasePresenter&lt;V @@ -644,4 +730,288 @@ public abstract class BaseActivity&lt;V extends BaseView, P extends BasePresenter&lt;V
644 public void logXml(String xml) { 730 public void logXml(String xml) {
645 Logger.xml(xml); 731 Logger.xml(xml);
646 } 732 }
  733 +
  734 + /*****************************fragment管理****************************************/
  735 + @Override
  736 + public SupportActivityDelegate getSupportDelegate() {
  737 + return mDelegate;
  738 + }
  739 +
  740 + /**
  741 + * Perform some extra transactions.
  742 + * 额外的事务:自定义Tag,添加SharedElement动画,操作非回退栈Fragment
  743 + */
  744 + @Override
  745 + public ExtraTransaction extraTransaction() {
  746 + return mDelegate.extraTransaction();
  747 + }
  748 +
  749 + /**
  750 + * Note: return mDelegate.dispatchTouchEvent(ev) || super.dispatchTouchEvent(ev);
  751 + */
  752 + @Override
  753 + public boolean dispatchTouchEvent(MotionEvent ev) {
  754 + return mDelegate.dispatchTouchEvent(ev) || super.dispatchTouchEvent(ev);
  755 + }
  756 +
  757 + /**
  758 + * 不建议复写该方法,请使用 {@link #onBackPressedSupport} 代替
  759 + */
  760 + @Override
  761 + public void onBackPressed() {
  762 + mDelegate.onBackPressed();
  763 + }
  764 +
  765 + /**
  766 + * 该方法回调时机为,Activity回退栈内Fragment的数量 小于等于1 时,默认finish Activity
  767 + * 请尽量复写该方法,避免复写onBackPress(),以保证SupportFragment内的onBackPressedSupport()回退事件正常执行
  768 + */
  769 + @Override
  770 + public void onBackPressedSupport() {
  771 + mDelegate.onBackPressedSupport();
  772 + }
  773 +
  774 + /**
  775 + * 获取设置的全局动画 copy
  776 + *
  777 + * @return FragmentAnimator
  778 + */
  779 + @Override
  780 + public FragmentAnimator getFragmentAnimator() {
  781 + return mDelegate.getFragmentAnimator();
  782 + }
  783 +
  784 + /**
  785 + * Set all fragments animation.
  786 + * 设置Fragment内的全局动画
  787 + */
  788 + @Override
  789 + public void setFragmentAnimator(FragmentAnimator fragmentAnimator) {
  790 + mDelegate.setFragmentAnimator(fragmentAnimator);
  791 + }
  792 +
  793 + /**
  794 + * Set all fragments animation.
  795 + * 构建Fragment转场动画
  796 + * <p/>
  797 + * 如果是在Activity内实现,则构建的是Activity内所有Fragment的转场动画,
  798 + * 如果是在Fragment内实现,则构建的是该Fragment的转场动画,此时优先级 > Activity的onCreateFragmentAnimator()
  799 + *
  800 + * @return FragmentAnimator对象
  801 + */
  802 + @Override
  803 + public FragmentAnimator onCreateFragmentAnimator() {
  804 + return mDelegate.onCreateFragmentAnimator();
  805 + }
  806 +
  807 + @Override
  808 + public void post(Runnable runnable) {
  809 + mDelegate.post(runnable);
  810 + }
  811 +
  812 + /****************************************以下为可选方法(Optional methods)******************************************************/
  813 + /**
  814 + * 加载根Fragment, 即Activity内的第一个Fragment 或 Fragment内的第一个子Fragment
  815 + * <p>
  816 + * root_container 容器id
  817 + *
  818 + * @param toFragment 目标Fragment
  819 + */
  820 + public void loadRootFragment(@NonNull ISupportFragment toFragment) {
  821 + mDelegate.loadRootFragment(R.id.root_container, toFragment);
  822 + }
  823 +
  824 + /**
  825 + * 加载根Fragment, 即Activity内的第一个Fragment 或 Fragment内的第一个子Fragment
  826 + *
  827 + * @param containerId 容器id
  828 + * @param toFragment 目标Fragment
  829 + */
  830 + public void loadRootFragment(int containerId, @NonNull ISupportFragment toFragment) {
  831 + mDelegate.loadRootFragment(containerId, toFragment);
  832 + }
  833 +
  834 + public void loadRootFragment(int containerId, ISupportFragment toFragment, boolean addToBackStack, boolean allowAnimation) {
  835 + mDelegate.loadRootFragment(containerId, toFragment, addToBackStack, allowAnimation);
  836 + }
  837 +
  838 + /**
  839 + * 加载多个同级根Fragment,类似Wechat, QQ主页的场景
  840 + */
  841 + public void loadMultipleRootFragment(int containerId, int showPosition, ISupportFragment... toFragments) {
  842 + mDelegate.loadMultipleRootFragment(containerId, showPosition, toFragments);
  843 + }
  844 +
  845 + /**
  846 + * show一个Fragment,hide其他同栈所有Fragment
  847 + * 使用该方法时,要确保同级栈内无多余的Fragment,(只有通过loadMultipleRootFragment()载入的Fragment)
  848 + * <p>
  849 + * 建议使用更明确的{@link #showHideFragment(ISupportFragment, ISupportFragment)}
  850 + *
  851 + * @param showFragment 需要show的Fragment
  852 + */
  853 + public void showHideFragment(ISupportFragment showFragment) {
  854 + mDelegate.showHideFragment(showFragment);
  855 + }
  856 +
  857 + /**
  858 + * show一个Fragment,hide一个Fragment ; 主要用于类似微信主页那种 切换tab的情况
  859 + */
  860 + public void showHideFragment(ISupportFragment showFragment, ISupportFragment hideFragment) {
  861 + mDelegate.showHideFragment(showFragment, hideFragment);
  862 + }
  863 +
  864 + /**
  865 + * It is recommended to use {@link SupportFragment#start(ISupportFragment)}.
  866 + */
  867 + public void start(ISupportFragment toFragment) {
  868 + mDelegate.start(toFragment);
  869 + }
  870 +
  871 + /**
  872 + * It is recommended to use {@link SupportFragment#start(ISupportFragment, int)}.
  873 + *
  874 + * @param launchMode Similar to Activity's LaunchMode.
  875 + */
  876 + public void start(ISupportFragment toFragment, @ISupportFragment.LaunchMode int launchMode) {
  877 + mDelegate.start(toFragment, launchMode);
  878 + }
  879 +
  880 + /**
  881 + * It is recommended to use {@link SupportFragment#startForResult(ISupportFragment, int)}.
  882 + * Launch an fragment for which you would like a result when it poped.
  883 + */
  884 + public void startForResult(ISupportFragment toFragment, int requestCode) {
  885 + mDelegate.startForResult(toFragment, requestCode);
  886 + }
  887 +
  888 + /**
  889 + * It is recommended to use {@link SupportFragment#startWithPop(ISupportFragment)}.
  890 + * Start the target Fragment and pop itself
  891 + */
  892 + public void startWithPop(ISupportFragment toFragment) {
  893 + mDelegate.startWithPop(toFragment);
  894 + }
  895 +
  896 + /**
  897 + * It is recommended to use {@link SupportFragment#startWithPopTo(ISupportFragment, Class, boolean)}.
  898 + *
  899 + * @see #popTo(Class, boolean)
  900 + * +
  901 + * @see #start(ISupportFragment)
  902 + */
  903 + public void startWithPopTo(ISupportFragment toFragment, Class<?> targetFragmentClass, boolean includeTargetFragment) {
  904 + mDelegate.startWithPopTo(toFragment, targetFragmentClass, includeTargetFragment);
  905 + }
  906 +
  907 + /**
  908 + * It is recommended to use {@link SupportFragment#replaceFragment(ISupportFragment, boolean)}.
  909 + */
  910 + public void replaceFragment(ISupportFragment toFragment, boolean addToBackStack) {
  911 + mDelegate.replaceFragment(toFragment, addToBackStack);
  912 + }
  913 +
  914 + /**
  915 + * Pop the fragment.
  916 + */
  917 + public void pop() {
  918 + mDelegate.pop();
  919 + }
  920 +
  921 + /**
  922 + * Pop the last fragment transition from the manager's fragment
  923 + * back stack.
  924 + * <p>
  925 + * 出栈到目标fragment
  926 + *
  927 + * @param targetFragmentClass 目标fragment
  928 + * @param includeTargetFragment 是否包含该fragment
  929 + */
  930 + public void popTo(Class<?> targetFragmentClass, boolean includeTargetFragment) {
  931 + mDelegate.popTo(targetFragmentClass, includeTargetFragment);
  932 + }
  933 +
  934 + /**
  935 + * If you want to begin another FragmentTransaction immediately after popTo(), use this method.
  936 + * 如果你想在出栈后, 立刻进行FragmentTransaction操作,请使用该方法
  937 + */
  938 + public void popTo(Class<?> targetFragmentClass, boolean includeTargetFragment, Runnable afterPopTransactionRunnable) {
  939 + mDelegate.popTo(targetFragmentClass, includeTargetFragment, afterPopTransactionRunnable);
  940 + }
  941 +
  942 + public void popTo(Class<?> targetFragmentClass, boolean includeTargetFragment, Runnable afterPopTransactionRunnable, int popAnim) {
  943 + mDelegate.popTo(targetFragmentClass, includeTargetFragment, afterPopTransactionRunnable, popAnim);
  944 + }
  945 +
  946 + /**
  947 + * 当Fragment根布局 没有 设定background属性时,
  948 + * Fragmentation默认使用Theme的android:windowbackground作为Fragment的背景,
  949 + * 可以通过该方法改变其内所有Fragment的默认背景。
  950 + */
  951 + public void setDefaultFragmentBackground(@DrawableRes int backgroundRes) {
  952 + mDelegate.setDefaultFragmentBackground(backgroundRes);
  953 + }
  954 +
  955 + /**
  956 + * 得到位于栈顶Fragment
  957 + */
  958 + public ISupportFragment getTopFragment() {
  959 + return SupportHelper.getTopFragment(getSupportFragmentManager());
  960 + }
  961 +
  962 + /**
  963 + * 获取栈内的fragment对象
  964 + */
  965 + public <T extends ISupportFragment> T findFragment(Class<T> fragmentClass) {
  966 + return SupportHelper.findFragment(getSupportFragmentManager(), fragmentClass);
  967 + }
  968 +
  969 +
  970 + /**
  971 + * 显示fragment栈视图
  972 + */
  973 + public void showFragmetStackView() {
  974 + Fragmentation.builder()
  975 + // show stack view. Mode: BUBBLE, SHAKE, NONE
  976 + .stackViewMode(Fragmentation.BUBBLE)
  977 + .debug(AppConfig.isDebug())
  978 + .install();
  979 + }
  980 +/***********************************滑动返回********************************************/
  981 + /**
  982 + * 是否可滑动
  983 + *
  984 + * @param enable
  985 + */
  986 + @Override
  987 + public void setSwipeBackEnable(boolean enable) {
  988 + isOpenSwipBack = enable;
  989 + mSwipeDelegate.setSwipeBackEnable(enable);
  990 + }
  991 +
  992 + @Override
  993 + public void setEdgeLevel(SwipeBackLayout.EdgeLevel edgeLevel) {
  994 + mSwipeDelegate.setEdgeLevel(edgeLevel);
  995 + }
  996 +
  997 + @Override
  998 + public void setEdgeLevel(int widthPixel) {
  999 + mSwipeDelegate.setEdgeLevel(widthPixel);
  1000 + }
  1001 +
  1002 + /**
  1003 + * 限制SwipeBack的条件,默认栈内Fragment数 <= 1时 , 优先滑动退出Activity , 而不是Fragment
  1004 + *
  1005 + * @return true: Activity优先滑动退出; false: Fragment优先滑动退出
  1006 + */
  1007 + @Override
  1008 + public boolean swipeBackPriority() {
  1009 + return mSwipeDelegate.swipeBackPriority();
  1010 + }
  1011 +
  1012 + @Override
  1013 + public SwipeBackLayout getSwipeBackLayout() {
  1014 + return mSwipeDelegate.getSwipeBackLayout();
  1015 + }
  1016 +
647 } 1017 }
648 \ No newline at end of file 1018 \ No newline at end of file
core/base/src/main/java/com/cnlive/core/libs/base/frame/fragment/BaseFragment.java
1 package com.cnlive.core.libs.base.frame.fragment; 1 package com.cnlive.core.libs.base.frame.fragment;
2 2
  3 +import android.app.Activity;
  4 +import android.content.Intent;
3 import android.os.Bundle; 5 import android.os.Bundle;
4 import android.view.LayoutInflater; 6 import android.view.LayoutInflater;
5 import android.view.View; 7 import android.view.View;
6 import android.view.ViewGroup; 8 import android.view.ViewGroup;
  9 +import android.view.animation.Animation;
7 import android.view.inputmethod.InputMethodManager; 10 import android.view.inputmethod.InputMethodManager;
8 11
9 import androidx.annotation.ColorRes; 12 import androidx.annotation.ColorRes;
  13 +import androidx.annotation.FloatRange;
10 import androidx.annotation.IntRange; 14 import androidx.annotation.IntRange;
11 import androidx.annotation.NonNull; 15 import androidx.annotation.NonNull;
12 import androidx.annotation.Nullable; 16 import androidx.annotation.Nullable;
  17 +import androidx.annotation.StringRes;
13 import androidx.core.content.ContextCompat; 18 import androidx.core.content.ContextCompat;
14 import androidx.databinding.DataBindingUtil; 19 import androidx.databinding.DataBindingUtil;
15 import androidx.databinding.ViewDataBinding; 20 import androidx.databinding.ViewDataBinding;
16 21
  22 +import com.alibaba.android.arouter.launcher.ARouter;
17 import com.cnlive.core.libs.base.frame.activity.BaseActivity; 23 import com.cnlive.core.libs.base.frame.activity.BaseActivity;
18 import com.cnlive.core.libs.base.frame.presenter.BasePresenter; 24 import com.cnlive.core.libs.base.frame.presenter.BasePresenter;
19 import com.cnlive.core.libs.base.interfaces.OnPermissionResponseListener; 25 import com.cnlive.core.libs.base.interfaces.OnPermissionResponseListener;
  26 +import com.cnlive.core.libs.base.network.manager.SubscriptionManager;
20 import com.cnlive.core.libs.base.util.ParameterCache; 27 import com.cnlive.core.libs.base.util.ParameterCache;
21 import com.cnlive.core.libs.base.util.ReflectUtil; 28 import com.cnlive.core.libs.base.util.ReflectUtil;
22 import com.cnlive.core.libs.base.frame.view.BaseView; 29 import com.cnlive.core.libs.base.frame.view.BaseView;
23 import com.cnlive.core.libs.base.util.StatusBarConfig; 30 import com.cnlive.core.libs.base.util.StatusBarConfig;
24 import com.cnlive.core.libs.base.util.StatusBarUtil; 31 import com.cnlive.core.libs.base.util.StatusBarUtil;
  32 +import com.me.yokeyword.fragmentation.ExtraTransaction;
  33 +import com.me.yokeyword.fragmentation.ISupportFragment;
  34 +import com.me.yokeyword.fragmentation.SupportFragmentDelegate;
  35 +import com.me.yokeyword.fragmentation.SupportHelper;
  36 +import com.me.yokeyword.fragmentation.SwipeBackLayout;
  37 +import com.me.yokeyword.fragmentation.anim.FragmentAnimator;
  38 +import com.me.yokeyword.fragmentation_swipeback.core.ISwipeBackFragment;
  39 +import com.me.yokeyword.fragmentation_swipeback.core.SwipeBackFragmentDelegate;
  40 +import com.orhanobut.logger.Logger;
  41 +
25 42
26 import static android.content.Context.INPUT_METHOD_SERVICE; 43 import static android.content.Context.INPUT_METHOD_SERVICE;
27 44
@@ -32,19 +49,27 @@ import static android.content.Context.INPUT_METHOD_SERVICE; @@ -32,19 +49,27 @@ import static android.content.Context.INPUT_METHOD_SERVICE;
32 * @param <P> 49 * @param <P>
33 * @author ys 50 * @author ys
34 */ 51 */
35 -public abstract class BaseFragment<V extends BaseView, P extends BasePresenter<V>> extends com.hannesdorfmann.mosby3.mvp.MvpFragment<V, P> { 52 +public abstract class BaseFragment<V extends BaseView, P extends BasePresenter<V>> extends com.hannesdorfmann.mosby3.mvp.MvpFragment<V, P> implements ISupportFragment, ISwipeBackFragment {
36 private V view; 53 private V view;
37 private P presenter; 54 private P presenter;
38 - protected final String TAG = this.getClass().getSimpleName(); 55 + public final String TAG = this.getClass().getSimpleName();
39 public ViewDataBinding baseBinding; 56 public ViewDataBinding baseBinding;
40 public View baseView; 57 public View baseView;
41 public BaseActivity me; 58 public BaseActivity me;
  59 + //fragment管理
  60 + private final SupportFragmentDelegate mDelegate = new SupportFragmentDelegate(this);
  61 + //fragment滑动返回
  62 + private final SwipeBackFragmentDelegate mSwipeDelegate = new SwipeBackFragmentDelegate(this);
42 63
43 @Override 64 @Override
44 public void onCreate(Bundle savedInstanceState) { 65 public void onCreate(Bundle savedInstanceState) {
45 super.onCreate(savedInstanceState); 66 super.onCreate(savedInstanceState);
46 if (getActivity() == null) return; 67 if (getActivity() == null) return;
47 me = (BaseActivity) getActivity(); 68 me = (BaseActivity) getActivity();
  69 + mDelegate.onCreate(savedInstanceState);
  70 + mSwipeDelegate.onCreate(savedInstanceState);
  71 + setSwipeBackEnable(me.isOpenSwipBack());
  72 + ARouter.getInstance().inject(this);
48 initFragmentStyle(); 73 initFragmentStyle();
49 initParams(); 74 initParams();
50 } 75 }
@@ -54,10 +79,18 @@ public abstract class BaseFragment&lt;V extends BaseView, P extends BasePresenter&lt;V @@ -54,10 +79,18 @@ public abstract class BaseFragment&lt;V extends BaseView, P extends BasePresenter&lt;V
54 public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 79 public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
55 if (0 != getBindLayoutId()) { 80 if (0 != getBindLayoutId()) {
56 baseBinding = DataBindingUtil.inflate(inflater, getBindLayoutId(), container, false); 81 baseBinding = DataBindingUtil.inflate(inflater, getBindLayoutId(), container, false);
57 - return baseBinding.getRoot(); 82 + if (me.isOpenSwipBack()) {
  83 + return attachToSwipeBack(baseBinding.getRoot());
  84 + } else {
  85 + return baseBinding.getRoot();
  86 + }
58 } else if (0 != getViewLayoutId()) { 87 } else if (0 != getViewLayoutId()) {
59 baseView = inflater.inflate(getViewLayoutId(), container, false); 88 baseView = inflater.inflate(getViewLayoutId(), container, false);
60 - return baseView; 89 + if (me.isOpenSwipBack()) {
  90 + return attachToSwipeBack(baseView);
  91 + } else {
  92 + return baseView;
  93 + }
61 } 94 }
62 return super.onCreateView(inflater, container, savedInstanceState); 95 return super.onCreateView(inflater, container, savedInstanceState);
63 } 96 }
@@ -65,6 +98,9 @@ public abstract class BaseFragment&lt;V extends BaseView, P extends BasePresenter&lt;V @@ -65,6 +98,9 @@ public abstract class BaseFragment&lt;V extends BaseView, P extends BasePresenter&lt;V
65 @Override 98 @Override
66 public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { 99 public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
67 super.onViewCreated(view, savedInstanceState); 100 super.onViewCreated(view, savedInstanceState);
  101 + //创建订阅映射
  102 + SubscriptionManager.getInstance().setCurrentDisposables(TAG);
  103 + mSwipeDelegate.onViewCreated(view, savedInstanceState);
68 if (null != getMvpView() && null != getPresenter()) { 104 if (null != getMvpView() && null != getPresenter()) {
69 initBindingData(); 105 initBindingData();
70 initView(); 106 initView();
@@ -150,49 +186,51 @@ public abstract class BaseFragment&lt;V extends BaseView, P extends BasePresenter&lt;V @@ -150,49 +186,51 @@ public abstract class BaseFragment&lt;V extends BaseView, P extends BasePresenter&lt;V
150 */ 186 */
151 protected void setStatusBarColor(@ColorRes int color, 187 protected void setStatusBarColor(@ColorRes int color,
152 @IntRange(from = 0, to = 255) int statusBarAlpha) { 188 @IntRange(from = 0, to = 255) int statusBarAlpha) {
153 - StatusBarUtil.setColor(getActivity(), ContextCompat.getColor(getActivity(), color), statusBarAlpha); 189 + me.setStatusBarColor(color, statusBarAlpha);
154 } 190 }
155 191
156 - /**  
157 - * 设置状态栏字体颜色  
158 - */  
159 - protected void setStatusBarTextColor(int type) {  
160 - if (type == StatusBarConfig.BLACK) {  
161 - StatusBarUtil.setStatusBarWrite(getActivity());  
162 - } else if (type == StatusBarConfig.WHITE) {  
163 - StatusBarUtil.setStatusBarDarkMode(getActivity());  
164 - } 192 + public void setTransparentForWindow(Activity activity) {
  193 + me.setTransparentForWindow(activity);
165 } 194 }
166 195
167 - /**  
168 - * 隐藏软键盘  
169 - */  
170 - public void hideSoftInput() {  
171 - InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(INPUT_METHOD_SERVICE);  
172 - if (getActivity().getCurrentFocus() != null && null != imm) {  
173 - imm.hideSoftInputFromWindow(getActivity().getCurrentFocus().getWindowToken(), 0); 196 + public void addTranslucentView(Activity activity, @IntRange(from = 0, to = 255) int statusBarAlpha) {
  197 + me.addTranslucentView(activity, statusBarAlpha);
  198 + }
  199 +
  200 + @Override
  201 + public void onDestroy() {
  202 + mDelegate.onDestroy();
  203 + mSwipeDelegate.onDestroyView();
  204 + //清除当前订阅
  205 + SubscriptionManager.getInstance().cancel(TAG);
  206 + super.onDestroy();
  207 + if (null != baseBinding) {
  208 + baseBinding.unbind();
174 } 209 }
175 } 210 }
176 211
177 /** 212 /**
178 - * 显示软键盘 213 + * 设置状态栏字体颜色
179 */ 214 */
180 - public void showSoftInput() {  
181 - InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(INPUT_METHOD_SERVICE);  
182 - if (getActivity().getCurrentFocus() != null && null != imm) {  
183 - imm.showSoftInputFromInputMethod(getActivity().getCurrentFocus().getWindowToken(), 0);  
184 - } 215 + protected void setStatusBarTextColor(int type) {
  216 + me.setStatusBarTextColor(type);
185 } 217 }
186 218
  219 +
187 /** 220 /**
188 * 显示软键盘 221 * 显示软键盘
189 */ 222 */
190 - public void showSoftInput(View view) {  
191 - // InputMethodManager.SHOW_FORCED);  
192 - InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(INPUT_METHOD_SERVICE);  
193 - imm.showSoftInput(view, InputMethodManager.SHOW_FORCED); 223 + public void showSoftInput() {
  224 + me.showSoftInput();
194 } 225 }
195 226
  227 +// /**
  228 +// * 显示软键盘
  229 +// */
  230 +// public void showSoftInput(View view) {
  231 +// me.showSoftInput(view);
  232 +// }
  233 +
196 234
197 /*********************************************************/ 235 /*********************************************************/
198 //用于进行dip和px转换 236 //用于进行dip和px转换
@@ -220,6 +258,16 @@ public abstract class BaseFragment&lt;V extends BaseView, P extends BasePresenter&lt;V @@ -220,6 +258,16 @@ public abstract class BaseFragment&lt;V extends BaseView, P extends BasePresenter&lt;V
220 me.requestPermission(requestCode, defineTip, permissions, onPermissionResponseListener); 258 me.requestPermission(requestCode, defineTip, permissions, onPermissionResponseListener);
221 } 259 }
222 260
  261 + public void requestPermission(String[] permissions, String defineTip, OnPermissionResponseListener
  262 + onPermissionResponseListener) {
  263 + me.requestPermission(permissions, defineTip, onPermissionResponseListener);
  264 + }
  265 +
  266 + public void requestPermission(int requestCode, @StringRes int defineTip, String[]
  267 + permissions, OnPermissionResponseListener onPermissionResponseListener) {
  268 + me.requestPermission(requestCode, defineTip, permissions, onPermissionResponseListener);
  269 + }
  270 +
223 //多权限检查 271 //多权限检查
224 public boolean checkPermissions(String[] permissions) { 272 public boolean checkPermissions(String[] permissions) {
225 return me.checkPermissions(permissions); 273 return me.checkPermissions(permissions);
@@ -230,4 +278,481 @@ public abstract class BaseFragment&lt;V extends BaseView, P extends BasePresenter&lt;V @@ -230,4 +278,481 @@ public abstract class BaseFragment&lt;V extends BaseView, P extends BasePresenter&lt;V
230 return me.checkPermissions(permission); 278 return me.checkPermissions(permission);
231 } 279 }
232 280
  281 + /************************************fragment管理********************************************/
  282 + @Override
  283 + public SupportFragmentDelegate getSupportDelegate() {
  284 + return mDelegate;
  285 + }
  286 +
  287 + /**
  288 + * Perform some extra transactions.
  289 + * 额外的事务:自定义Tag,添加SharedElement动画,操作非回退栈Fragment
  290 + */
  291 + @Override
  292 + public ExtraTransaction extraTransaction() {
  293 + return mDelegate.extraTransaction();
  294 + }
  295 +
  296 + @Override
  297 + public void onAttach(Activity activity) {
  298 + super.onAttach(activity);
  299 + mDelegate.onAttach(activity);
  300 + me = (BaseActivity) mDelegate.getActivity();
  301 + }
  302 +
  303 + @Override
  304 + public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) {
  305 + return mDelegate.onCreateAnimation(transit, enter, nextAnim);
  306 + }
  307 +
  308 + @Override
  309 + public void onActivityCreated(@Nullable Bundle savedInstanceState) {
  310 + super.onActivityCreated(savedInstanceState);
  311 + mDelegate.onActivityCreated(savedInstanceState);
  312 + }
  313 +
  314 + @Override
  315 + public void onSaveInstanceState(Bundle outState) {
  316 + super.onSaveInstanceState(outState);
  317 + mDelegate.onSaveInstanceState(outState);
  318 + }
  319 +
  320 + @Override
  321 + public void onResume() {
  322 + super.onResume();
  323 + mDelegate.onResume();
  324 + }
  325 +
  326 + @Override
  327 + public void onPause() {
  328 + super.onPause();
  329 + mDelegate.onPause();
  330 + }
  331 +
  332 + @Override
  333 + public void onDestroyView() {
  334 + mDelegate.onDestroyView();
  335 + super.onDestroyView();
  336 + }
  337 +
  338 + @Override
  339 + public void onHiddenChanged(boolean hidden) {
  340 + super.onHiddenChanged(hidden);
  341 + mDelegate.onHiddenChanged(hidden);
  342 + mSwipeDelegate.onHiddenChanged(hidden);
  343 + }
  344 +
  345 + @Override
  346 + public void setUserVisibleHint(boolean isVisibleToUser) {
  347 + super.setUserVisibleHint(isVisibleToUser);
  348 + mDelegate.setUserVisibleHint(isVisibleToUser);
  349 + }
  350 +
  351 + public void finish() {
  352 + if (null != me) {
  353 + me.finish();
  354 + }
  355 + }
  356 +
  357 + /*************************************log******************************************/
  358 + public void logError(Object info) {
  359 + Logger.e(TAG, info);
  360 + }
  361 +
  362 + public void logDebug(Object info) {
  363 + Logger.d(TAG, info);
  364 + }
  365 +
  366 + public void logWarn(Object info) {
  367 + Logger.w(TAG, info);
  368 + }
  369 +
  370 + public void logInfo(Object info) {
  371 + Logger.i(TAG, info);
  372 + }
  373 +
  374 + public void logVerbose(Object info) {
  375 + Logger.v(TAG, info);
  376 + }
  377 +
  378 + public void logJson(String json) {
  379 + Logger.json(json);
  380 + }
  381 +
  382 + public void logXml(String xml) {
  383 + Logger.xml(xml);
  384 + }
  385 +/*********************************fragment 管理******************************************/
  386 + /**
  387 + * Causes the Runnable r to be added to the action queue.
  388 + * <p>
  389 + * The runnable will be run after all the previous action has been run.
  390 + * <p>
  391 + * 前面的事务全部执行后 执行该Action
  392 + *
  393 + * @deprecated Use {@link #post(Runnable)} instead.
  394 + */
  395 + @Deprecated
  396 + @Override
  397 + public void enqueueAction(Runnable runnable) {
  398 + mDelegate.enqueueAction(runnable);
  399 + }
  400 +
  401 + /**
  402 + * Causes the Runnable r to be added to the action queue.
  403 + * <p>
  404 + * The runnable will be run after all the previous action has been run.
  405 + * <p>
  406 + * 前面的事务全部执行后 执行该Action
  407 + */
  408 + @Override
  409 + public void post(Runnable runnable) {
  410 + mDelegate.post(runnable);
  411 + }
  412 +
  413 + /**
  414 + * Called when the enter-animation end.
  415 + * 入栈动画 结束时,回调
  416 + */
  417 + @Override
  418 + public void onEnterAnimationEnd(Bundle savedInstanceState) {
  419 + mDelegate.onEnterAnimationEnd(savedInstanceState);
  420 + }
  421 +
  422 +
  423 + /**
  424 + * Lazy initial,Called when fragment is first called.
  425 + * <p>
  426 + * 同级下的 懒加载 + ViewPager下的懒加载 的结合回调方法
  427 + */
  428 + @Override
  429 + public void onLazyInitView(@Nullable Bundle savedInstanceState) {
  430 + mDelegate.onLazyInitView(savedInstanceState);
  431 + }
  432 +
  433 + /**
  434 + * Called when the fragment is visible.
  435 + * 当Fragment对用户可见时回调
  436 + * <p>
  437 + * Is the combination of [onHiddenChanged() + onResume()/onPause() + setUserVisibleHint()]
  438 + */
  439 + @Override
  440 + public void onSupportVisible() {
  441 + mDelegate.onSupportVisible();
  442 + }
  443 +
  444 + /**
  445 + * Called when the fragment is invivible.
  446 + * <p>
  447 + * Is the combination of [onHiddenChanged() + onResume()/onPause() + setUserVisibleHint()]
  448 + */
  449 + @Override
  450 + public void onSupportInvisible() {
  451 + mDelegate.onSupportInvisible();
  452 + }
  453 +
  454 + /**
  455 + * Return true if the fragment has been supportVisible.
  456 + */
  457 + @Override
  458 + final public boolean isSupportVisible() {
  459 + return mDelegate.isSupportVisible();
  460 + }
  461 +
  462 + /**
  463 + * Set fragment animation with a higher priority than the ISupportActivity
  464 + * 设定当前Fragmemt动画,优先级比在SupportActivity里高
  465 + */
  466 + @Override
  467 + public FragmentAnimator onCreateFragmentAnimator() {
  468 + return mDelegate.onCreateFragmentAnimator();
  469 + }
  470 +
  471 + /**
  472 + * 获取设置的全局动画 copy
  473 + *
  474 + * @return FragmentAnimator
  475 + */
  476 + @Override
  477 + public FragmentAnimator getFragmentAnimator() {
  478 + return mDelegate.getFragmentAnimator();
  479 + }
  480 +
  481 + /**
  482 + * 设置Fragment内的全局动画
  483 + */
  484 + @Override
  485 + public void setFragmentAnimator(FragmentAnimator fragmentAnimator) {
  486 + mDelegate.setFragmentAnimator(fragmentAnimator);
  487 + }
  488 +
  489 + /**
  490 + * 按返回键触发,前提是SupportActivity的onBackPressed()方法能被调用
  491 + *
  492 + * @return false则继续向上传递, true则消费掉该事件
  493 + */
  494 + @Override
  495 + public boolean onBackPressedSupport() {
  496 + return mDelegate.onBackPressedSupport();
  497 + }
  498 +
  499 + /**
  500 + * 类似 {@link Activity#setResult(int, Intent)}
  501 + * <p>
  502 + * Similar to {@link Activity#setResult(int, Intent)}
  503 + *
  504 + * @see #startForResult(ISupportFragment, int)
  505 + */
  506 + @Override
  507 + public void setFragmentResult(int resultCode, Bundle bundle) {
  508 + mDelegate.setFragmentResult(resultCode, bundle);
  509 + }
  510 +
  511 + /**
  512 + * 类似 {@link Activity#onActivityResult(int, int, Intent)}
  513 + * <p>
  514 + * Similar to {@link Activity#onActivityResult(int, int, Intent)}
  515 + *
  516 + * @see #startForResult(ISupportFragment, int)
  517 + */
  518 + @Override
  519 + public void onFragmentResult(int requestCode, int resultCode, Bundle data) {
  520 + mDelegate.onFragmentResult(requestCode, resultCode, data);
  521 + }
  522 +
  523 + /**
  524 + * 在start(TargetFragment,LaunchMode)时,启动模式为SingleTask/SingleTop, 回调TargetFragment的该方法
  525 + * 类似 {@link Activity#onNewIntent(Intent)}
  526 + * <p>
  527 + * Similar to {@link Activity#onNewIntent(Intent)}
  528 + *
  529 + * @param args putNewBundle(Bundle newBundle)
  530 + * @see #start(ISupportFragment, int)
  531 + */
  532 + @Override
  533 + public void onNewBundle(Bundle args) {
  534 + mDelegate.onNewBundle(args);
  535 + }
  536 +
  537 + /**
  538 + * 添加NewBundle,用于启动模式为SingleTask/SingleTop时
  539 + *
  540 + * @see #start(ISupportFragment, int)
  541 + */
  542 + @Override
  543 + public void putNewBundle(Bundle newBundle) {
  544 + mDelegate.putNewBundle(newBundle);
  545 + }
  546 +
  547 +
  548 + /****************************************以下为可选方法(Optional methods)******************************************************/
  549 +
  550 + /**
  551 + * 隐藏软键盘
  552 + */
  553 + protected void hideSoftInput() {
  554 + mDelegate.hideSoftInput();
  555 + }
  556 +
  557 + /**
  558 + * 显示软键盘,调用该方法后,会在onPause时自动隐藏软键盘
  559 + */
  560 + protected void showSoftInput(final View view) {
  561 + mDelegate.showSoftInput(view);
  562 + }
  563 +
  564 + /**
  565 + * 加载根Fragment, 即Activity内的第一个Fragment 或 Fragment内的第一个子Fragment
  566 + *
  567 + * @param containerId 容器id
  568 + * @param toFragment 目标Fragment
  569 + */
  570 + public void loadRootFragment(int containerId, ISupportFragment toFragment) {
  571 + mDelegate.loadRootFragment(containerId, toFragment);
  572 + }
  573 +
  574 + public void loadRootFragment(int containerId, ISupportFragment toFragment, boolean addToBackStack, boolean allowAnim) {
  575 + mDelegate.loadRootFragment(containerId, toFragment, addToBackStack, allowAnim);
  576 + }
  577 +
  578 + /**
  579 + * 加载多个同级根Fragment,类似Wechat, QQ主页的场景
  580 + */
  581 + public void loadMultipleRootFragment(int containerId, int showPosition, ISupportFragment... toFragments) {
  582 + mDelegate.loadMultipleRootFragment(containerId, showPosition, toFragments);
  583 + }
  584 +
  585 + /**
  586 + * show一个Fragment,hide其他同栈所有Fragment
  587 + * 使用该方法时,要确保同级栈内无多余的Fragment,(只有通过loadMultipleRootFragment()载入的Fragment)
  588 + * <p>
  589 + * 建议使用更明确的{@link #showHideFragment(ISupportFragment, ISupportFragment)}
  590 + *
  591 + * @param showFragment 需要show的Fragment
  592 + */
  593 + public void showHideFragment(ISupportFragment showFragment) {
  594 + mDelegate.showHideFragment(showFragment);
  595 + }
  596 +
  597 + /**
  598 + * show一个Fragment,hide一个Fragment ; 主要用于类似微信主页那种 切换tab的情况
  599 + */
  600 + public void showHideFragment(ISupportFragment showFragment, ISupportFragment hideFragment) {
  601 + mDelegate.showHideFragment(showFragment, hideFragment);
  602 + }
  603 +
  604 + public void start(ISupportFragment toFragment) {
  605 + mDelegate.start(toFragment);
  606 + }
  607 +
  608 + /**
  609 + * @param launchMode Similar to Activity's LaunchMode.
  610 + */
  611 + public void start(final ISupportFragment toFragment, @LaunchMode int launchMode) {
  612 + mDelegate.start(toFragment, launchMode);
  613 + }
  614 +
  615 + /**
  616 + * Launch an fragment for which you would like a result when it poped.
  617 + */
  618 + public void startForResult(ISupportFragment toFragment, int requestCode) {
  619 + mDelegate.startForResult(toFragment, requestCode);
  620 + }
  621 +
  622 + /**
  623 + * Start the target Fragment and pop itself
  624 + */
  625 + public void startWithPop(ISupportFragment toFragment) {
  626 + mDelegate.startWithPop(toFragment);
  627 + }
  628 +
  629 + /**
  630 + * @see #popTo(Class, boolean)
  631 + * +
  632 + * @see #start(ISupportFragment)
  633 + */
  634 + public void startWithPopTo(ISupportFragment toFragment, Class<?> targetFragmentClass, boolean includeTargetFragment) {
  635 + mDelegate.startWithPopTo(toFragment, targetFragmentClass, includeTargetFragment);
  636 + }
  637 +
  638 +
  639 + public void replaceFragment(ISupportFragment toFragment, boolean addToBackStack) {
  640 + mDelegate.replaceFragment(toFragment, addToBackStack);
  641 + }
  642 +
  643 + public void pop() {
  644 + mDelegate.pop();
  645 + }
  646 +
  647 + /**
  648 + * Pop the child fragment.
  649 + */
  650 + public void popChild() {
  651 + mDelegate.popChild();
  652 + }
  653 +
  654 + /**
  655 + * Pop the last fragment transition from the manager's fragment
  656 + * back stack.
  657 + * <p>
  658 + * 出栈到目标fragment
  659 + *
  660 + * @param targetFragmentClass 目标fragment
  661 + * @param includeTargetFragment 是否包含该fragment
  662 + */
  663 + public void popTo(Class<?> targetFragmentClass, boolean includeTargetFragment) {
  664 + mDelegate.popTo(targetFragmentClass, includeTargetFragment);
  665 + }
  666 +
  667 + /**
  668 + * If you want to begin another FragmentTransaction immediately after popTo(), use this method.
  669 + * 如果你想在出栈后, 立刻进行FragmentTransaction操作,请使用该方法
  670 + */
  671 + public void popTo(Class<?> targetFragmentClass, boolean includeTargetFragment, Runnable afterPopTransactionRunnable) {
  672 + mDelegate.popTo(targetFragmentClass, includeTargetFragment, afterPopTransactionRunnable);
  673 + }
  674 +
  675 + public void popTo(Class<?> targetFragmentClass, boolean includeTargetFragment, Runnable afterPopTransactionRunnable, int popAnim) {
  676 + mDelegate.popTo(targetFragmentClass, includeTargetFragment, afterPopTransactionRunnable, popAnim);
  677 + }
  678 +
  679 + public void popToChild(Class<?> targetFragmentClass, boolean includeTargetFragment) {
  680 + mDelegate.popToChild(targetFragmentClass, includeTargetFragment);
  681 + }
  682 +
  683 + public void popToChild(Class<?> targetFragmentClass, boolean includeTargetFragment, Runnable afterPopTransactionRunnable) {
  684 + mDelegate.popToChild(targetFragmentClass, includeTargetFragment, afterPopTransactionRunnable);
  685 + }
  686 +
  687 + public void popToChild(Class<?> targetFragmentClass, boolean includeTargetFragment, Runnable afterPopTransactionRunnable, int popAnim) {
  688 + mDelegate.popToChild(targetFragmentClass, includeTargetFragment, afterPopTransactionRunnable, popAnim);
  689 + }
  690 +
  691 + /**
  692 + * 得到位于栈顶Fragment
  693 + */
  694 + public ISupportFragment getTopFragment() {
  695 + return SupportHelper.getTopFragment(getFragmentManager());
  696 + }
  697 +
  698 + public ISupportFragment getTopChildFragment() {
  699 + return SupportHelper.getTopFragment(getChildFragmentManager());
  700 + }
  701 +
  702 + /**
  703 + * @return 位于当前Fragment的前一个Fragment
  704 + */
  705 + public ISupportFragment getPreFragment() {
  706 + return SupportHelper.getPreFragment(this);
  707 + }
  708 +
  709 + /**
  710 + * 获取栈内的fragment对象
  711 + */
  712 + public <T extends ISupportFragment> T findFragment(Class<T> fragmentClass) {
  713 + return SupportHelper.findFragment(getFragmentManager(), fragmentClass);
  714 + }
  715 +
  716 + /**
  717 + * 获取栈内的fragment对象
  718 + */
  719 + public <T extends ISupportFragment> T findChildFragment(Class<T> fragmentClass) {
  720 + return SupportHelper.findFragment(getChildFragmentManager(), fragmentClass);
  721 + }
  722 +
  723 + /*****************************侧滑返回************************************/
  724 + @Override
  725 + public View attachToSwipeBack(View view) {
  726 + return mSwipeDelegate.attachToSwipeBack(view);
  727 + }
  728 +
  729 + public SwipeBackLayout getSwipeBackLayout() {
  730 + return mSwipeDelegate.getSwipeBackLayout();
  731 + }
  732 +
  733 + /**
  734 + * 是否可滑动
  735 + *
  736 + * @param enable
  737 + */
  738 + public void setSwipeBackEnable(boolean enable) {
  739 + mSwipeDelegate.setSwipeBackEnable(enable);
  740 + }
  741 +
  742 + @Override
  743 + public void setEdgeLevel(SwipeBackLayout.EdgeLevel edgeLevel) {
  744 + mSwipeDelegate.setEdgeLevel(edgeLevel);
  745 + }
  746 +
  747 + @Override
  748 + public void setEdgeLevel(int widthPixel) {
  749 + mSwipeDelegate.setEdgeLevel(widthPixel);
  750 + }
  751 +
  752 + /**
  753 + * Set the offset of the parallax slip.
  754 + */
  755 + public void setParallaxOffset(@FloatRange(from = 0.0f, to = 1.0f) float offset) {
  756 + mSwipeDelegate.setParallaxOffset(offset);
  757 + }
233 } 758 }
core/base/src/main/java/com/cnlive/core/libs/base/frame/presenter/BasePresenter.java
@@ -2,6 +2,7 @@ package com.cnlive.core.libs.base.frame.presenter; @@ -2,6 +2,7 @@ package com.cnlive.core.libs.base.frame.presenter;
2 2
3 import com.cnlive.core.libs.base.frame.view.BaseView; 3 import com.cnlive.core.libs.base.frame.view.BaseView;
4 import com.hannesdorfmann.mosby3.mvp.MvpBasePresenter; 4 import com.hannesdorfmann.mosby3.mvp.MvpBasePresenter;
  5 +import com.orhanobut.logger.Logger;
5 6
6 public class BasePresenter<V extends BaseView> extends MvpBasePresenter<V> { 7 public class BasePresenter<V extends BaseView> extends MvpBasePresenter<V> {
7 protected final String TAG = this.getClass().getSimpleName(); 8 protected final String TAG = this.getClass().getSimpleName();
@@ -17,4 +18,32 @@ public class BasePresenter&lt;V extends BaseView&gt; extends MvpBasePresenter&lt;V&gt; { @@ -17,4 +18,32 @@ public class BasePresenter&lt;V extends BaseView&gt; extends MvpBasePresenter&lt;V&gt; {
17 // public V getView() { 18 // public V getView() {
18 // return super.getView(); 19 // return super.getView();
19 // } 20 // }
  21 +
  22 + public void logError(Object info) {
  23 + Logger.e(TAG, info);
  24 + }
  25 +
  26 + public void logDebug(Object info) {
  27 + Logger.d(TAG, info);
  28 + }
  29 +
  30 + public void logWarn(Object info) {
  31 + Logger.w(TAG, info);
  32 + }
  33 +
  34 + public void logInfo(Object info) {
  35 + Logger.i(TAG, info);
  36 + }
  37 +
  38 + public void logVerbose(Object info) {
  39 + Logger.v(TAG, info);
  40 + }
  41 +
  42 + public void logJson(String json) {
  43 + Logger.json(json);
  44 + }
  45 +
  46 + public void logXml(String xml) {
  47 + Logger.xml(xml);
  48 + }
20 } 49 }
core/base/src/main/java/com/cnlive/core/libs/base/frame/view/BaseView.java
1 package com.cnlive.core.libs.base.frame.view; 1 package com.cnlive.core.libs.base.frame.view;
2 2
3 import com.hannesdorfmann.mosby3.mvp.MvpView; 3 import com.hannesdorfmann.mosby3.mvp.MvpView;
  4 +import com.orhanobut.logger.Logger;
4 5
5 /** 6 /**
6 * @author ys 7 * @author ys
@@ -22,4 +23,32 @@ public class BaseView implements MvpView { @@ -22,4 +23,32 @@ public class BaseView implements MvpView {
22 } 23 }
23 return false; 24 return false;
24 } 25 }
  26 +
  27 + public void logError(Object info) {
  28 + Logger.e(TAG, info);
  29 + }
  30 +
  31 + public void logDebug(Object info) {
  32 + Logger.d(TAG, info);
  33 + }
  34 +
  35 + public void logWarn(Object info) {
  36 + Logger.w(TAG, info);
  37 + }
  38 +
  39 + public void logInfo(Object info) {
  40 + Logger.i(TAG, info);
  41 + }
  42 +
  43 + public void logVerbose(Object info) {
  44 + Logger.v(TAG, info);
  45 + }
  46 +
  47 + public void logJson(String json) {
  48 + Logger.json(json);
  49 + }
  50 +
  51 + public void logXml(String xml) {
  52 + Logger.xml(xml);
  53 + }
25 } 54 }
core/base/src/main/java/com/cnlive/core/libs/base/ui/widget/BottomSheet.java 0 → 100644
  1 +package com.cnlive.core.libs.base.ui.widget;
  2 +
  3 +import android.app.Dialog;
  4 +import android.content.Context;
  5 +import android.os.Bundle;
  6 +import android.text.TextUtils;
  7 +import android.util.Log;
  8 +import android.view.Gravity;
  9 +import android.view.LayoutInflater;
  10 +import android.view.View;
  11 +import android.view.ViewGroup;
  12 +import android.view.WindowManager;
  13 +import android.view.animation.AlphaAnimation;
  14 +import android.view.animation.Animation;
  15 +import android.view.animation.AnimationSet;
  16 +import android.view.animation.DecelerateInterpolator;
  17 +import android.view.animation.TranslateAnimation;
  18 +import android.widget.BaseAdapter;
  19 +import android.widget.ListView;
  20 +import android.widget.TextView;
  21 +
  22 +import androidx.annotation.NonNull;
  23 +
  24 +import com.cnlive.core.libs.base.util.DensityUtils;
  25 +import com.cnlive.strike.base.R;
  26 +import com.qmuiteam.qmui.QMUILog;
  27 +import com.qmuiteam.qmui.util.QMUIDisplayHelper;
  28 +import com.qmuiteam.qmui.util.QMUILangHelper;
  29 +import com.qmuiteam.qmui.util.QMUIResHelper;
  30 +
  31 +import java.util.ArrayList;
  32 +import java.util.List;
  33 +
  34 +/**
  35 + * QMUIBottomSheet 在 {@link Dialog} 的基础上重新定制了 {@link #show()} 和 {@link #hide()} 时的动画效果, 使 {@link Dialog} 在界面底部升起和降下。
  36 + * <p>
  37 + * 提供了以下两种面板样式:
  38 + * <ul>
  39 + * <li>列表样式, 使用 {@link BottomSheet.BottomListSheetBuilder} 生成。</li>
  40 + * </ul>
  41 + * </p>
  42 + */
  43 +public class BottomSheet extends Dialog {
  44 + private static final String TAG = "QMUIBottomSheet";
  45 + // 动画时长
  46 + private final static int mAnimationDuration = 200;
  47 + // 持有 ContentView,为了做动画
  48 + private View mContentView;
  49 + private boolean mIsAnimating = false;
  50 +
  51 + private OnBottomSheetShowListener mOnBottomSheetShowListener;
  52 +
  53 + public BottomSheet(Context context) {
  54 + super(context, com.qmuiteam.qmui.R.style.QMUI_BottomSheet);
  55 + }
  56 +
  57 + public void setOnBottomSheetShowListener(OnBottomSheetShowListener onBottomSheetShowListener) {
  58 + mOnBottomSheetShowListener = onBottomSheetShowListener;
  59 + }
  60 +
  61 + @Override
  62 + protected void onCreate(Bundle savedInstanceState) {
  63 + super.onCreate(savedInstanceState);
  64 +
  65 + //noinspection ConstantConditions
  66 + getWindow().getDecorView().setPadding(0, 0, 0, 0);
  67 +
  68 + // 在底部,宽度撑满
  69 + WindowManager.LayoutParams params = getWindow().getAttributes();
  70 + params.height = ViewGroup.LayoutParams.WRAP_CONTENT;
  71 + params.gravity = Gravity.BOTTOM | Gravity.CENTER;
  72 +
  73 + int screenWidth = QMUIDisplayHelper.getScreenWidth(getContext());
  74 + int screenHeight = QMUIDisplayHelper.getScreenHeight(getContext());
  75 + params.width = screenWidth < screenHeight ? screenWidth : screenHeight;
  76 + getWindow().setAttributes(params);
  77 + setCanceledOnTouchOutside(true);
  78 + }
  79 +
  80 + @Override
  81 + public void setContentView(int layoutResID) {
  82 + mContentView = LayoutInflater.from(getContext()).inflate(layoutResID, null);
  83 + super.setContentView(mContentView);
  84 + }
  85 +
  86 + @Override
  87 + public void setContentView(@NonNull View view, ViewGroup.LayoutParams params) {
  88 + mContentView = view;
  89 + super.setContentView(view, params);
  90 + }
  91 +
  92 + public View getContentView() {
  93 + return mContentView;
  94 + }
  95 +
  96 + @Override
  97 + public void setContentView(@NonNull View view) {
  98 + mContentView = view;
  99 + super.setContentView(view);
  100 + }
  101 +
  102 + /**
  103 + * BottomSheet升起动画
  104 + */
  105 + private void animateUp() {
  106 + if (mContentView == null) {
  107 + return;
  108 + }
  109 + TranslateAnimation translate = new TranslateAnimation(
  110 + Animation.RELATIVE_TO_SELF, 0f, Animation.RELATIVE_TO_SELF, 0f,
  111 + Animation.RELATIVE_TO_SELF, 1f, Animation.RELATIVE_TO_SELF, 0f
  112 + );
  113 + AlphaAnimation alpha = new AlphaAnimation(0, 1);
  114 + AnimationSet set = new AnimationSet(true);
  115 + set.addAnimation(translate);
  116 + set.addAnimation(alpha);
  117 + set.setInterpolator(new DecelerateInterpolator());
  118 + set.setDuration(mAnimationDuration);
  119 + set.setFillAfter(true);
  120 + mContentView.startAnimation(set);
  121 + }
  122 +
  123 + /**
  124 + * BottomSheet降下动画
  125 + */
  126 + private void animateDown() {
  127 + if (mContentView == null) {
  128 + return;
  129 + }
  130 + TranslateAnimation translate = new TranslateAnimation(
  131 + Animation.RELATIVE_TO_SELF, 0f, Animation.RELATIVE_TO_SELF, 0f,
  132 + Animation.RELATIVE_TO_SELF, 0f, Animation.RELATIVE_TO_SELF, 1f
  133 + );
  134 + AlphaAnimation alpha = new AlphaAnimation(1, 0);
  135 + AnimationSet set = new AnimationSet(true);
  136 + set.addAnimation(translate);
  137 + set.addAnimation(alpha);
  138 + set.setInterpolator(new DecelerateInterpolator());
  139 + set.setDuration(mAnimationDuration);
  140 + set.setFillAfter(true);
  141 + set.setAnimationListener(new Animation.AnimationListener() {
  142 + @Override
  143 + public void onAnimationStart(Animation animation) {
  144 + mIsAnimating = true;
  145 + }
  146 +
  147 + @Override
  148 + public void onAnimationEnd(Animation animation) {
  149 + mIsAnimating = false;
  150 + /**
  151 + * Bugfix: Attempting to destroy the window while drawing!
  152 + */
  153 + mContentView.post(new Runnable() {
  154 + @Override
  155 + public void run() {
  156 + // java.lang.IllegalArgumentException: View=com.android.internal.policy.PhoneWindow$DecorView{22dbf5b V.E...... R......D 0,0-1080,1083} not attached to window manager
  157 + // 在dismiss的时候可能已经detach了,简单try-catch一下
  158 + try {
  159 + BottomSheet.super.dismiss();
  160 + } catch (Exception e) {
  161 + QMUILog.w(TAG, "dismiss error\n" + Log.getStackTraceString(e));
  162 + }
  163 + }
  164 + });
  165 + }
  166 +
  167 + @Override
  168 + public void onAnimationRepeat(Animation animation) {
  169 +
  170 + }
  171 + });
  172 + mContentView.startAnimation(set);
  173 + }
  174 +
  175 + @Override
  176 + public void show() {
  177 + super.show();
  178 + animateUp();
  179 + if (mOnBottomSheetShowListener != null) {
  180 + mOnBottomSheetShowListener.onShow();
  181 + }
  182 + }
  183 +
  184 + @Override
  185 + public void dismiss() {
  186 + if (mIsAnimating) {
  187 + return;
  188 + }
  189 + animateDown();
  190 + }
  191 +
  192 + /**
  193 + * 销毁提示窗
  194 + *
  195 + * @param animation 是否启动动画
  196 + */
  197 + public void dismiss(boolean animation) {
  198 + if (animation) {
  199 + dismiss();
  200 + } else {
  201 + super.dismiss();
  202 + }
  203 + }
  204 +
  205 + public interface OnBottomSheetShowListener {
  206 + void onShow();
  207 + }
  208 +
  209 + /**
  210 + * 生成列表类型的 {@link BottomSheet} 对话框。
  211 + */
  212 + public static class BottomListSheetBuilder {
  213 +
  214 + private Context mContext;
  215 +
  216 + private BottomSheet mDialog;
  217 + private List<BottomSheetListItemData> mItems;
  218 + private BaseAdapter mAdapter;
  219 + private List<View> mHeaderViews;
  220 + private ListView mContainerView;
  221 + private int mCheckedIndex;
  222 + private String mTitle;
  223 + private TextView mTitleTv;
  224 + private OnSheetItemClickListener mOnSheetItemClickListener;
  225 + private OnDismissListener mOnBottomDialogDismissListener;
  226 +
  227 +
  228 + public BottomListSheetBuilder(Context context) {
  229 + mContext = context;
  230 + mItems = new ArrayList<>();
  231 + mHeaderViews = new ArrayList<>();
  232 + }
  233 +
  234 + public BottomListSheetBuilder setCheckedIndex(int checkedIndex) {
  235 + mCheckedIndex = checkedIndex;
  236 + return this;
  237 + }
  238 +
  239 + /**
  240 + * @param textAndTag Item 的文字内容,同时会把内容设置为 tag。
  241 + */
  242 + public BottomListSheetBuilder addItem(String textAndTag) {
  243 + mItems.add(new BottomSheetListItemData(textAndTag, textAndTag, null, false));
  244 + return this;
  245 + }
  246 +
  247 + /**
  248 + * @param textAndTag Item 的文字内容,同时会把内容设置为 tag。
  249 + * @param split 是否显示分割线
  250 + */
  251 + public BottomListSheetBuilder addItem(String textAndTag, boolean split) {
  252 + mItems.add(new BottomSheetListItemData(textAndTag, textAndTag, null, split));
  253 + return this;
  254 + }
  255 +
  256 + /**
  257 + * @param subTitle 副标题文字内容
  258 + * @param textAndTag Item 的文字内容,同时会把内容设置为 tag。
  259 + * @param split 是否显示分割线
  260 + * @return
  261 + */
  262 + public BottomListSheetBuilder addItem(String textAndTag, String subTitle, boolean split) {
  263 + mItems.add(new BottomSheetListItemData(textAndTag, textAndTag, subTitle, split));
  264 + return this;
  265 + }
  266 +
  267 + /**
  268 + * @param text Item 的文字内容。
  269 + * @param tag item 的 tag。
  270 + */
  271 + public BottomListSheetBuilder addItem(String text, String tag) {
  272 + mItems.add(new BottomSheetListItemData(text, tag));
  273 + return this;
  274 + }
  275 +
  276 +
  277 + public BottomListSheetBuilder setOnSheetItemClickListener(OnSheetItemClickListener onSheetItemClickListener) {
  278 + mOnSheetItemClickListener = onSheetItemClickListener;
  279 + return this;
  280 + }
  281 +
  282 + public BottomListSheetBuilder setOnBottomDialogDismissListener(OnDismissListener listener) {
  283 + mOnBottomDialogDismissListener = listener;
  284 + return this;
  285 + }
  286 +
  287 + public BottomListSheetBuilder addHeaderView(View view) {
  288 + if (view != null) {
  289 + mHeaderViews.add(view);
  290 + }
  291 + return this;
  292 + }
  293 +
  294 + public BottomListSheetBuilder setTitle(String title) {
  295 + mTitle = title;
  296 + return this;
  297 + }
  298 +
  299 + public BottomListSheetBuilder setTitle(int resId) {
  300 + mTitle = mContext.getResources().getString(resId);
  301 + return this;
  302 + }
  303 +
  304 + public BottomSheet build() {
  305 + mDialog = new BottomSheet(mContext);
  306 + View contentView = buildViews();
  307 + mDialog.setContentView(contentView,
  308 + new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
  309 + if (mOnBottomDialogDismissListener != null) {
  310 + mDialog.setOnDismissListener(mOnBottomDialogDismissListener);
  311 + }
  312 + return mDialog;
  313 + }
  314 +
  315 + private View buildViews() {
  316 + View wrapperView = View.inflate(mContext, getContentViewLayoutId(), null);
  317 + mTitleTv = (TextView) wrapperView.findViewById(com.qmuiteam.qmui.R.id.title);
  318 + mContainerView = (ListView) wrapperView.findViewById(com.qmuiteam.qmui.R.id.listview);
  319 + if (mTitle != null && mTitle.length() != 0) {
  320 + mTitleTv.setVisibility(View.VISIBLE);
  321 + mTitleTv.setText(mTitle);
  322 + } else {
  323 + mTitleTv.setVisibility(View.GONE);
  324 + }
  325 + if (mHeaderViews.size() > 0) {
  326 + for (View headerView : mHeaderViews) {
  327 + mContainerView.addHeaderView(headerView);
  328 + }
  329 + }
  330 + if (needToScroll()) {
  331 + mContainerView.getLayoutParams().height = getListMaxHeight();
  332 + mDialog.setOnBottomSheetShowListener(new OnBottomSheetShowListener() {
  333 + @Override
  334 + public void onShow() {
  335 + mContainerView.setSelection(mCheckedIndex);
  336 + }
  337 + });
  338 + }
  339 +
  340 + mAdapter = new ListAdapter();
  341 + mContainerView.setAdapter(mAdapter);
  342 + return wrapperView;
  343 + }
  344 +
  345 + private boolean needToScroll() {
  346 + int itemHeight = QMUIResHelper.getAttrDimen(mContext, com.qmuiteam.qmui.R.attr.qmui_bottom_sheet_list_item_height);
  347 + int totalHeight = mItems.size() * itemHeight;
  348 + if (mHeaderViews.size() > 0) {
  349 + for (View view : mHeaderViews) {
  350 + if (view.getMeasuredHeight() == 0) {
  351 + view.measure(0, 0);
  352 + }
  353 + totalHeight += view.getMeasuredHeight();
  354 + }
  355 + }
  356 + if (mTitleTv != null && !QMUILangHelper.isNullOrEmpty(mTitle)) {
  357 + totalHeight += QMUIResHelper.getAttrDimen(mContext, com.qmuiteam.qmui.R.attr.qmui_bottom_sheet_title_height);
  358 + }
  359 + return totalHeight > getListMaxHeight();
  360 + }
  361 +
  362 + /**
  363 + * 注意:这里只考虑List的高度,如果有title或者headerView,不计入考虑中
  364 + */
  365 + protected int getListMaxHeight() {
  366 + return (int) (QMUIDisplayHelper.getScreenHeight(mContext) * 0.5);
  367 + }
  368 +
  369 + public void notifyDataSetChanged() {
  370 + if (mAdapter != null) {
  371 + mAdapter.notifyDataSetChanged();
  372 + }
  373 + if (needToScroll()) {
  374 + mContainerView.getLayoutParams().height = getListMaxHeight();
  375 + mContainerView.setSelection(mCheckedIndex);
  376 + }
  377 + }
  378 +
  379 + protected int getContentViewLayoutId() {
  380 + return R.layout.qmui_bottom_sheet_list;
  381 + }
  382 +
  383 + public interface OnSheetItemClickListener {
  384 + void onClick(BottomSheet dialog, View itemView, int position, String tag);
  385 + }
  386 +
  387 + private static class BottomSheetListItemData {
  388 +
  389 + String text;
  390 + String tag = "";
  391 + boolean isDisabled = false;
  392 + boolean split = false;
  393 + String subTitle;
  394 +
  395 + public BottomSheetListItemData(String text, String tag, String subTitle, boolean split) {
  396 + this.text = text;
  397 + this.tag = tag;
  398 + this.split = split;
  399 + this.subTitle = subTitle;
  400 + }
  401 +
  402 + public BottomSheetListItemData(String text, String tag) {
  403 + this.text = text;
  404 + this.tag = tag;
  405 + }
  406 +
  407 +
  408 + }
  409 +
  410 + private static class ViewHolder {
  411 + TextView textView;
  412 + TextView subTextView;
  413 + View bottonBar;
  414 + View itemView;
  415 + }
  416 +
  417 + private class ListAdapter extends BaseAdapter {
  418 +
  419 + @Override
  420 + public int getCount() {
  421 + return mItems.size();
  422 + }
  423 +
  424 + @Override
  425 + public BottomSheetListItemData getItem(int position) {
  426 + return mItems.get(position);
  427 + }
  428 +
  429 + @Override
  430 + public long getItemId(int position) {
  431 + return 0;
  432 + }
  433 +
  434 + @Override
  435 + public View getView(final int position, View convertView, ViewGroup parent) {
  436 + final BottomSheetListItemData data = getItem(position);
  437 + final ViewHolder holder;
  438 + if (convertView == null) {
  439 + LayoutInflater inflater = LayoutInflater.from(mContext);
  440 + convertView = inflater.inflate(R.layout.qmui_bottom_sheet_list_item, parent, false);
  441 + holder = new ViewHolder();
  442 + holder.textView = (TextView) convertView.findViewById(com.qmuiteam.qmui.R.id.bottom_dialog_list_item_title);
  443 + holder.bottonBar = convertView.findViewById(R.id.botton_bar);
  444 + holder.subTextView = convertView.findViewById(R.id.bottom_dialog_list_item_subtitle);
  445 + holder.itemView = convertView.findViewById(R.id.itemView);
  446 + convertView.setTag(holder);
  447 + } else {
  448 + holder = (ViewHolder) convertView.getTag();
  449 + }
  450 + // holder.textView.setTextColor(mContext.getResources().getColor(R.color.qmui_config_color_red));
  451 + if (data.text.equals("取消")){
  452 + holder.textView.setTextColor(mContext.getResources().getColor(R.color.gay));
  453 + }else {
  454 + holder.textView.setTextColor(mContext.getResources().getColor(R.color.green));
  455 + }
  456 + holder.textView.setText(data.text);
  457 +
  458 + if (data.isDisabled) {
  459 + holder.textView.setEnabled(false);
  460 + convertView.setEnabled(false);
  461 + } else {
  462 + holder.textView.setEnabled(true);
  463 + convertView.setEnabled(true);
  464 + }
  465 +
  466 + if (data.split) {
  467 + holder.bottonBar.setVisibility(View.VISIBLE);
  468 + } else {
  469 + holder.bottonBar.setVisibility(View.GONE);
  470 + }
  471 + if (TextUtils.isEmpty(data.subTitle)) {
  472 + holder.subTextView.setText("");
  473 + holder.subTextView.setVisibility(View.GONE);
  474 + holder.itemView.getLayoutParams().height = DensityUtils.dp2px(56);
  475 + } else {
  476 + holder.itemView.getLayoutParams().height = DensityUtils.dp2px(61);
  477 + holder.subTextView.setText(data.subTitle);
  478 + holder.subTextView.setVisibility(View.VISIBLE);
  479 + }
  480 +
  481 + convertView.setOnClickListener(new View.OnClickListener() {
  482 + @Override
  483 + public void onClick(View v) {
  484 + if (mOnSheetItemClickListener != null) {
  485 + mOnSheetItemClickListener.onClick(mDialog, v, position, data.tag);
  486 + }
  487 + }
  488 + });
  489 + return convertView;
  490 + }
  491 + }
  492 +
  493 + }
  494 +
  495 +}
core/base/src/main/java/com/cnlive/core/libs/base/ui/widget/switchbutton/ColorUtils.java 0 → 100644
  1 +package com.cnlive.core.libs.base.ui.widget.switchbutton;
  2 +
  3 +import android.content.res.ColorStateList;
  4 +
  5 +/**
  6 + * Generate thumb and background color state list use tintColor
  7 + * Created by kyle on 15/11/4.
  8 + */
  9 +public class ColorUtils {
  10 + private static final int ENABLE_ATTR = android.R.attr.state_enabled;
  11 + private static final int CHECKED_ATTR = android.R.attr.state_checked;
  12 + private static final int PRESSED_ATTR = android.R.attr.state_pressed;
  13 +
  14 + static ColorStateList generateThumbColorWithTintColor(final int tintColor) {
  15 + int[][] states = new int[][]{
  16 + {-ENABLE_ATTR, CHECKED_ATTR},
  17 + {-ENABLE_ATTR},
  18 + {PRESSED_ATTR, -CHECKED_ATTR},
  19 + {PRESSED_ATTR, CHECKED_ATTR},
  20 + {CHECKED_ATTR},
  21 + {-CHECKED_ATTR}
  22 + };
  23 +
  24 + int[] colors = new int[]{
  25 + tintColor - 0xAA000000,
  26 + 0xFFBABABA,
  27 + tintColor - 0x99000000,
  28 + tintColor - 0x99000000,
  29 + tintColor | 0xFF000000,
  30 + 0xFFEEEEEE
  31 + };
  32 + return new ColorStateList(states, colors);
  33 + }
  34 +
  35 + static ColorStateList generateBackColorWithTintColor(final int tintColor) {
  36 + int[][] states = new int[][]{
  37 + {-ENABLE_ATTR, CHECKED_ATTR},
  38 + {-ENABLE_ATTR},
  39 + {CHECKED_ATTR, PRESSED_ATTR},
  40 + {-CHECKED_ATTR, PRESSED_ATTR},
  41 + {CHECKED_ATTR},
  42 + {-CHECKED_ATTR}
  43 + };
  44 +
  45 + int[] colors = new int[]{
  46 + tintColor - 0xE1000000,
  47 + 0x10000000,
  48 + tintColor - 0xD0000000,
  49 + 0x20000000,
  50 + tintColor - 0xD0000000,
  51 + 0x20000000
  52 + };
  53 + return new ColorStateList(states, colors);
  54 + }
  55 +}
core/base/src/main/java/com/cnlive/core/libs/base/ui/widget/switchbutton/SwitchButton.java 0 → 100644
  1 +package com.cnlive.core.libs.base.ui.widget.switchbutton;
  2 +
  3 +import android.animation.ObjectAnimator;
  4 +import android.annotation.SuppressLint;
  5 +import android.content.Context;
  6 +import android.content.res.ColorStateList;
  7 +import android.content.res.Resources;
  8 +import android.content.res.TypedArray;
  9 +import android.graphics.Canvas;
  10 +import android.graphics.Color;
  11 +import android.graphics.Paint;
  12 +import android.graphics.PointF;
  13 +import android.graphics.RectF;
  14 +import android.graphics.drawable.Drawable;
  15 +import android.graphics.drawable.StateListDrawable;
  16 +import android.os.Parcel;
  17 +import android.os.Parcelable;
  18 +import android.text.Layout;
  19 +import android.text.StaticLayout;
  20 +import android.text.TextPaint;
  21 +import android.text.TextUtils;
  22 +import android.util.AttributeSet;
  23 +import android.util.TypedValue;
  24 +import android.view.MotionEvent;
  25 +import android.view.SoundEffectConstants;
  26 +import android.view.ViewConfiguration;
  27 +import android.view.ViewParent;
  28 +import android.view.animation.AccelerateDecelerateInterpolator;
  29 +import android.widget.CompoundButton;
  30 +
  31 +import androidx.core.content.ContextCompat;
  32 +
  33 +import com.cnlive.strike.base.R;
  34 +
  35 +
  36 +/**
  37 + * SwitchButton
  38 + *
  39 + * @author kyleduo
  40 + * @since 2014-09-24
  41 + */
  42 +
  43 +@SuppressWarnings("unused")
  44 +public class SwitchButton extends CompoundButton {
  45 + public static final float DEFAULT_THUMB_RANGE_RATIO = 1.8f;
  46 + public static final int DEFAULT_THUMB_SIZE_DP = 20;
  47 + public static final int DEFAULT_THUMB_MARGIN_DP = 2;
  48 + public static final int DEFAULT_ANIMATION_DURATION = 250;
  49 + public static final int DEFAULT_TINT_COLOR = 0x327FC2;
  50 +
  51 + private static int[] CHECKED_PRESSED_STATE = new int[]{android.R.attr.state_checked, android.R.attr.state_enabled, android.R.attr.state_pressed};
  52 + private static int[] UNCHECKED_PRESSED_STATE = new int[]{-android.R.attr.state_checked, android.R.attr.state_enabled, android.R.attr.state_pressed};
  53 +
  54 + private Drawable mThumbDrawable, mBackDrawable;
  55 + private ColorStateList mBackColor, mThumbColor;
  56 + private float mThumbRadius, mBackRadius;
  57 + private RectF mThumbMargin;
  58 + private float mThumbRangeRatio;
  59 + private long mAnimationDuration;
  60 + // fade back drawable or color when dragging or animating
  61 + private boolean mFadeBack;
  62 + private int mTintColor;
  63 + private int mThumbWidth;
  64 + private int mThumbHeight;
  65 + private int mBackWidth;
  66 + private int mBackHeight;
  67 +
  68 + private int mCurrThumbColor, mCurrBackColor, mNextBackColor, mOnTextColor, mOffTextColor;
  69 + private Drawable mCurrentBackDrawable, mNextBackDrawable;
  70 + private RectF mThumbRectF, mBackRectF, mSafeRectF, mTextOnRectF, mTextOffRectF;
  71 + private Paint mPaint;
  72 + // whether using Drawable for thumb or back
  73 + private boolean mIsThumbUseDrawable, mIsBackUseDrawable;
  74 + private boolean mDrawDebugRect = false;
  75 + private ObjectAnimator mProgressAnimator;
  76 + // animation control
  77 + private float mProgress;
  78 + // temp position of thumb when dragging or animating
  79 + private RectF mPresentThumbRectF;
  80 + private float mStartX, mStartY, mLastX;
  81 + private int mTouchSlop;
  82 + private int mClickTimeout;
  83 + private Paint mRectPaint;
  84 + private CharSequence mTextOn;
  85 + private CharSequence mTextOff;
  86 + private TextPaint mTextPaint;
  87 + private Layout mOnLayout;
  88 + private Layout mOffLayout;
  89 + private float mTextWidth;
  90 + private float mTextHeight;
  91 + private int mTextThumbInset;
  92 + private int mTextExtra;
  93 + private int mTextAdjust;
  94 + // FIX #78,#85 : When restoring saved states, setChecked() called by super. So disable
  95 + // animation and event listening when restoring.
  96 + private boolean mRestoring = false;
  97 + private boolean mReady = false;
  98 + private boolean mCatch = false;
  99 +
  100 + private OnCheckedChangeListener mChildOnCheckedChangeListener;
  101 +
  102 + public SwitchButton(Context context, AttributeSet attrs, int defStyle) {
  103 + super(context, attrs, defStyle);
  104 + init(attrs);
  105 + }
  106 +
  107 + public SwitchButton(Context context, AttributeSet attrs) {
  108 + super(context, attrs);
  109 + init(attrs);
  110 + }
  111 +
  112 + public SwitchButton(Context context) {
  113 + super(context);
  114 + init(null);
  115 + }
  116 +
  117 + private void init(AttributeSet attrs) {
  118 + mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
  119 + mClickTimeout = ViewConfiguration.getPressedStateDuration() + ViewConfiguration.getTapTimeout();
  120 +
  121 + mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
  122 + mRectPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
  123 + mRectPaint.setStyle(Paint.Style.STROKE);
  124 + mRectPaint.setStrokeWidth(getResources().getDisplayMetrics().density);
  125 +
  126 + mTextPaint = getPaint();
  127 +
  128 + mThumbRectF = new RectF();
  129 + mBackRectF = new RectF();
  130 + mSafeRectF = new RectF();
  131 + mThumbMargin = new RectF();
  132 + mTextOnRectF = new RectF();
  133 + mTextOffRectF = new RectF();
  134 +
  135 + mProgressAnimator = ObjectAnimator.ofFloat(this, "progress", 0, 0).setDuration(DEFAULT_ANIMATION_DURATION);
  136 + mProgressAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
  137 +
  138 + mPresentThumbRectF = new RectF();
  139 +
  140 + Resources res = getResources();
  141 + float density = res.getDisplayMetrics().density;
  142 +
  143 + Drawable thumbDrawable = null;
  144 + ColorStateList thumbColor = null;
  145 + float margin = density * DEFAULT_THUMB_MARGIN_DP;
  146 + float marginLeft = 0;
  147 + float marginRight = 0;
  148 + float marginTop = 0;
  149 + float marginBottom = 0;
  150 + float thumbWidth = 0;
  151 + float thumbHeight = 0;
  152 + float thumbRadius = -1;
  153 + float backRadius = -1;
  154 + Drawable backDrawable = null;
  155 + ColorStateList backColor = null;
  156 + float thumbRangeRatio = DEFAULT_THUMB_RANGE_RATIO;
  157 + int animationDuration = DEFAULT_ANIMATION_DURATION;
  158 + boolean fadeBack = true;
  159 + int tintColor = 0;
  160 + String textOn = null;
  161 + String textOff = null;
  162 + int textThumbInset = 0;
  163 + int textExtra = 0;
  164 + int textAdjust = 0;
  165 +
  166 + TypedArray ta = attrs == null ? null : getContext().obtainStyledAttributes(attrs, R.styleable.SwitchButton);
  167 + if (ta != null) {
  168 + thumbDrawable = ta.getDrawable(R.styleable.SwitchButton_kswThumbDrawable);
  169 + thumbColor = ta.getColorStateList(R.styleable.SwitchButton_kswThumbColor);
  170 + margin = ta.getDimension(R.styleable.SwitchButton_kswThumbMargin, margin);
  171 + marginLeft = ta.getDimension(R.styleable.SwitchButton_kswThumbMarginLeft, margin);
  172 + marginRight = ta.getDimension(R.styleable.SwitchButton_kswThumbMarginRight, margin);
  173 + marginTop = ta.getDimension(R.styleable.SwitchButton_kswThumbMarginTop, margin);
  174 + marginBottom = ta.getDimension(R.styleable.SwitchButton_kswThumbMarginBottom, margin);
  175 + thumbWidth = ta.getDimension(R.styleable.SwitchButton_kswThumbWidth, thumbWidth);
  176 + thumbHeight = ta.getDimension(R.styleable.SwitchButton_kswThumbHeight, thumbHeight);
  177 + thumbRadius = ta.getDimension(R.styleable.SwitchButton_kswThumbRadius, thumbRadius);
  178 + backRadius = ta.getDimension(R.styleable.SwitchButton_kswBackRadius, backRadius);
  179 + backDrawable = ta.getDrawable(R.styleable.SwitchButton_kswBackDrawable);
  180 + backColor = ta.getColorStateList(R.styleable.SwitchButton_kswBackColor);
  181 + thumbRangeRatio = ta.getFloat(R.styleable.SwitchButton_kswThumbRangeRatio, thumbRangeRatio);
  182 + animationDuration = ta.getInteger(R.styleable.SwitchButton_kswAnimationDuration, animationDuration);
  183 + fadeBack = ta.getBoolean(R.styleable.SwitchButton_kswFadeBack, true);
  184 + tintColor = ta.getColor(R.styleable.SwitchButton_kswTintColor, tintColor);
  185 + textOn = ta.getString(R.styleable.SwitchButton_kswTextOn);
  186 + textOff = ta.getString(R.styleable.SwitchButton_kswTextOff);
  187 + textThumbInset = ta.getDimensionPixelSize(R.styleable.SwitchButton_kswTextThumbInset, 0);
  188 + textExtra = ta.getDimensionPixelSize(R.styleable.SwitchButton_kswTextExtra, 0);
  189 + textAdjust = ta.getDimensionPixelSize(R.styleable.SwitchButton_kswTextAdjust, 0);
  190 + ta.recycle();
  191 + }
  192 +
  193 + // click
  194 + ta = attrs == null ? null : getContext().obtainStyledAttributes(attrs, new int[]{android.R.attr.focusable, android.R.attr.clickable});
  195 + if (ta != null) {
  196 + boolean focusable = ta.getBoolean(0, true);
  197 + //noinspection ResourceType
  198 + @SuppressLint("ResourceType")
  199 + boolean clickable = ta.getBoolean(1, focusable);
  200 + setFocusable(focusable);
  201 + setClickable(clickable);
  202 + ta.recycle();
  203 + } else {
  204 + setFocusable(true);
  205 + setClickable(true);
  206 + }
  207 +
  208 + // text
  209 + mTextOn = textOn;
  210 + mTextOff = textOff;
  211 + mTextThumbInset = textThumbInset;
  212 + mTextExtra = textExtra;
  213 + mTextAdjust = textAdjust;
  214 +
  215 + // thumb drawable and color
  216 + mThumbDrawable = thumbDrawable;
  217 + mThumbColor = thumbColor;
  218 + mIsThumbUseDrawable = mThumbDrawable != null;
  219 + mTintColor = tintColor;
  220 + if (mTintColor == 0) {
  221 + TypedValue typedValue = new TypedValue();
  222 + boolean found = getContext().getTheme().resolveAttribute(R.attr.colorAccent, typedValue, true);
  223 + if (found) {
  224 + mTintColor = typedValue.data;
  225 + } else {
  226 + mTintColor = DEFAULT_TINT_COLOR;
  227 + }
  228 + }
  229 + if (!mIsThumbUseDrawable && mThumbColor == null) {
  230 + mThumbColor = ColorUtils.generateThumbColorWithTintColor(mTintColor);
  231 + mCurrThumbColor = mThumbColor.getDefaultColor();
  232 + }
  233 +
  234 + // thumbSize
  235 + mThumbWidth = ceil(thumbWidth);
  236 + mThumbHeight = ceil(thumbHeight);
  237 +
  238 + // back drawable and color
  239 + mBackDrawable = backDrawable;
  240 + mBackColor = backColor;
  241 + mIsBackUseDrawable = mBackDrawable != null;
  242 + if (!mIsBackUseDrawable && mBackColor == null) {
  243 + mBackColor = ColorUtils.generateBackColorWithTintColor(mTintColor);
  244 + mCurrBackColor = mBackColor.getDefaultColor();
  245 + mNextBackColor = mBackColor.getColorForState(CHECKED_PRESSED_STATE, mCurrBackColor);
  246 + }
  247 +
  248 + // margin
  249 + mThumbMargin.set(marginLeft, marginTop, marginRight, marginBottom);
  250 +
  251 + // size & measure params must larger than 1
  252 + mThumbRangeRatio = mThumbMargin.width() >= 0 ? Math.max(thumbRangeRatio, 1) : thumbRangeRatio;
  253 +
  254 + mThumbRadius = thumbRadius;
  255 + mBackRadius = backRadius;
  256 + mAnimationDuration = animationDuration;
  257 + mFadeBack = fadeBack;
  258 +
  259 + mProgressAnimator.setDuration(mAnimationDuration);
  260 +
  261 + // sync checked status
  262 + if (isChecked()) {
  263 + setProgress(1);
  264 + }
  265 + }
  266 +
  267 +
  268 + private Layout makeLayout(CharSequence text) {
  269 + return new StaticLayout(text, mTextPaint, (int) Math.ceil(Layout.getDesiredWidth(text, mTextPaint)), Layout.Alignment.ALIGN_CENTER, 1.f, 0, false);
  270 + }
  271 +
  272 + @Override
  273 + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  274 + /*
  275 + * ensure textLayout
  276 + */
  277 + if (mOnLayout == null && !TextUtils.isEmpty(mTextOn)) {
  278 + mOnLayout = makeLayout(mTextOn);
  279 + }
  280 + if (mOffLayout == null && !TextUtils.isEmpty(mTextOff)) {
  281 + mOffLayout = makeLayout(mTextOff);
  282 + }
  283 +
  284 + float onWidth = mOnLayout != null ? mOnLayout.getWidth() : 0;
  285 + float offWidth = mOffLayout != null ? mOffLayout.getWidth() : 0;
  286 + if (onWidth != 0 || offWidth != 0) {
  287 + mTextWidth = Math.max(onWidth, offWidth);
  288 + } else {
  289 + mTextWidth = 0;
  290 + }
  291 +
  292 + float onHeight = mOnLayout != null ? mOnLayout.getHeight() : 0;
  293 + float offHeight = mOffLayout != null ? mOffLayout.getHeight() : 0;
  294 + if (onHeight != 0 || offHeight != 0) {
  295 + mTextHeight = Math.max(onHeight, offHeight);
  296 + } else {
  297 + mTextHeight = 0;
  298 + }
  299 +
  300 + setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));
  301 + }
  302 +
  303 + /**
  304 + * SwitchButton use this formula to determine the final size of thumb, background and itself.
  305 + *
  306 + * textWidth = max(onWidth, offWidth)
  307 + * thumbRange = thumbWidth * rangeRatio
  308 + * textExtraSpace = textWidth + textExtra - (moveRange - thumbWidth + max(thumbMargin.left, thumbMargin.right) + textThumbInset)
  309 + * backWidth = thumbRange + thumbMargin.left + thumbMargin.right + max(textExtraSpace, 0)
  310 + * contentSize = thumbRange + max(thumbMargin.left, 0) + max(thumbMargin.right, 0) + max(textExtraSpace, 0)
  311 + *
  312 + * @param widthMeasureSpec widthMeasureSpec
  313 + * @return measuredWidth
  314 + */
  315 + private int measureWidth(int widthMeasureSpec) {
  316 + int widthSize = MeasureSpec.getSize(widthMeasureSpec);
  317 + int widthMode = MeasureSpec.getMode(widthMeasureSpec);
  318 + int measuredWidth = widthSize;
  319 +
  320 + if (mThumbWidth == 0 && mIsThumbUseDrawable) {
  321 + mThumbWidth = mThumbDrawable.getIntrinsicWidth();
  322 + }
  323 +
  324 + int moveRange;
  325 + int textWidth = ceil(mTextWidth);
  326 + // how much the background should extend to fit text.
  327 + int textExtraSpace;
  328 + int contentSize;
  329 +
  330 + if (mThumbRangeRatio == 0) {
  331 + mThumbRangeRatio = DEFAULT_THUMB_RANGE_RATIO;
  332 + }
  333 +
  334 + if (widthMode == MeasureSpec.EXACTLY) {
  335 + contentSize = widthSize - getPaddingLeft() - getPaddingRight();
  336 +
  337 + if (mThumbWidth != 0) {
  338 + moveRange = ceil(mThumbWidth * mThumbRangeRatio);
  339 + textExtraSpace = textWidth + mTextExtra - (moveRange - mThumbWidth + ceil(Math.max(mThumbMargin.left, mThumbMargin.right)));
  340 + mBackWidth = ceil(moveRange + mThumbMargin.left + mThumbMargin.right + Math.max(textExtraSpace, 0));
  341 + if (mBackWidth < 0) {
  342 + mThumbWidth = 0;
  343 + }
  344 + if (moveRange + Math.max(mThumbMargin.left, 0) + Math.max(mThumbMargin.right, 0) + Math.max(textExtraSpace, 0) > contentSize) {
  345 + mThumbWidth = 0;
  346 + }
  347 + }
  348 +
  349 + if (mThumbWidth == 0) {
  350 + contentSize = widthSize - getPaddingLeft() - getPaddingRight();
  351 + moveRange = ceil(contentSize - Math.max(mThumbMargin.left, 0) - Math.max(mThumbMargin.right, 0));
  352 + if (moveRange < 0) {
  353 + mThumbWidth = 0;
  354 + mBackWidth = 0;
  355 + return measuredWidth;
  356 + }
  357 + mThumbWidth = ceil(moveRange / mThumbRangeRatio);
  358 + mBackWidth = ceil(moveRange + mThumbMargin.left + mThumbMargin.right);
  359 + if (mBackWidth < 0) {
  360 + mThumbWidth = 0;
  361 + mBackWidth = 0;
  362 + return measuredWidth;
  363 + }
  364 + textExtraSpace = textWidth + mTextExtra - (moveRange - mThumbWidth + ceil(Math.max(mThumbMargin.left, mThumbMargin.right)));
  365 + if (textExtraSpace > 0) {
  366 + // since backWidth is determined by view width, so we can only reduce thumbSize.
  367 + mThumbWidth = mThumbWidth - textExtraSpace;
  368 + }
  369 + if (mThumbWidth < 0) {
  370 + mThumbWidth = 0;
  371 + mBackWidth = 0;
  372 + return measuredWidth;
  373 + }
  374 + }
  375 + } else {
  376 + /*
  377 + If parent view want SwitchButton to determine it's size itself, we calculate the minimal
  378 + size of it's content. Further more, we ignore the limitation of widthSize since we want
  379 + to display SwitchButton in its actual size rather than compress the shape.
  380 + */
  381 + if (mThumbWidth == 0) {
  382 + /*
  383 + If thumbWidth is not set, use the default one.
  384 + */
  385 + mThumbWidth = ceil(getResources().getDisplayMetrics().density * DEFAULT_THUMB_SIZE_DP);
  386 + }
  387 + if (mThumbRangeRatio == 0) {
  388 + mThumbRangeRatio = DEFAULT_THUMB_RANGE_RATIO;
  389 + }
  390 +
  391 + moveRange = ceil(mThumbWidth * mThumbRangeRatio);
  392 + textExtraSpace = ceil(textWidth + mTextExtra - (moveRange - mThumbWidth + Math.max(mThumbMargin.left, mThumbMargin.right) + mTextThumbInset));
  393 + mBackWidth = ceil(moveRange + mThumbMargin.left + mThumbMargin.right + Math.max(0, textExtraSpace));
  394 + if (mBackWidth < 0) {
  395 + mThumbWidth = 0;
  396 + mBackWidth = 0;
  397 + return measuredWidth;
  398 + }
  399 + contentSize = ceil(moveRange + Math.max(0, mThumbMargin.left) + Math.max(0, mThumbMargin.right) + Math.max(0, textExtraSpace));
  400 +
  401 + measuredWidth = Math.max(contentSize, contentSize + getPaddingLeft() + getPaddingRight());
  402 + }
  403 + return measuredWidth;
  404 + }
  405 +
  406 + private int measureHeight(int heightMeasureSpec) {
  407 + int heightSize = MeasureSpec.getSize(heightMeasureSpec);
  408 + int heightMode = MeasureSpec.getMode(heightMeasureSpec);
  409 + int measuredHeight = heightSize;
  410 +
  411 + if (mThumbHeight == 0 && mIsThumbUseDrawable) {
  412 + mThumbHeight = mThumbDrawable.getIntrinsicHeight();
  413 + }
  414 + int contentSize;
  415 + int textExtraSpace;
  416 + if (heightMode == MeasureSpec.EXACTLY) {
  417 + if (mThumbHeight != 0) {
  418 + /*
  419 + If thumbHeight has been set, we calculate backHeight and check if there is enough room.
  420 + */
  421 + mBackHeight = ceil(mThumbHeight + mThumbMargin.top + mThumbMargin.bottom);
  422 + mBackHeight = ceil(Math.max(mBackHeight, mTextHeight));
  423 + if (mBackHeight + getPaddingTop() + getPaddingBottom() - Math.min(0, mThumbMargin.top) - Math.min(0, mThumbMargin.bottom) > heightSize) {
  424 + // No enough room, we set thumbHeight to zero to calculate these value again.
  425 + mThumbHeight = 0;
  426 + }
  427 + }
  428 +
  429 + if (mThumbHeight == 0) {
  430 + mBackHeight = ceil(heightSize - getPaddingTop() - getPaddingBottom() + Math.min(0, mThumbMargin.top) + Math.min(0, mThumbMargin.bottom));
  431 + if (mBackHeight < 0) {
  432 + mBackHeight = 0;
  433 + mThumbHeight = 0;
  434 + return measuredHeight;
  435 + }
  436 + mThumbHeight = ceil(mBackHeight - mThumbMargin.top - mThumbMargin.bottom);
  437 + }
  438 + if (mThumbHeight < 0) {
  439 + mBackHeight = 0;
  440 + mThumbHeight = 0;
  441 + return measuredHeight;
  442 + }
  443 + } else {
  444 + if (mThumbHeight == 0) {
  445 + mThumbHeight = ceil(getResources().getDisplayMetrics().density * DEFAULT_THUMB_SIZE_DP);
  446 + }
  447 + mBackHeight = ceil(mThumbHeight + mThumbMargin.top + mThumbMargin.bottom);
  448 + if (mBackHeight < 0) {
  449 + mBackHeight = 0;
  450 + mThumbHeight = 0;
  451 + return measuredHeight;
  452 + }
  453 + textExtraSpace = ceil(mTextHeight - mBackHeight);
  454 + if (textExtraSpace > 0) {
  455 + mBackHeight += textExtraSpace;
  456 + mThumbHeight += textExtraSpace;
  457 + }
  458 + contentSize = Math.max(mThumbHeight, mBackHeight);
  459 +
  460 + measuredHeight = Math.max(contentSize, contentSize + getPaddingTop() + getPaddingBottom());
  461 + measuredHeight = Math.max(measuredHeight, getSuggestedMinimumHeight());
  462 + }
  463 +
  464 + return measuredHeight;
  465 + }
  466 +
  467 + @Override
  468 + protected void onSizeChanged(int w, int h, int oldw, int oldh) {
  469 + super.onSizeChanged(w, h, oldw, oldh);
  470 + if (w != oldw || h != oldh) {
  471 + setup();
  472 + }
  473 + }
  474 +
  475 + private int ceil(double dimen) {
  476 + return (int) Math.ceil(dimen);
  477 + }
  478 +
  479 + /**
  480 + * set up the rect of back and thumb
  481 + */
  482 + private void setup() {
  483 + if (mThumbWidth == 0 || mThumbHeight == 0 || mBackWidth == 0 || mBackHeight == 0) {
  484 + return;
  485 + }
  486 +
  487 + if (mThumbRadius == -1) {
  488 + mThumbRadius = Math.min(mThumbWidth, mThumbHeight) / 2;
  489 + }
  490 + if (mBackRadius == -1) {
  491 + mBackRadius = Math.min(mBackWidth, mBackHeight) / 2;
  492 + }
  493 +
  494 + int contentWidth = getMeasuredWidth() - getPaddingLeft() - getPaddingRight();
  495 + int contentHeight = getMeasuredHeight() - getPaddingTop() - getPaddingBottom();
  496 +
  497 + // max range of drawing content, when thumbMargin is negative, drawing range is larger than backWidth
  498 + int drawingWidth = ceil(mBackWidth - Math.min(0, mThumbMargin.left) - Math.min(0, mThumbMargin.right));
  499 + int drawingHeight = ceil(mBackHeight - Math.min(0, mThumbMargin.top) - Math.min(0, mThumbMargin.bottom));
  500 +
  501 + float thumbTop;
  502 + if (contentHeight <= drawingHeight) {
  503 + thumbTop = getPaddingTop() + Math.max(0, mThumbMargin.top);
  504 + } else {
  505 + // center vertical in content area
  506 + thumbTop = getPaddingTop() + Math.max(0, mThumbMargin.top) + (contentHeight - drawingHeight + 1) / 2;
  507 + }
  508 +
  509 + float thumbLeft;
  510 + if (contentWidth <= mBackWidth) {
  511 + thumbLeft = getPaddingLeft() + Math.max(0, mThumbMargin.left);
  512 + } else {
  513 + thumbLeft = getPaddingLeft() + Math.max(0, mThumbMargin.left) + (contentWidth - drawingWidth + 1) / 2;
  514 + }
  515 +
  516 + mThumbRectF.set(thumbLeft, thumbTop, thumbLeft + mThumbWidth, thumbTop + mThumbHeight);
  517 +
  518 + float backLeft = mThumbRectF.left - mThumbMargin.left;
  519 + mBackRectF.set(backLeft,
  520 + mThumbRectF.top - mThumbMargin.top,
  521 + backLeft + mBackWidth,
  522 + mThumbRectF.top - mThumbMargin.top + mBackHeight);
  523 +
  524 + mSafeRectF.set(mThumbRectF.left, 0, mBackRectF.right - mThumbMargin.right - mThumbRectF.width(), 0);
  525 +
  526 + float minBackRadius = Math.min(mBackRectF.width(), mBackRectF.height()) / 2.f;
  527 + mBackRadius = Math.min(minBackRadius, mBackRadius);
  528 +
  529 + if (mBackDrawable != null) {
  530 + mBackDrawable.setBounds((int) mBackRectF.left, (int) mBackRectF.top, ceil(mBackRectF.right), ceil(mBackRectF.bottom));
  531 + }
  532 +
  533 + if (mOnLayout != null) {
  534 + float onLeft = mBackRectF.left + (mBackRectF.width() + mTextThumbInset - mThumbWidth - mThumbMargin.right - mOnLayout.getWidth()) / 2f - mTextAdjust;
  535 + float onTop = mBackRectF.top + (mBackRectF.height() - mOnLayout.getHeight()) / 2;
  536 + mTextOnRectF.set(onLeft, onTop, onLeft + mOnLayout.getWidth(), onTop + mOnLayout.getHeight());
  537 + }
  538 +
  539 + if (mOffLayout != null) {
  540 + float offLeft = mBackRectF.right - (mBackRectF.width() + mTextThumbInset - mThumbWidth - mThumbMargin.left - mOffLayout.getWidth()) / 2f - mOffLayout.getWidth() + mTextAdjust;
  541 + float offTop = mBackRectF.top + (mBackRectF.height() - mOffLayout.getHeight()) / 2;
  542 + mTextOffRectF.set(offLeft, offTop, offLeft + mOffLayout.getWidth(), offTop + mOffLayout.getHeight());
  543 + }
  544 +
  545 + mReady = true;
  546 + }
  547 +
  548 + @Override
  549 + protected void onDraw(Canvas canvas) {
  550 + super.onDraw(canvas);
  551 +
  552 + if (!mReady) {
  553 + setup();
  554 + }
  555 + if (!mReady) {
  556 + return;
  557 + }
  558 +
  559 + // fade back
  560 + if (mIsBackUseDrawable) {
  561 + if (mFadeBack && mCurrentBackDrawable != null && mNextBackDrawable != null) {
  562 + // fix #75, 70%A + 30%B != 30%B + 70%A, order matters when mix two layer of different alpha.
  563 + // So make sure the order of on/off layers never change during slide from one endpoint to another.
  564 + Drawable below = isChecked() ? mCurrentBackDrawable : mNextBackDrawable;
  565 + Drawable above = isChecked() ? mNextBackDrawable : mCurrentBackDrawable;
  566 +
  567 + int alpha = (int) (255 * getProgress());
  568 + below.setAlpha(alpha);
  569 + below.draw(canvas);
  570 + alpha = 255 - alpha;
  571 + above.setAlpha(alpha);
  572 + above.draw(canvas);
  573 + } else {
  574 + mBackDrawable.setAlpha(255);
  575 + mBackDrawable.draw(canvas);
  576 + }
  577 + } else {
  578 + if (mFadeBack) {
  579 + int alpha;
  580 + int colorAlpha;
  581 +
  582 + // fix #75
  583 + int belowColor = isChecked() ? mCurrBackColor : mNextBackColor;
  584 + int aboveColor = isChecked() ? mNextBackColor : mCurrBackColor;
  585 +
  586 + // curr back
  587 + alpha = (int) (255 * getProgress());
  588 + colorAlpha = Color.alpha(belowColor);
  589 + colorAlpha = colorAlpha * alpha / 255;
  590 + mPaint.setARGB(colorAlpha, Color.red(belowColor), Color.green(belowColor), Color.blue(belowColor));
  591 + canvas.drawRoundRect(mBackRectF, mBackRadius, mBackRadius, mPaint);
  592 +
  593 + // next back
  594 + alpha = 255 - alpha;
  595 + colorAlpha = Color.alpha(aboveColor);
  596 + colorAlpha = colorAlpha * alpha / 255;
  597 + mPaint.setARGB(colorAlpha, Color.red(aboveColor), Color.green(aboveColor), Color.blue(aboveColor));
  598 + canvas.drawRoundRect(mBackRectF, mBackRadius, mBackRadius, mPaint);
  599 +
  600 + mPaint.setAlpha(255);
  601 + } else {
  602 + mPaint.setColor(mCurrBackColor);
  603 + canvas.drawRoundRect(mBackRectF, mBackRadius, mBackRadius, mPaint);
  604 + }
  605 + }
  606 +
  607 + // text
  608 + Layout switchText = getProgress() > 0.5 ? mOnLayout : mOffLayout;
  609 + RectF textRectF = getProgress() > 0.5 ? mTextOnRectF : mTextOffRectF;
  610 + if (switchText != null && textRectF != null) {
  611 + int alpha = (int) (255 * (getProgress() >= 0.75 ? getProgress() * 4 - 3 : (getProgress() < 0.25 ? 1 - getProgress() * 4 : 0)));
  612 + int textColor = getProgress() > 0.5 ? mOnTextColor : mOffTextColor;
  613 + int colorAlpha = Color.alpha(textColor);
  614 + colorAlpha = colorAlpha * alpha / 255;
  615 + switchText.getPaint().setARGB(colorAlpha, Color.red(textColor), Color.green(textColor), Color.blue(textColor));
  616 + canvas.save();
  617 + canvas.translate(textRectF.left, textRectF.top);
  618 + switchText.draw(canvas);
  619 + canvas.restore();
  620 + }
  621 +
  622 + // thumb
  623 + mPresentThumbRectF.set(mThumbRectF);
  624 + mPresentThumbRectF.offset(mProgress * mSafeRectF.width(), 0);
  625 + if (mIsThumbUseDrawable) {
  626 + mThumbDrawable.setBounds((int) mPresentThumbRectF.left, (int) mPresentThumbRectF.top, ceil(mPresentThumbRectF.right), ceil(mPresentThumbRectF.bottom));
  627 + mThumbDrawable.draw(canvas);
  628 + } else {
  629 + mPaint.setColor(mCurrThumbColor);
  630 + canvas.drawRoundRect(mPresentThumbRectF, mThumbRadius, mThumbRadius, mPaint);
  631 + }
  632 +
  633 + if (mDrawDebugRect) {
  634 + mRectPaint.setColor(Color.parseColor("#AA0000"));
  635 + canvas.drawRect(mBackRectF, mRectPaint);
  636 + mRectPaint.setColor(Color.parseColor("#0000FF"));
  637 + canvas.drawRect(mPresentThumbRectF, mRectPaint);
  638 + mRectPaint.setColor(Color.parseColor("#000000"));
  639 + canvas.drawLine(mSafeRectF.left, mThumbRectF.top, mSafeRectF.right, mThumbRectF.top, mRectPaint);
  640 + mRectPaint.setColor(Color.parseColor("#00CC00"));
  641 + canvas.drawRect(getProgress() > 0.5 ? mTextOnRectF : mTextOffRectF, mRectPaint);
  642 + }
  643 + }
  644 +
  645 + @Override
  646 + protected void drawableStateChanged() {
  647 + super.drawableStateChanged();
  648 +
  649 + if (!mIsThumbUseDrawable && mThumbColor != null) {
  650 + mCurrThumbColor = mThumbColor.getColorForState(getDrawableState(), mCurrThumbColor);
  651 + } else {
  652 + setDrawableState(mThumbDrawable);
  653 + }
  654 +
  655 + int[] nextState = isChecked() ? UNCHECKED_PRESSED_STATE : CHECKED_PRESSED_STATE;
  656 + ColorStateList textColors = getTextColors();
  657 + if (textColors != null) {
  658 + int defaultTextColor = textColors.getDefaultColor();
  659 + mOnTextColor = textColors.getColorForState(CHECKED_PRESSED_STATE, defaultTextColor);
  660 + mOffTextColor = textColors.getColorForState(UNCHECKED_PRESSED_STATE, defaultTextColor);
  661 + }
  662 + if (!mIsBackUseDrawable && mBackColor != null) {
  663 + mCurrBackColor = mBackColor.getColorForState(getDrawableState(), mCurrBackColor);
  664 + mNextBackColor = mBackColor.getColorForState(nextState, mCurrBackColor);
  665 + } else {
  666 + if (mBackDrawable instanceof StateListDrawable && mFadeBack) {
  667 + mBackDrawable.setState(nextState);
  668 + mNextBackDrawable = mBackDrawable.getCurrent().mutate();
  669 + } else {
  670 + mNextBackDrawable = null;
  671 + }
  672 + setDrawableState(mBackDrawable);
  673 + if (mBackDrawable != null) {
  674 + mCurrentBackDrawable = mBackDrawable.getCurrent().mutate();
  675 + }
  676 + }
  677 + }
  678 +
  679 + @Override
  680 + public boolean onTouchEvent(MotionEvent event) {
  681 +
  682 + if (!isEnabled() || !isClickable() || !isFocusable() || !mReady) {
  683 + return false;
  684 + }
  685 +
  686 + int action = event.getAction();
  687 +
  688 + float deltaX = event.getX() - mStartX;
  689 + float deltaY = event.getY() - mStartY;
  690 +
  691 + switch (action) {
  692 + case MotionEvent.ACTION_DOWN:
  693 + mStartX = event.getX();
  694 + mStartY = event.getY();
  695 + mLastX = mStartX;
  696 + setPressed(true);
  697 + break;
  698 +
  699 + case MotionEvent.ACTION_MOVE:
  700 + float x = event.getX();
  701 + setProgress(getProgress() + (x - mLastX) / mSafeRectF.width());
  702 + if (!mCatch && (Math.abs(deltaX) > mTouchSlop / 2 || Math.abs(deltaY) > mTouchSlop / 2)) {
  703 + if (deltaY == 0 || Math.abs(deltaX) > Math.abs(deltaY)) {
  704 + catchView();
  705 + } else if (Math.abs(deltaY) > Math.abs(deltaX)) {
  706 + return false;
  707 + }
  708 + }
  709 + mLastX = x;
  710 + break;
  711 +
  712 + case MotionEvent.ACTION_CANCEL:
  713 + case MotionEvent.ACTION_UP:
  714 + mCatch = false;
  715 + setPressed(false);
  716 + float time = event.getEventTime() - event.getDownTime();
  717 + if (Math.abs(deltaX) < mTouchSlop && Math.abs(deltaY) < mTouchSlop && time < mClickTimeout) {
  718 + performClick();
  719 + } else {
  720 + boolean nextStatus = getStatusBasedOnPos();
  721 + if (nextStatus != isChecked()) {
  722 + playSoundEffect(SoundEffectConstants.CLICK);
  723 + setChecked(nextStatus);
  724 + } else {
  725 + animateToState(nextStatus);
  726 + }
  727 + }
  728 + break;
  729 +
  730 + default:
  731 + break;
  732 + }
  733 + return true;
  734 + }
  735 +
  736 +
  737 + /**
  738 + * return the status based on position of thumb
  739 + *
  740 + * @return whether checked or not
  741 + */
  742 + private boolean getStatusBasedOnPos() {
  743 + return getProgress() > 0.5f;
  744 + }
  745 +
  746 + private float getProgress() {
  747 + return mProgress;
  748 + }
  749 +
  750 + private void setProgress(final float progress) {
  751 + float tp = progress;
  752 + if (tp > 1) {
  753 + tp = 1;
  754 + } else if (tp < 0) {
  755 + tp = 0;
  756 + }
  757 + this.mProgress = tp;
  758 + invalidate();
  759 + }
  760 +
  761 + @Override
  762 + public boolean performClick() {
  763 + return super.performClick();
  764 + }
  765 +
  766 + /**
  767 + * processing animation
  768 + *
  769 + * @param checked checked or unChecked
  770 + */
  771 + protected void animateToState(boolean checked) {
  772 + if (mProgressAnimator == null) {
  773 + return;
  774 + }
  775 + if (mProgressAnimator.isRunning()) {
  776 + mProgressAnimator.cancel();
  777 + }
  778 + mProgressAnimator.setDuration(mAnimationDuration);
  779 + if (checked) {
  780 + mProgressAnimator.setFloatValues(mProgress, 1f);
  781 + } else {
  782 + mProgressAnimator.setFloatValues(mProgress, 0);
  783 + }
  784 + mProgressAnimator.start();
  785 + }
  786 +
  787 + private void catchView() {
  788 + ViewParent parent = getParent();
  789 + if (parent != null) {
  790 + parent.requestDisallowInterceptTouchEvent(true);
  791 + }
  792 + mCatch = true;
  793 + }
  794 +
  795 + @Override
  796 + public void setChecked(final boolean checked) {
  797 + // animate before super.setChecked() become user may call setChecked again in OnCheckedChangedListener
  798 + if (isChecked() != checked) {
  799 + animateToState(checked);
  800 + }
  801 + if (mRestoring) {
  802 + setCheckedImmediatelyNoEvent(checked);
  803 + } else {
  804 + super.setChecked(checked);
  805 + }
  806 + }
  807 +
  808 + public void setCheckedNoEvent(final boolean checked) {
  809 + if (mChildOnCheckedChangeListener == null) {
  810 + setChecked(checked);
  811 + } else {
  812 + super.setOnCheckedChangeListener(null);
  813 + setChecked(checked);
  814 + super.setOnCheckedChangeListener(mChildOnCheckedChangeListener);
  815 + }
  816 + }
  817 +
  818 + public void setCheckedImmediatelyNoEvent(boolean checked) {
  819 + if (mChildOnCheckedChangeListener == null) {
  820 + setCheckedImmediately(checked);
  821 + } else {
  822 + super.setOnCheckedChangeListener(null);
  823 + setCheckedImmediately(checked);
  824 + super.setOnCheckedChangeListener(mChildOnCheckedChangeListener);
  825 + }
  826 + }
  827 +
  828 + public void toggleNoEvent() {
  829 + if (mChildOnCheckedChangeListener == null) {
  830 + toggle();
  831 + } else {
  832 + super.setOnCheckedChangeListener(null);
  833 + toggle();
  834 + super.setOnCheckedChangeListener(mChildOnCheckedChangeListener);
  835 + }
  836 + }
  837 +
  838 + public void toggleImmediatelyNoEvent() {
  839 + if (mChildOnCheckedChangeListener == null) {
  840 + toggleImmediately();
  841 + } else {
  842 + super.setOnCheckedChangeListener(null);
  843 + toggleImmediately();
  844 + super.setOnCheckedChangeListener(mChildOnCheckedChangeListener);
  845 + }
  846 + }
  847 +
  848 + @Override
  849 + public void setOnCheckedChangeListener(OnCheckedChangeListener onCheckedChangeListener) {
  850 + super.setOnCheckedChangeListener(onCheckedChangeListener);
  851 + mChildOnCheckedChangeListener = onCheckedChangeListener;
  852 + }
  853 +
  854 + public void setCheckedImmediately(boolean checked) {
  855 + super.setChecked(checked);
  856 + if (mProgressAnimator != null && mProgressAnimator.isRunning()) {
  857 + mProgressAnimator.cancel();
  858 + }
  859 + setProgress(checked ? 1 : 0);
  860 + invalidate();
  861 + }
  862 +
  863 + public void toggleImmediately() {
  864 + setCheckedImmediately(!isChecked());
  865 + }
  866 +
  867 + private void setDrawableState(Drawable drawable) {
  868 + if (drawable != null) {
  869 + int[] myDrawableState = getDrawableState();
  870 + drawable.setState(myDrawableState);
  871 + invalidate();
  872 + }
  873 + }
  874 +
  875 + public boolean isDrawDebugRect() {
  876 + return mDrawDebugRect;
  877 + }
  878 +
  879 + public void setDrawDebugRect(boolean drawDebugRect) {
  880 + mDrawDebugRect = drawDebugRect;
  881 + invalidate();
  882 + }
  883 +
  884 + public long getAnimationDuration() {
  885 + return mAnimationDuration;
  886 + }
  887 +
  888 + public void setAnimationDuration(long animationDuration) {
  889 + mAnimationDuration = animationDuration;
  890 + }
  891 +
  892 + public Drawable getThumbDrawable() {
  893 + return mThumbDrawable;
  894 + }
  895 +
  896 + public void setThumbDrawable(Drawable thumbDrawable) {
  897 + mThumbDrawable = thumbDrawable;
  898 + mIsThumbUseDrawable = mThumbDrawable != null;
  899 + refreshDrawableState();
  900 + mReady = false;
  901 + requestLayout();
  902 + invalidate();
  903 + }
  904 +
  905 + public void setThumbDrawableRes(int thumbDrawableRes) {
  906 + setThumbDrawable(ContextCompat.getDrawable(getContext(), thumbDrawableRes));
  907 + }
  908 +
  909 + public Drawable getBackDrawable() {
  910 + return mBackDrawable;
  911 + }
  912 +
  913 + public void setBackDrawable(Drawable backDrawable) {
  914 + mBackDrawable = backDrawable;
  915 + mIsBackUseDrawable = mBackDrawable != null;
  916 + refreshDrawableState();
  917 + mReady = false;
  918 + requestLayout();
  919 + invalidate();
  920 + }
  921 +
  922 + public void setBackDrawableRes(int backDrawableRes) {
  923 + setBackDrawable(ContextCompat.getDrawable(getContext(), backDrawableRes));
  924 + }
  925 +
  926 + public ColorStateList getBackColor() {
  927 + return mBackColor;
  928 + }
  929 +
  930 + public void setBackColor(ColorStateList backColor) {
  931 + mBackColor = backColor;
  932 + if (mBackColor != null) {
  933 + setBackDrawable(null);
  934 + }
  935 + invalidate();
  936 + }
  937 +
  938 + public void setBackColorRes(int backColorRes) {
  939 + setBackColor(ContextCompat.getColorStateList(getContext(), backColorRes));
  940 + }
  941 +
  942 + public ColorStateList getThumbColor() {
  943 + return mThumbColor;
  944 + }
  945 +
  946 + public void setThumbColor(ColorStateList thumbColor) {
  947 + mThumbColor = thumbColor;
  948 + if (mThumbColor != null) {
  949 + setThumbDrawable(null);
  950 + }
  951 + invalidate();
  952 + }
  953 +
  954 + public void setThumbColorRes(int thumbColorRes) {
  955 + setThumbColor(ContextCompat.getColorStateList(getContext(), thumbColorRes));
  956 + }
  957 +
  958 + public float getThumbRangeRatio() {
  959 + return mThumbRangeRatio;
  960 + }
  961 +
  962 + public void setThumbRangeRatio(float thumbRangeRatio) {
  963 + mThumbRangeRatio = thumbRangeRatio;
  964 + // We need to mark "ready" to false since requestLayout may not cause size changed.
  965 + mReady = false;
  966 + requestLayout();
  967 + }
  968 +
  969 + public RectF getThumbMargin() {
  970 + return mThumbMargin;
  971 + }
  972 +
  973 + public void setThumbMargin(RectF thumbMargin) {
  974 + if (thumbMargin == null) {
  975 + setThumbMargin(0, 0, 0, 0);
  976 + } else {
  977 + setThumbMargin(thumbMargin.left, thumbMargin.top, thumbMargin.right, thumbMargin.bottom);
  978 + }
  979 + }
  980 +
  981 + public void setThumbMargin(float left, float top, float right, float bottom) {
  982 + mThumbMargin.set(left, top, right, bottom);
  983 + mReady = false;
  984 + requestLayout();
  985 + }
  986 +
  987 + public void setThumbSize(int width, int height) {
  988 + mThumbWidth = width;
  989 + mThumbHeight = height;
  990 + mReady = false;
  991 + requestLayout();
  992 + }
  993 +
  994 + public float getThumbWidth() {
  995 + return mThumbWidth;
  996 + }
  997 +
  998 + public float getThumbHeight() {
  999 + return mThumbHeight;
  1000 + }
  1001 +
  1002 + public float getThumbRadius() {
  1003 + return mThumbRadius;
  1004 + }
  1005 +
  1006 + public void setThumbRadius(float thumbRadius) {
  1007 + mThumbRadius = thumbRadius;
  1008 + if (!mIsThumbUseDrawable) {
  1009 + invalidate();
  1010 + }
  1011 + }
  1012 +
  1013 + public PointF getBackSizeF() {
  1014 + return new PointF(mBackRectF.width(), mBackRectF.height());
  1015 + }
  1016 +
  1017 + public float getBackRadius() {
  1018 + return mBackRadius;
  1019 + }
  1020 +
  1021 + public void setBackRadius(float backRadius) {
  1022 + mBackRadius = backRadius;
  1023 + if (!mIsBackUseDrawable) {
  1024 + invalidate();
  1025 + }
  1026 + }
  1027 +
  1028 + public boolean isFadeBack() {
  1029 + return mFadeBack;
  1030 + }
  1031 +
  1032 + public void setFadeBack(boolean fadeBack) {
  1033 + mFadeBack = fadeBack;
  1034 + }
  1035 +
  1036 + public int getTintColor() {
  1037 + return mTintColor;
  1038 + }
  1039 +
  1040 + public void setTintColor(@SuppressWarnings("SameParameterValue") int tintColor) {
  1041 + mTintColor = tintColor;
  1042 + mThumbColor = ColorUtils.generateThumbColorWithTintColor(mTintColor);
  1043 + mBackColor = ColorUtils.generateBackColorWithTintColor(mTintColor);
  1044 + mIsBackUseDrawable = false;
  1045 + mIsThumbUseDrawable = false;
  1046 + // call this method to refresh color states
  1047 + refreshDrawableState();
  1048 + invalidate();
  1049 + }
  1050 +
  1051 + public void setText(CharSequence onText, CharSequence offText) {
  1052 + mTextOn = onText;
  1053 + mTextOff = offText;
  1054 +
  1055 + mOnLayout = null;
  1056 + mOffLayout = null;
  1057 +
  1058 + mReady = false;
  1059 + requestLayout();
  1060 + invalidate();
  1061 + }
  1062 +
  1063 + public CharSequence getTextOn() {
  1064 + return mTextOn;
  1065 + }
  1066 +
  1067 + public CharSequence getTextOff() {
  1068 + return mTextOff;
  1069 + }
  1070 +
  1071 + public void setTextThumbInset(int textThumbInset) {
  1072 + mTextThumbInset = textThumbInset;
  1073 + mReady = false;
  1074 + requestLayout();
  1075 + invalidate();
  1076 + }
  1077 +
  1078 + public void setTextExtra(int textExtra) {
  1079 + mTextExtra = textExtra;
  1080 + mReady = false;
  1081 + requestLayout();
  1082 + invalidate();
  1083 + }
  1084 +
  1085 + public void setTextAdjust(int textAdjust) {
  1086 + mTextAdjust = textAdjust;
  1087 + mReady = false;
  1088 + requestLayout();
  1089 + invalidate();
  1090 + }
  1091 +
  1092 + @Override
  1093 + public Parcelable onSaveInstanceState() {
  1094 + Parcelable superState = super.onSaveInstanceState();
  1095 + SavedState ss = new SavedState(superState);
  1096 + ss.onText = mTextOn;
  1097 + ss.offText = mTextOff;
  1098 + return ss;
  1099 + }
  1100 +
  1101 + @Override
  1102 + public void onRestoreInstanceState(Parcelable state) {
  1103 + SavedState ss = (SavedState) state;
  1104 + setText(ss.onText, ss.offText);
  1105 + mRestoring = true;
  1106 + super.onRestoreInstanceState(ss.getSuperState());
  1107 + mRestoring = false;
  1108 + }
  1109 +
  1110 + static class SavedState extends BaseSavedState {
  1111 + CharSequence onText;
  1112 + CharSequence offText;
  1113 +
  1114 + SavedState(Parcelable superState) {
  1115 + super(superState);
  1116 + }
  1117 +
  1118 + private SavedState(Parcel in) {
  1119 + super(in);
  1120 + onText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
  1121 + offText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
  1122 + }
  1123 +
  1124 + @Override
  1125 + public void writeToParcel(Parcel out, int flags) {
  1126 + super.writeToParcel(out, flags);
  1127 + TextUtils.writeToParcel(onText, out, flags);
  1128 + TextUtils.writeToParcel(offText, out, flags);
  1129 + }
  1130 +
  1131 + public static final Creator<SavedState> CREATOR
  1132 + = new Creator<SavedState>() {
  1133 + public SavedState createFromParcel(Parcel in) {
  1134 + return new SavedState(in);
  1135 + }
  1136 +
  1137 + public SavedState[] newArray(int size) {
  1138 + return new SavedState[size];
  1139 + }
  1140 + };
  1141 + }
  1142 +}
0 \ No newline at end of file 1143 \ No newline at end of file
core/base/src/main/java/com/cnlive/core/libs/base/util/CheckUtil.java
1 package com.cnlive.core.libs.base.util; 1 package com.cnlive.core.libs.base.util;
2 2
3 import android.app.Activity; 3 import android.app.Activity;
  4 +import android.content.Context;
4 import android.content.Intent; 5 import android.content.Intent;
5 import android.content.pm.PackageManager; 6 import android.content.pm.PackageManager;
  7 +import android.location.LocationManager;
6 import android.net.Uri; 8 import android.net.Uri;
7 import android.os.PowerManager; 9 import android.os.PowerManager;
8 import android.provider.Settings; 10 import android.provider.Settings;
9 import android.widget.Toast; 11 import android.widget.Toast;
10 12
  13 +
  14 +import com.cnlive.strike.base.R;
  15 +
11 import static android.content.Context.POWER_SERVICE; 16 import static android.content.Context.POWER_SERVICE;
12 17
13 public class CheckUtil { 18 public class CheckUtil {
  19 + /**
  20 + * 判断GPS是否开启,GPS或者AGPS开启一个就认为是开启的
  21 + *
  22 + * @param context
  23 + * @return true 表示开启
  24 + */
  25 + public static final boolean isOPenGps(final Context context) {
  26 + try {
  27 + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
  28 + LocationManager locationManager
  29 + = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
  30 + // 通过GPS卫星定位,定位级别可以精确到街(通过24颗卫星定位,在室外和空旷的地方定位准确、速度快)
  31 + boolean gps = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
  32 + // 通过WLAN或移动网络(3G/2G)确定的位置(也称作AGPS,辅助GPS定位。主要用于在室内或遮盖物(建筑群或茂密的深林等)密集的地方定位)
  33 + boolean network = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
  34 + if (gps) {
  35 + return true;
  36 + } else {
  37 + return false;
  38 + }
  39 + } else {
  40 + return true;
  41 + }
  42 + } catch (Exception e) {
  43 + //异常就返回true
  44 + return true;
  45 + }
  46 + }
14 47
  48 + public static void openGPS(Activity context) {
  49 + //开启GPS
  50 + try {
  51 + Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
  52 + context.startActivityForResult(intent, 10);
  53 + Toast.makeText(context, context.getString(R.string.open_gps_tip), Toast.LENGTH_LONG).show();
  54 + } catch (Exception e) {
  55 + Toast.makeText(context, "请手动打开GPS", Toast.LENGTH_LONG).show();
  56 + }
  57 + }
15 /** 58 /**
16 * 锤子手机不能检测电池白名单,会崩溃 59 * 锤子手机不能检测电池白名单,会崩溃
17 * 60 *
core/base/src/main/java/com/cnlive/core/libs/base/util/SimpleDES.java 0 → 100644
  1 +package com.cnlive.core.libs.base.util;
  2 +
  3 +import android.util.Base64;
  4 +
  5 +import java.security.Key;
  6 +
  7 +import javax.crypto.Cipher;
  8 +import javax.crypto.SecretKeyFactory;
  9 +import javax.crypto.spec.DESKeySpec;
  10 +
  11 +import static javax.crypto.Cipher.getInstance;
  12 +
  13 +/**
  14 + * 加密工具
  15 + */
  16 +public class SimpleDES {
  17 + //key 的长度得大于8
  18 + public static final String DES_KEY = "cnliveIm";
  19 + private static String encoding = "UTF-8";
  20 +
  21 + /**
  22 + * 加密字符串
  23 + */
  24 + public static String ebotongEncrypto(String str, String key) {
  25 + String result = str;
  26 + if (str != null && str.length() > 0) {
  27 + try {
  28 + byte[] encodeByte = symmetricEncrypto(str.getBytes(encoding), key);
  29 + result = Base64.encodeToString(encodeByte, Base64.DEFAULT);
  30 +
  31 + } catch (Exception e) {
  32 + // e.printStackTrace();
  33 + }
  34 + }
  35 + return result;
  36 + }
  37 +
  38 + /**
  39 + * 解密字符串
  40 + */
  41 + public static String ebotongDecrypto(String str, String key) {
  42 + String result = str;
  43 + if (str != null && str.length() > 0) {
  44 + try {
  45 + byte[] encodeByte = Base64.decode(str, Base64.DEFAULT);
  46 +
  47 + byte[] decoder = symmetricDecrypto(encodeByte, key);
  48 + result = new String(decoder, encoding);
  49 + } catch (Exception e) {
  50 + // e.printStackTrace();
  51 + }
  52 + }
  53 + return result;
  54 + }
  55 +
  56 + /**
  57 + * 加密byte[]
  58 + */
  59 + public static byte[] ebotongEncrypto(byte[] str, String key) {
  60 + byte[] result = null;
  61 + if (str != null && str.length > 0) {
  62 + try {
  63 + byte[] encodeByte = symmetricEncrypto(str, key);
  64 + result = Base64.encode(encodeByte, Base64.DEFAULT);
  65 +
  66 + } catch (Exception e) {
  67 + // e.printStackTrace();
  68 + }
  69 + }
  70 + return result;
  71 + }
  72 +
  73 + /**
  74 + * 解密byte[]
  75 + */
  76 + public static byte[] ebotongDecrypto(byte[] str, String key) {
  77 + byte[] result = null;
  78 + if (str != null && str.length > 0) {
  79 + try {
  80 +
  81 + byte[] encodeByte = Base64.decode(new String(str, encoding), Base64.DEFAULT);
  82 + //byte[] encodeByte = base64decoder.decodeBuffer(new String(str));
  83 + byte[] decoder = symmetricDecrypto(encodeByte, key);
  84 + result = new String(decoder).getBytes(encoding);
  85 + result = new String(decoder).getBytes();
  86 + } catch (Exception e) {
  87 + // e.printStackTrace();
  88 + }
  89 + }
  90 + return result;
  91 + }
  92 +
  93 + /**
  94 + * 对称加密字节数组并返回
  95 + *
  96 + * @param byteSource 需要加密的数据
  97 + * @return 经过加密的数据
  98 + * @throws Exception
  99 + */
  100 + public static byte[] symmetricEncrypto(byte[] byteSource, String sKey) throws Exception {
  101 + try {
  102 + int mode = Cipher.ENCRYPT_MODE;
  103 + SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
  104 + byte[] keyData = sKey.getBytes();
  105 + DESKeySpec keySpec = new DESKeySpec(keyData);
  106 + Key key = keyFactory.generateSecret(keySpec);
  107 + Cipher cipher = getInstance("DES");
  108 + cipher.init(mode, key);
  109 +
  110 + return cipher.doFinal(byteSource);
  111 + } catch (Exception e) {
  112 + return null;
  113 + }
  114 + }
  115 +
  116 + /**
  117 + * 对称解密字节数组并返回
  118 + *
  119 + * @param byteSource 需要解密的数据
  120 + * @return 经过解密的数据
  121 + * @throws Exception
  122 + */
  123 + public static byte[] symmetricDecrypto(byte[] byteSource, String sKey) throws Exception {
  124 + try {
  125 + int mode = Cipher.DECRYPT_MODE;
  126 + SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
  127 + byte[] keyData = sKey.getBytes();
  128 + DESKeySpec keySpec = new DESKeySpec(keyData);
  129 + Key key = keyFactory.generateSecret(keySpec);
  130 + Cipher cipher = getInstance("DES");
  131 + cipher.init(mode, key);
  132 + return cipher.doFinal(byteSource);
  133 + } catch (Exception e) {
  134 + return null;
  135 + }
  136 + }
  137 +}