Commit 556ee8b2a75d0fb8c69c32c6da8f3325e509b8b2
1 parent
d1cb2a91
1 优化基类,fragment支持侧滑返回
Showing
22 changed files
with
4277 additions
and
196 deletions
Too many changes to show.
To preserve performance only 22 of 61 files are displayed.
app/strike/src/main/java/com/cnlive/strike/MainActivity.java
| @@ -24,7 +24,7 @@ public class MainActivity extends AppCompatActivity { | @@ -24,7 +24,7 @@ public class MainActivity extends AppCompatActivity { | ||
| 24 | protected void onCreate(@Nullable Bundle savedInstanceState) { | 24 | protected void onCreate(@Nullable Bundle savedInstanceState) { |
| 25 | super.onCreate(savedInstanceState); | 25 | super.onCreate(savedInstanceState); |
| 26 | setContentView(R.layout.activity_main); | 26 | setContentView(R.layout.activity_main); |
| 27 | - findViewById(R.id.go_to).setOnClickListener(view -> startActivity(new Intent(this, LoginActivity.class)) ); | 27 | + findViewById(R.id.go_to).setOnClickListener(view -> startActivity(new Intent(this, DemoActivity.class)) ); |
| 28 | 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)) ); |
| 29 | } | 29 | } |
| 30 | 30 |
app/strike/src/main/java/com/cnlive/strike/MyActivity.java
| @@ -13,7 +13,6 @@ public class MyActivity extends BaseActivity { | @@ -13,7 +13,6 @@ public class MyActivity extends BaseActivity { | ||
| 13 | 13 | ||
| 14 | @Override | 14 | @Override |
| 15 | protected void initView() { | 15 | protected void initView() { |
| 16 | - setOpenSwipBack(true); | ||
| 17 | getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new MyFragment()).commitAllowingStateLoss(); | 16 | getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new MyFragment()).commitAllowingStateLoss(); |
| 18 | } | 17 | } |
| 19 | 18 |
app/strike/src/main/java/com/cnlive/strike/MyFragment.java
| @@ -19,6 +19,8 @@ import com.cnlive.strike.network.BaseRequest; | @@ -19,6 +19,8 @@ import com.cnlive.strike.network.BaseRequest; | ||
| 19 | import com.cnlive.strike.network.api.ApiService; | 19 | import com.cnlive.strike.network.api.ApiService; |
| 20 | import com.cnlive.strike.network.bean.LetHimNoSeeBean; | 20 | import com.cnlive.strike.network.bean.LetHimNoSeeBean; |
| 21 | import com.cnlive.strike.network.bean.TestBean; | 21 | import com.cnlive.strike.network.bean.TestBean; |
| 22 | +import com.me.yokeyword.fragmentation.anim.DefaultVerticalAnimator; | ||
| 23 | +import com.me.yokeyword.fragmentation.anim.FragmentAnimator; | ||
| 22 | 24 | ||
| 23 | import androidx.annotation.NonNull; | 25 | import androidx.annotation.NonNull; |
| 24 | import androidx.annotation.Nullable; | 26 | import androidx.annotation.Nullable; |
| @@ -31,23 +33,21 @@ import io.reactivex.functions.Function; | @@ -31,23 +33,21 @@ import io.reactivex.functions.Function; | ||
| 31 | 33 | ||
| 32 | 34 | ||
| 33 | public class MyFragment extends BaseFragment<MyFragmentView, MyPresenter> { | 35 | public class MyFragment extends BaseFragment<MyFragmentView, MyPresenter> { |
| 34 | - private View view; | ||
| 35 | public TextView textView; | 36 | public TextView textView; |
| 36 | 37 | ||
| 37 | - @Nullable | ||
| 38 | @Override | 38 | @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; | 39 | + protected int getViewLayoutId() { |
| 40 | + return R.layout.activity_main1; | ||
| 43 | } | 41 | } |
| 44 | 42 | ||
| 45 | @Override | 43 | @Override |
| 46 | protected void initView() { | 44 | protected void initView() { |
| 47 | super.initView(); | 45 | super.initView(); |
| 46 | + setSwipeBackEnable(true); | ||
| 48 | setStatusBarColor(R.color.green, 0); | 47 | setStatusBarColor(R.color.green, 0); |
| 49 | setStatusBarTextColor(StatusBarConfig.BLACK); | 48 | setStatusBarTextColor(StatusBarConfig.BLACK); |
| 50 | - view.findViewById(R.id.btn_test2).setOnClickListener(new View.OnClickListener() { | 49 | + textView = baseView.findViewById(R.id.tv1); |
| 50 | + baseView.findViewById(R.id.btn_test2).setOnClickListener(new View.OnClickListener() { | ||
| 51 | @Override | 51 | @Override |
| 52 | public void onClick(View v) { | 52 | public void onClick(View v) { |
| 53 | requestPermission(010001, "测试", new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, new OnPermissionResponseListener() { | 53 | requestPermission(010001, "测试", new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, new OnPermissionResponseListener() { |
| @@ -63,23 +63,24 @@ public class MyFragment extends BaseFragment<MyFragmentView, MyPresenter> { | @@ -63,23 +63,24 @@ public class MyFragment extends BaseFragment<MyFragmentView, MyPresenter> { | ||
| 63 | }); | 63 | }); |
| 64 | } | 64 | } |
| 65 | }); | 65 | }); |
| 66 | - view.findViewById(R.id.btn_test1).setOnClickListener(new View.OnClickListener() { | 66 | + baseView.findViewById(R.id.btn_test1).setOnClickListener(new View.OnClickListener() { |
| 67 | @Override | 67 | @Override |
| 68 | public void onClick(View v) { | 68 | 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 | - }); | 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 | +// }); | ||
| 80 | + startForResult(new MyFragment1(),1001); | ||
| 80 | } | 81 | } |
| 81 | }); | 82 | }); |
| 82 | - view.findViewById(R.id.btn_test).setOnClickListener(new View.OnClickListener() { | 83 | + baseView.findViewById(R.id.btn_test).setOnClickListener(new View.OnClickListener() { |
| 83 | @Override | 84 | @Override |
| 84 | public void onClick(View v) { | 85 | public void onClick(View v) { |
| 85 | //单个请求 | 86 | //单个请求 |
| @@ -144,4 +145,17 @@ public class MyFragment extends BaseFragment<MyFragmentView, MyPresenter> { | @@ -144,4 +145,17 @@ public class MyFragment extends BaseFragment<MyFragmentView, MyPresenter> { | ||
| 144 | getPresenter().setData("hha"); | 145 | getPresenter().setData("hha"); |
| 145 | getMvpView().setData("test"); | 146 | getMvpView().setData("test"); |
| 146 | } | 147 | } |
| 148 | + | ||
| 149 | + @Override | ||
| 150 | + public FragmentAnimator onCreateFragmentAnimator() { | ||
| 151 | + return new DefaultVerticalAnimator(); | ||
| 152 | + } | ||
| 153 | + | ||
| 154 | + @Override | ||
| 155 | + public void onFragmentResult(int requestCode, int resultCode, Bundle data) { | ||
| 156 | + super.onFragmentResult(requestCode, resultCode, data); | ||
| 157 | + if (requestCode==1001){ | ||
| 158 | + setStatusBarColor(R.color.green,0); | ||
| 159 | + } | ||
| 160 | + } | ||
| 147 | } | 161 | } |
app/strike/src/main/java/com/cnlive/strike/MyFragment1.java
| @@ -14,13 +14,11 @@ import com.cnlive.core.libs.base.util.StatusBarConfig; | @@ -14,13 +14,11 @@ import com.cnlive.core.libs.base.util.StatusBarConfig; | ||
| 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,6 @@ public class MyFragment1 extends BaseFragment { | @@ -28,5 +26,6 @@ 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 | + | ||
| 31 | } | 30 | } |
| 32 | } | 31 | } |
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(R.id.fl_container, 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> |
config.gradle
| @@ -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 | ] |
| @@ -47,6 +47,12 @@ ext { | @@ -47,6 +47,12 @@ ext { | ||
| 47 | ] | 47 | ] |
| 48 | 48 | ||
| 49 | library = [ | 49 | library = [ |
| 50 | + | ||
| 51 | + //fragment滑动返回( https://github.com/YoKeyword/Fragmentation ,源码导入修改) | ||
| 52 | + fragmentation_swipeback : 'me.yokeyword:fragmentationx-swipeback:1.0.2', | ||
| 53 | + //对fragment进行管理( https://github.com/YoKeyword/Fragmentation ,源码导入修改) | ||
| 54 | + fragmentationx : 'me.yokeyword:fragmentationx:1.0.2', | ||
| 55 | + //log日志 | ||
| 50 | logger : 'com.orhanobut:logger:2.2.0', | 56 | logger : 'com.orhanobut:logger:2.2.0', |
| 51 | // //空祖对话框 https://github.com/kongzue/DialogV3 | 57 | // //空祖对话框 https://github.com/kongzue/DialogV3 |
| 52 | // kongzueDailog : 'com.kongzue.dialog_v3x:dialog:3.1.6', | 58 | // kongzueDailog : 'com.kongzue.dialog_v3x:dialog:3.1.6', |
| @@ -101,31 +107,33 @@ ext { | @@ -101,31 +107,33 @@ ext { | ||
| 101 | // ] | 107 | // ] |
| 102 | //基础三方库 | 108 | //基础三方库 |
| 103 | base_librarys = [ | 109 | base_librarys = [ |
| 104 | - library.logger, | ||
| 105 | - //对话框 | 110 | +// library.fragmentation_swipeback, |
| 111 | +// library.fragmentationx, | ||
| 112 | +library.logger, | ||
| 113 | +//对话框 | ||
| 106 | // library.kongzueDailog, | 114 | // library.kongzueDailog, |
| 107 | - //视讯云加密库 | ||
| 108 | - library.libCnencipher, | ||
| 109 | - //视频库 | ||
| 110 | - library.libVideoQiniu, | ||
| 111 | - //视讯云播放器 | ||
| 112 | - library.libCnVideo, | ||
| 113 | - //权限 | ||
| 114 | - library.easypermissions, | ||
| 115 | - //EvenBus | ||
| 116 | - library.eventBus, | ||
| 117 | - //QMUI | ||
| 118 | - library.qmui, | ||
| 119 | - library.qmui_arch, | ||
| 120 | - //mvp | 115 | +//视讯云加密库 |
| 116 | +library.libCnencipher, | ||
| 117 | +//视频库 | ||
| 118 | +library.libVideoQiniu, | ||
| 119 | +//视讯云播放器 | ||
| 120 | +library.libCnVideo, | ||
| 121 | +//权限 | ||
| 122 | +library.easypermissions, | ||
| 123 | +//EvenBus | ||
| 124 | +library.eventBus, | ||
| 125 | +//QMUI | ||
| 126 | +library.qmui, | ||
| 127 | +library.qmui_arch, | ||
| 128 | +//mvp | ||
| 121 | // library.mvp, | 129 | // library.mvp, |
| 122 | // library.mvp_lce, | 130 | // library.mvp_lce, |
| 123 | // library.mvp_nullobject_presenter, | 131 | // library.mvp_nullobject_presenter, |
| 124 | // library.mvp_viewstate, | 132 | // library.mvp_viewstate, |
| 125 | - //图片加载Glide | ||
| 126 | - glide.api, | ||
| 127 | - glide.transformations, | ||
| 128 | - //兼容旧版 | 133 | +//图片加载Glide |
| 134 | +glide.api, | ||
| 135 | +glide.transformations, | ||
| 136 | +//兼容旧版 | ||
| 129 | // library.supportV4, | 137 | // library.supportV4, |
| 130 | // library.appcompatV7, | 138 | // library.appcompatV7, |
| 131 | // library.design, | 139 | // library.design, |
| @@ -133,26 +141,26 @@ ext { | @@ -133,26 +141,26 @@ ext { | ||
| 133 | // library.recyclerviewV7, | 141 | // library.recyclerviewV7, |
| 134 | // library.cardviewV7, | 142 | // library.cardviewV7, |
| 135 | // library.dataBinding, | 143 | // library.dataBinding, |
| 136 | - //使用androidx | ||
| 137 | - androidx.appcompat, | ||
| 138 | - androidx.constraintlayout, | ||
| 139 | - androidx.multidex, | ||
| 140 | - //其他库 | ||
| 141 | - library.rxjava, | ||
| 142 | - library.rxandroid, | ||
| 143 | - library.retrofit, | ||
| 144 | - library.retrofitConverterGson, | ||
| 145 | - library.retrofitAdapterRxjava2, | ||
| 146 | - library.okhttp, | ||
| 147 | - library.okhttpLoggingInterceptor, | ||
| 148 | - library.greendao, | ||
| 149 | - //管理rxjava生命周期 | 144 | +//使用androidx |
| 145 | +androidx.appcompat, | ||
| 146 | +androidx.constraintlayout, | ||
| 147 | +androidx.multidex, | ||
| 148 | +//其他库 | ||
| 149 | +library.rxjava, | ||
| 150 | +library.rxandroid, | ||
| 151 | +library.retrofit, | ||
| 152 | +library.retrofitConverterGson, | ||
| 153 | +library.retrofitAdapterRxjava2, | ||
| 154 | +library.okhttp, | ||
| 155 | +library.okhttpLoggingInterceptor, | ||
| 156 | +library.greendao, | ||
| 157 | +//管理rxjava生命周期 | ||
| 150 | // library.rx | 158 | // library.rx |
| 151 | - router.api, | 159 | +router.api, |
| 152 | 160 | ||
| 153 | - test.junit, | ||
| 154 | - test.runner, | ||
| 155 | - test.espresso | 161 | +test.junit, |
| 162 | +test.runner, | ||
| 163 | +test.espresso | ||
| 156 | ] | 164 | ] |
| 157 | 165 | ||
| 158 | base_compilers = [ | 166 | base_compilers = [ |
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/frame/activity/BaseActivity.java
| @@ -14,12 +14,14 @@ import android.provider.Settings; | @@ -14,12 +14,14 @@ import android.provider.Settings; | ||
| 14 | import android.text.TextUtils; | 14 | import android.text.TextUtils; |
| 15 | import android.util.DisplayMetrics; | 15 | import android.util.DisplayMetrics; |
| 16 | import android.view.Display; | 16 | import android.view.Display; |
| 17 | +import android.view.MotionEvent; | ||
| 17 | import android.view.View; | 18 | import android.view.View; |
| 18 | import android.view.Window; | 19 | import android.view.Window; |
| 19 | import android.view.WindowManager; | 20 | import android.view.WindowManager; |
| 20 | import android.view.inputmethod.InputMethodManager; | 21 | import android.view.inputmethod.InputMethodManager; |
| 21 | 22 | ||
| 22 | import androidx.annotation.ColorRes; | 23 | import androidx.annotation.ColorRes; |
| 24 | +import androidx.annotation.DrawableRes; | ||
| 23 | import androidx.annotation.IntRange; | 25 | import androidx.annotation.IntRange; |
| 24 | import androidx.annotation.NonNull; | 26 | import androidx.annotation.NonNull; |
| 25 | import androidx.annotation.Nullable; | 27 | import androidx.annotation.Nullable; |
| @@ -31,6 +33,7 @@ import androidx.databinding.DataBindingUtil; | @@ -31,6 +33,7 @@ import androidx.databinding.DataBindingUtil; | ||
| 31 | import androidx.databinding.ViewDataBinding; | 33 | import androidx.databinding.ViewDataBinding; |
| 32 | 34 | ||
| 33 | import com.alibaba.android.arouter.launcher.ARouter; | 35 | import com.alibaba.android.arouter.launcher.ARouter; |
| 36 | +import com.cnlive.core.libs.base.application.AppConfig; | ||
| 34 | import com.cnlive.core.libs.base.frame.presenter.BasePresenter; | 37 | import com.cnlive.core.libs.base.frame.presenter.BasePresenter; |
| 35 | import com.cnlive.core.libs.base.frame.view.BaseView; | 38 | import com.cnlive.core.libs.base.frame.view.BaseView; |
| 36 | import com.cnlive.core.libs.base.interfaces.OnPermissionResponseListener; | 39 | import com.cnlive.core.libs.base.interfaces.OnPermissionResponseListener; |
| @@ -39,27 +42,36 @@ import com.cnlive.core.libs.base.util.AppManager; | @@ -39,27 +42,36 @@ import com.cnlive.core.libs.base.util.AppManager; | ||
| 39 | import com.cnlive.core.libs.base.util.ReflectUtil; | 42 | import com.cnlive.core.libs.base.util.ReflectUtil; |
| 40 | import com.cnlive.core.libs.base.util.StatusBarConfig; | 43 | import com.cnlive.core.libs.base.util.StatusBarConfig; |
| 41 | import com.cnlive.core.libs.base.util.StatusBarUtil; | 44 | import com.cnlive.core.libs.base.util.StatusBarUtil; |
| 42 | -import com.cnlive.core.libs.base.util.swipeback.util.SwipeBackActivityBase; | ||
| 43 | -import com.cnlive.core.libs.base.util.swipeback.util.SwipeBackActivityHelper; | ||
| 44 | -import com.cnlive.core.libs.base.util.swipeback.util.SwipeBackLayout; | ||
| 45 | -import com.cnlive.core.libs.base.util.swipeback.util.SwipeBackUtil; | 45 | +import com.cnlive.strike.base.R; |
| 46 | import com.hannesdorfmann.mosby3.mvp.MvpActivity; | 46 | import com.hannesdorfmann.mosby3.mvp.MvpActivity; |
| 47 | +import com.me.yokeyword.fragmentation.ExtraTransaction; | ||
| 48 | +import com.me.yokeyword.fragmentation.Fragmentation; | ||
| 49 | +import com.me.yokeyword.fragmentation.ISupportActivity; | ||
| 50 | +import com.me.yokeyword.fragmentation.ISupportFragment; | ||
| 51 | +import com.me.yokeyword.fragmentation.SupportActivityDelegate; | ||
| 52 | +import com.me.yokeyword.fragmentation.SupportHelper; | ||
| 53 | +import com.me.yokeyword.fragmentation.SwipeBackLayout; | ||
| 54 | +import com.me.yokeyword.fragmentation.anim.FragmentAnimator; | ||
| 55 | +import com.me.yokeyword.fragmentation_swipeback.core.ISwipeBackActivity; | ||
| 56 | +import com.me.yokeyword.fragmentation_swipeback.core.SwipeBackActivityDelegate; | ||
| 47 | import com.orhanobut.logger.Logger; | 57 | import com.orhanobut.logger.Logger; |
| 48 | 58 | ||
| 49 | import java.lang.reflect.Field; | 59 | import java.lang.reflect.Field; |
| 50 | import java.util.ArrayList; | 60 | import java.util.ArrayList; |
| 51 | import java.util.List; | 61 | import java.util.List; |
| 52 | 62 | ||
| 63 | + | ||
| 53 | /** | 64 | /** |
| 54 | * @author ys | 65 | * @author ys |
| 55 | * 基类 activity | 66 | * 基类 activity |
| 67 | + * SwipeBackActivityBase, | ||
| 56 | */ | 68 | */ |
| 57 | -public abstract class BaseActivity<V extends BaseView, P extends BasePresenter<V>> extends MvpActivity<V, P> implements SwipeBackActivityBase { | 69 | +public abstract class BaseActivity<V extends BaseView, P extends BasePresenter<V>> extends MvpActivity<V, P> implements ISupportActivity, ISwipeBackActivity { |
| 58 | private V view; | 70 | private V view; |
| 59 | private P presenter; | 71 | private P presenter; |
| 60 | public ViewDataBinding baseBinding; | 72 | public ViewDataBinding baseBinding; |
| 61 | //获取TAG的activity名称 | 73 | //获取TAG的activity名称 |
| 62 | - protected final String TAG = this.getClass().getSimpleName(); | 74 | + public final String TAG = this.getClass().getSimpleName(); |
| 63 | //是否显示标题栏 | 75 | //是否显示标题栏 |
| 64 | private boolean isShowTitle = true; | 76 | private boolean isShowTitle = true; |
| 65 | //是否显示状态栏 | 77 | //是否显示状态栏 |
| @@ -76,9 +88,12 @@ public abstract class BaseActivity<V extends BaseView, P extends BasePresenter<V | @@ -76,9 +88,12 @@ public abstract class BaseActivity<V extends BaseView, P extends BasePresenter<V | ||
| 76 | private int USER_SET_REQUEST_CODE_PERMISSION = -0x00099;//用户设置的权限请求码 | 88 | private int USER_SET_REQUEST_CODE_PERMISSION = -0x00099;//用户设置的权限请求码 |
| 77 | private String defaultDefinePermissionTip = "需要必要的权限才可以正常使用该功能,您已拒绝获得该权限。\n如果需要重新授权,您可以点击“允许”按钮进入系统设置进行授权";//默认拒绝的权限提示语 | 89 | private String defaultDefinePermissionTip = "需要必要的权限才可以正常使用该功能,您已拒绝获得该权限。\n如果需要重新授权,您可以点击“允许”按钮进入系统设置进行授权";//默认拒绝的权限提示语 |
| 78 | private String userSetDefinePermissionTip = "";//用户设置的权限提示语 | 90 | private String userSetDefinePermissionTip = "";//用户设置的权限提示语 |
| 79 | - private SwipeBackActivityHelper mHelper;//侧滑返回 | 91 | + // private SwipeBackActivityHelper mHelper;//侧滑返回 |
| 80 | private boolean isOpenSwipBack = false; | 92 | private boolean isOpenSwipBack = false; |
| 81 | - private AlertDialog alertDialog; | 93 | + //fragmnet管理 |
| 94 | + private final SupportActivityDelegate mDelegate = new SupportActivityDelegate(this); | ||
| 95 | + //fragment侧滑 | ||
| 96 | + private final SwipeBackActivityDelegate mSwipeDelegate = new SwipeBackActivityDelegate(this); | ||
| 82 | 97 | ||
| 83 | @Override | 98 | @Override |
| 84 | protected void onCreate(@Nullable Bundle savedInstanceState) { | 99 | protected void onCreate(@Nullable Bundle savedInstanceState) { |
| @@ -88,8 +103,17 @@ public abstract class BaseActivity<V extends BaseView, P extends BasePresenter<V | @@ -88,8 +103,17 @@ public abstract class BaseActivity<V extends BaseView, P extends BasePresenter<V | ||
| 88 | } else if (0 != getViewLayoutId()) { | 103 | } else if (0 != getViewLayoutId()) { |
| 89 | setContentView(getViewLayoutId()); | 104 | setContentView(getViewLayoutId()); |
| 90 | } | 105 | } |
| 106 | + //两种视图都没有设置,就加载默认跟视图,用于fragment切换 | ||
| 107 | + if (0 == getBindLayoutId() && 0 == getViewLayoutId()) { | ||
| 108 | + setContentView(R.layout.base_activity_main); | ||
| 109 | + } | ||
| 91 | context = this; | 110 | context = this; |
| 92 | me = this; | 111 | me = this; |
| 112 | + //fragment管理 | ||
| 113 | + mDelegate.onCreate(savedInstanceState); | ||
| 114 | + mSwipeDelegate.onCreate(savedInstanceState); | ||
| 115 | + //是否开启滑动返回 | ||
| 116 | + setSwipeBackEnable(isOpenSwipBack); | ||
| 93 | this.savedInstanceState = savedInstanceState; | 117 | this.savedInstanceState = savedInstanceState; |
| 94 | //路由参数初始化 | 118 | //路由参数初始化 |
| 95 | ARouter.getInstance().inject(this); | 119 | ARouter.getInstance().inject(this); |
| @@ -118,16 +142,11 @@ public abstract class BaseActivity<V extends BaseView, P extends BasePresenter<V | @@ -118,16 +142,11 @@ public abstract class BaseActivity<V extends BaseView, P extends BasePresenter<V | ||
| 118 | initView(); | 142 | initView(); |
| 119 | //设置数据 | 143 | //设置数据 |
| 120 | initData(); | 144 | initData(); |
| 121 | - //是否开启滑动返回 | ||
| 122 | - if (isOpenSwipBack) { | ||
| 123 | - mHelper = new SwipeBackActivityHelper(this); | ||
| 124 | - mHelper.onActivityCreate(); | ||
| 125 | - } | ||
| 126 | - | ||
| 127 | - } | ||
| 128 | - | ||
| 129 | - protected void setOpenSwipBack(boolean isOpen) { | ||
| 130 | - isOpenSwipBack = isOpen; | 145 | +// if (isOpenSwipBack) { |
| 146 | +// mHelper = new SwipeBackActivityHelper(this); | ||
| 147 | +// mHelper.onActivityCreate(); | ||
| 148 | +// | ||
| 149 | +// } | ||
| 131 | } | 150 | } |
| 132 | 151 | ||
| 133 | 152 | ||
| @@ -151,6 +170,10 @@ public abstract class BaseActivity<V extends BaseView, P extends BasePresenter<V | @@ -151,6 +170,10 @@ public abstract class BaseActivity<V extends BaseView, P extends BasePresenter<V | ||
| 151 | 170 | ||
| 152 | } | 171 | } |
| 153 | 172 | ||
| 173 | + public boolean isOpenSwipBack() { | ||
| 174 | + return isOpenSwipBack; | ||
| 175 | + } | ||
| 176 | + | ||
| 154 | /** | 177 | /** |
| 155 | * 设置是否显示标题栏 | 178 | * 设置是否显示标题栏 |
| 156 | * | 179 | * |
| @@ -242,9 +265,10 @@ public abstract class BaseActivity<V extends BaseView, P extends BasePresenter<V | @@ -242,9 +265,10 @@ public abstract class BaseActivity<V extends BaseView, P extends BasePresenter<V | ||
| 242 | 265 | ||
| 243 | @Override | 266 | @Override |
| 244 | protected void onDestroy() { | 267 | protected void onDestroy() { |
| 268 | + mDelegate.onDestroy(); | ||
| 245 | super.onDestroy(); | 269 | super.onDestroy(); |
| 246 | - if (null != alertDialog) { | ||
| 247 | - alertDialog.dismiss(); | 270 | + if (null != baseBinding) { |
| 271 | + baseBinding.unbind(); | ||
| 248 | } | 272 | } |
| 249 | //activity管理 | 273 | //activity管理 |
| 250 | AppManager.getInstance().deleteActivity(me); | 274 | AppManager.getInstance().deleteActivity(me); |
| @@ -258,15 +282,15 @@ public abstract class BaseActivity<V extends BaseView, P extends BasePresenter<V | @@ -258,15 +282,15 @@ public abstract class BaseActivity<V extends BaseView, P extends BasePresenter<V | ||
| 258 | * @param color | 282 | * @param color |
| 259 | * @param statusBarAlpha | 283 | * @param statusBarAlpha |
| 260 | */ | 284 | */ |
| 261 | - protected void setStatusBarColor(@ColorRes int color, | ||
| 262 | - @IntRange(from = 0, to = 255) int statusBarAlpha) { | 285 | + public void setStatusBarColor(@ColorRes int color, |
| 286 | + @IntRange(from = 0, to = 255) int statusBarAlpha) { | ||
| 263 | StatusBarUtil.setColor(this, ContextCompat.getColor(this, color), statusBarAlpha); | 287 | StatusBarUtil.setColor(this, ContextCompat.getColor(this, color), statusBarAlpha); |
| 264 | } | 288 | } |
| 265 | 289 | ||
| 266 | /** | 290 | /** |
| 267 | * 设置状态栏字体颜色 | 291 | * 设置状态栏字体颜色 |
| 268 | */ | 292 | */ |
| 269 | - protected void setStatusBarTextColor(int type) { | 293 | + public void setStatusBarTextColor(int type) { |
| 270 | if (type == StatusBarConfig.BLACK) { | 294 | if (type == StatusBarConfig.BLACK) { |
| 271 | StatusBarUtil.setStatusBarWrite(this); | 295 | StatusBarUtil.setStatusBarWrite(this); |
| 272 | } else if (type == StatusBarConfig.WHITE) { | 296 | } else if (type == StatusBarConfig.WHITE) { |
| @@ -615,33 +639,36 @@ public abstract class BaseActivity<V extends BaseView, P extends BasePresenter<V | @@ -615,33 +639,36 @@ public abstract class BaseActivity<V extends BaseView, P extends BasePresenter<V | ||
| 615 | @Override | 639 | @Override |
| 616 | protected void onPostCreate(Bundle savedInstanceState) { | 640 | protected void onPostCreate(Bundle savedInstanceState) { |
| 617 | super.onPostCreate(savedInstanceState); | 641 | super.onPostCreate(savedInstanceState); |
| 618 | - if (null != mHelper) { | ||
| 619 | - mHelper.onPostCreate(); | ||
| 620 | - } | ||
| 621 | - } | ||
| 622 | - | ||
| 623 | - @Override | ||
| 624 | - public SwipeBackLayout getSwipeBackLayout() { | ||
| 625 | - if (null != mHelper) { | ||
| 626 | - return mHelper.getSwipeBackLayout(); | ||
| 627 | - } | ||
| 628 | - return null; | ||
| 629 | - } | ||
| 630 | - | ||
| 631 | - @Override | ||
| 632 | - public void setSwipeBackEnable(boolean enable) { | ||
| 633 | - if (null != getSwipeBackLayout()) { | ||
| 634 | - getSwipeBackLayout().setEnableGesture(enable); | ||
| 635 | - } | ||
| 636 | - } | ||
| 637 | - | ||
| 638 | - @Override | ||
| 639 | - public void scrollToFinishActivity() { | ||
| 640 | - if (null != mHelper) { | ||
| 641 | - SwipeBackUtil.convertActivityToTranslucent(this); | ||
| 642 | - getSwipeBackLayout().scrollToFinishActivity(); | ||
| 643 | - } | ||
| 644 | - } | 642 | +// if (null != mHelper) { |
| 643 | +// mHelper.onPostCreate(); | ||
| 644 | +// } | ||
| 645 | + mDelegate.onPostCreate(savedInstanceState); | ||
| 646 | + mSwipeDelegate.onPostCreate(savedInstanceState); | ||
| 647 | + | ||
| 648 | + } | ||
| 649 | + | ||
| 650 | +// @Override | ||
| 651 | +// public SwipeBackLayout getSwipeBackLayout() { | ||
| 652 | +// if (null != mHelper) { | ||
| 653 | +// return mHelper.getSwipeBackLayout(); | ||
| 654 | +// } | ||
| 655 | +// return null; | ||
| 656 | +// } | ||
| 657 | +// | ||
| 658 | +// @Override | ||
| 659 | +// public void setSwipeBackEnable(boolean enable) { | ||
| 660 | +// if (null != getSwipeBackLayout()) { | ||
| 661 | +// getSwipeBackLayout().setEnableGesture(enable); | ||
| 662 | +// } | ||
| 663 | +// } | ||
| 664 | + | ||
| 665 | +// @Override | ||
| 666 | +// public void scrollToFinishActivity() { | ||
| 667 | +// if (null != mHelper) { | ||
| 668 | +// SwipeBackUtil.convertActivityToTranslucent(this); | ||
| 669 | +// getSwipeBackLayout().scrollToFinishActivity(); | ||
| 670 | +// } | ||
| 671 | +// } | ||
| 645 | 672 | ||
| 646 | 673 | ||
| 647 | public void logError(Object info) { | 674 | public void logError(Object info) { |
| @@ -671,4 +698,278 @@ public abstract class BaseActivity<V extends BaseView, P extends BasePresenter<V | @@ -671,4 +698,278 @@ public abstract class BaseActivity<V extends BaseView, P extends BasePresenter<V | ||
| 671 | public void logXml(String xml) { | 698 | public void logXml(String xml) { |
| 672 | Logger.xml(xml); | 699 | Logger.xml(xml); |
| 673 | } | 700 | } |
| 701 | + | ||
| 702 | + /*****************************fragment管理****************************************/ | ||
| 703 | + @Override | ||
| 704 | + public SupportActivityDelegate getSupportDelegate() { | ||
| 705 | + return mDelegate; | ||
| 706 | + } | ||
| 707 | + | ||
| 708 | + /** | ||
| 709 | + * Perform some extra transactions. | ||
| 710 | + * 额外的事务:自定义Tag,添加SharedElement动画,操作非回退栈Fragment | ||
| 711 | + */ | ||
| 712 | + @Override | ||
| 713 | + public ExtraTransaction extraTransaction() { | ||
| 714 | + return mDelegate.extraTransaction(); | ||
| 715 | + } | ||
| 716 | + | ||
| 717 | + /** | ||
| 718 | + * Note: return mDelegate.dispatchTouchEvent(ev) || super.dispatchTouchEvent(ev); | ||
| 719 | + */ | ||
| 720 | + @Override | ||
| 721 | + public boolean dispatchTouchEvent(MotionEvent ev) { | ||
| 722 | + return mDelegate.dispatchTouchEvent(ev) || super.dispatchTouchEvent(ev); | ||
| 723 | + } | ||
| 724 | + | ||
| 725 | + /** | ||
| 726 | + * 不建议复写该方法,请使用 {@link #onBackPressedSupport} 代替 | ||
| 727 | + */ | ||
| 728 | + @Override | ||
| 729 | + public void onBackPressed() { | ||
| 730 | + mDelegate.onBackPressed(); | ||
| 731 | + } | ||
| 732 | + | ||
| 733 | + /** | ||
| 734 | + * 该方法回调时机为,Activity回退栈内Fragment的数量 小于等于1 时,默认finish Activity | ||
| 735 | + * 请尽量复写该方法,避免复写onBackPress(),以保证SupportFragment内的onBackPressedSupport()回退事件正常执行 | ||
| 736 | + */ | ||
| 737 | + @Override | ||
| 738 | + public void onBackPressedSupport() { | ||
| 739 | + mDelegate.onBackPressedSupport(); | ||
| 740 | + } | ||
| 741 | + | ||
| 742 | + /** | ||
| 743 | + * 获取设置的全局动画 copy | ||
| 744 | + * | ||
| 745 | + * @return FragmentAnimator | ||
| 746 | + */ | ||
| 747 | + @Override | ||
| 748 | + public FragmentAnimator getFragmentAnimator() { | ||
| 749 | + return mDelegate.getFragmentAnimator(); | ||
| 750 | + } | ||
| 751 | + | ||
| 752 | + /** | ||
| 753 | + * Set all fragments animation. | ||
| 754 | + * 设置Fragment内的全局动画 | ||
| 755 | + */ | ||
| 756 | + @Override | ||
| 757 | + public void setFragmentAnimator(FragmentAnimator fragmentAnimator) { | ||
| 758 | + mDelegate.setFragmentAnimator(fragmentAnimator); | ||
| 759 | + } | ||
| 760 | + | ||
| 761 | + /** | ||
| 762 | + * Set all fragments animation. | ||
| 763 | + * 构建Fragment转场动画 | ||
| 764 | + * <p/> | ||
| 765 | + * 如果是在Activity内实现,则构建的是Activity内所有Fragment的转场动画, | ||
| 766 | + * 如果是在Fragment内实现,则构建的是该Fragment的转场动画,此时优先级 > Activity的onCreateFragmentAnimator() | ||
| 767 | + * | ||
| 768 | + * @return FragmentAnimator对象 | ||
| 769 | + */ | ||
| 770 | + @Override | ||
| 771 | + public FragmentAnimator onCreateFragmentAnimator() { | ||
| 772 | + return mDelegate.onCreateFragmentAnimator(); | ||
| 773 | + } | ||
| 774 | + | ||
| 775 | + @Override | ||
| 776 | + public void post(Runnable runnable) { | ||
| 777 | + mDelegate.post(runnable); | ||
| 778 | + } | ||
| 779 | + | ||
| 780 | + /****************************************以下为可选方法(Optional methods)******************************************************/ | ||
| 781 | + | ||
| 782 | + /** | ||
| 783 | + * 加载根Fragment, 即Activity内的第一个Fragment 或 Fragment内的第一个子Fragment | ||
| 784 | + * | ||
| 785 | + * @param containerId 容器id | ||
| 786 | + * @param toFragment 目标Fragment | ||
| 787 | + */ | ||
| 788 | + public void loadRootFragment(int containerId, @NonNull ISupportFragment toFragment) { | ||
| 789 | + mDelegate.loadRootFragment(containerId, toFragment); | ||
| 790 | + } | ||
| 791 | + | ||
| 792 | + public void loadRootFragment(int containerId, ISupportFragment toFragment, boolean addToBackStack, boolean allowAnimation) { | ||
| 793 | + mDelegate.loadRootFragment(containerId, toFragment, addToBackStack, allowAnimation); | ||
| 794 | + } | ||
| 795 | + | ||
| 796 | + /** | ||
| 797 | + * 加载多个同级根Fragment,类似Wechat, QQ主页的场景 | ||
| 798 | + */ | ||
| 799 | + public void loadMultipleRootFragment(int containerId, int showPosition, ISupportFragment... toFragments) { | ||
| 800 | + mDelegate.loadMultipleRootFragment(containerId, showPosition, toFragments); | ||
| 801 | + } | ||
| 802 | + | ||
| 803 | + /** | ||
| 804 | + * show一个Fragment,hide其他同栈所有Fragment | ||
| 805 | + * 使用该方法时,要确保同级栈内无多余的Fragment,(只有通过loadMultipleRootFragment()载入的Fragment) | ||
| 806 | + * <p> | ||
| 807 | + * 建议使用更明确的{@link #showHideFragment(ISupportFragment, ISupportFragment)} | ||
| 808 | + * | ||
| 809 | + * @param showFragment 需要show的Fragment | ||
| 810 | + */ | ||
| 811 | + public void showHideFragment(ISupportFragment showFragment) { | ||
| 812 | + mDelegate.showHideFragment(showFragment); | ||
| 813 | + } | ||
| 814 | + | ||
| 815 | + /** | ||
| 816 | + * show一个Fragment,hide一个Fragment ; 主要用于类似微信主页那种 切换tab的情况 | ||
| 817 | + */ | ||
| 818 | + public void showHideFragment(ISupportFragment showFragment, ISupportFragment hideFragment) { | ||
| 819 | + mDelegate.showHideFragment(showFragment, hideFragment); | ||
| 820 | + } | ||
| 821 | + | ||
| 822 | + /** | ||
| 823 | + * It is recommended to use {@link SupportFragment#start(ISupportFragment)}. | ||
| 824 | + */ | ||
| 825 | + public void start(ISupportFragment toFragment) { | ||
| 826 | + mDelegate.start(toFragment); | ||
| 827 | + } | ||
| 828 | + | ||
| 829 | + /** | ||
| 830 | + * It is recommended to use {@link SupportFragment#start(ISupportFragment, int)}. | ||
| 831 | + * | ||
| 832 | + * @param launchMode Similar to Activity's LaunchMode. | ||
| 833 | + */ | ||
| 834 | + public void start(ISupportFragment toFragment, @ISupportFragment.LaunchMode int launchMode) { | ||
| 835 | + mDelegate.start(toFragment, launchMode); | ||
| 836 | + } | ||
| 837 | + | ||
| 838 | + /** | ||
| 839 | + * It is recommended to use {@link SupportFragment#startForResult(ISupportFragment, int)}. | ||
| 840 | + * Launch an fragment for which you would like a result when it poped. | ||
| 841 | + */ | ||
| 842 | + public void startForResult(ISupportFragment toFragment, int requestCode) { | ||
| 843 | + mDelegate.startForResult(toFragment, requestCode); | ||
| 844 | + } | ||
| 845 | + | ||
| 846 | + /** | ||
| 847 | + * It is recommended to use {@link SupportFragment#startWithPop(ISupportFragment)}. | ||
| 848 | + * Start the target Fragment and pop itself | ||
| 849 | + */ | ||
| 850 | + public void startWithPop(ISupportFragment toFragment) { | ||
| 851 | + mDelegate.startWithPop(toFragment); | ||
| 852 | + } | ||
| 853 | + | ||
| 854 | + /** | ||
| 855 | + * It is recommended to use {@link SupportFragment#startWithPopTo(ISupportFragment, Class, boolean)}. | ||
| 856 | + * | ||
| 857 | + * @see #popTo(Class, boolean) | ||
| 858 | + * + | ||
| 859 | + * @see #start(ISupportFragment) | ||
| 860 | + */ | ||
| 861 | + public void startWithPopTo(ISupportFragment toFragment, Class<?> targetFragmentClass, boolean includeTargetFragment) { | ||
| 862 | + mDelegate.startWithPopTo(toFragment, targetFragmentClass, includeTargetFragment); | ||
| 863 | + } | ||
| 864 | + | ||
| 865 | + /** | ||
| 866 | + * It is recommended to use {@link SupportFragment#replaceFragment(ISupportFragment, boolean)}. | ||
| 867 | + */ | ||
| 868 | + public void replaceFragment(ISupportFragment toFragment, boolean addToBackStack) { | ||
| 869 | + mDelegate.replaceFragment(toFragment, addToBackStack); | ||
| 870 | + } | ||
| 871 | + | ||
| 872 | + /** | ||
| 873 | + * Pop the fragment. | ||
| 874 | + */ | ||
| 875 | + public void pop() { | ||
| 876 | + mDelegate.pop(); | ||
| 877 | + } | ||
| 878 | + | ||
| 879 | + /** | ||
| 880 | + * Pop the last fragment transition from the manager's fragment | ||
| 881 | + * back stack. | ||
| 882 | + * <p> | ||
| 883 | + * 出栈到目标fragment | ||
| 884 | + * | ||
| 885 | + * @param targetFragmentClass 目标fragment | ||
| 886 | + * @param includeTargetFragment 是否包含该fragment | ||
| 887 | + */ | ||
| 888 | + public void popTo(Class<?> targetFragmentClass, boolean includeTargetFragment) { | ||
| 889 | + mDelegate.popTo(targetFragmentClass, includeTargetFragment); | ||
| 890 | + } | ||
| 891 | + | ||
| 892 | + /** | ||
| 893 | + * If you want to begin another FragmentTransaction immediately after popTo(), use this method. | ||
| 894 | + * 如果你想在出栈后, 立刻进行FragmentTransaction操作,请使用该方法 | ||
| 895 | + */ | ||
| 896 | + public void popTo(Class<?> targetFragmentClass, boolean includeTargetFragment, Runnable afterPopTransactionRunnable) { | ||
| 897 | + mDelegate.popTo(targetFragmentClass, includeTargetFragment, afterPopTransactionRunnable); | ||
| 898 | + } | ||
| 899 | + | ||
| 900 | + public void popTo(Class<?> targetFragmentClass, boolean includeTargetFragment, Runnable afterPopTransactionRunnable, int popAnim) { | ||
| 901 | + mDelegate.popTo(targetFragmentClass, includeTargetFragment, afterPopTransactionRunnable, popAnim); | ||
| 902 | + } | ||
| 903 | + | ||
| 904 | + /** | ||
| 905 | + * 当Fragment根布局 没有 设定background属性时, | ||
| 906 | + * Fragmentation默认使用Theme的android:windowbackground作为Fragment的背景, | ||
| 907 | + * 可以通过该方法改变其内所有Fragment的默认背景。 | ||
| 908 | + */ | ||
| 909 | + public void setDefaultFragmentBackground(@DrawableRes int backgroundRes) { | ||
| 910 | + mDelegate.setDefaultFragmentBackground(backgroundRes); | ||
| 911 | + } | ||
| 912 | + | ||
| 913 | + /** | ||
| 914 | + * 得到位于栈顶Fragment | ||
| 915 | + */ | ||
| 916 | + public ISupportFragment getTopFragment() { | ||
| 917 | + return SupportHelper.getTopFragment(getSupportFragmentManager()); | ||
| 918 | + } | ||
| 919 | + | ||
| 920 | + /** | ||
| 921 | + * 获取栈内的fragment对象 | ||
| 922 | + */ | ||
| 923 | + public <T extends ISupportFragment> T findFragment(Class<T> fragmentClass) { | ||
| 924 | + return SupportHelper.findFragment(getSupportFragmentManager(), fragmentClass); | ||
| 925 | + } | ||
| 926 | + | ||
| 927 | + | ||
| 928 | + /** | ||
| 929 | + * 显示fragment栈视图 | ||
| 930 | + */ | ||
| 931 | + public void showFragmetStackView() { | ||
| 932 | + Fragmentation.builder() | ||
| 933 | + // show stack view. Mode: BUBBLE, SHAKE, NONE | ||
| 934 | + .stackViewMode(Fragmentation.BUBBLE) | ||
| 935 | + .debug(AppConfig.isDebug()) | ||
| 936 | + .install(); | ||
| 937 | + } | ||
| 938 | +/***********************************滑动返回********************************************/ | ||
| 939 | + /** | ||
| 940 | + * 是否可滑动 | ||
| 941 | + * | ||
| 942 | + * @param enable | ||
| 943 | + */ | ||
| 944 | + @Override | ||
| 945 | + public void setSwipeBackEnable(boolean enable) { | ||
| 946 | + isOpenSwipBack = enable; | ||
| 947 | + mSwipeDelegate.setSwipeBackEnable(enable); | ||
| 948 | + } | ||
| 949 | + | ||
| 950 | + @Override | ||
| 951 | + public void setEdgeLevel(SwipeBackLayout.EdgeLevel edgeLevel) { | ||
| 952 | + mSwipeDelegate.setEdgeLevel(edgeLevel); | ||
| 953 | + } | ||
| 954 | + | ||
| 955 | + @Override | ||
| 956 | + public void setEdgeLevel(int widthPixel) { | ||
| 957 | + mSwipeDelegate.setEdgeLevel(widthPixel); | ||
| 958 | + } | ||
| 959 | + | ||
| 960 | + /** | ||
| 961 | + * 限制SwipeBack的条件,默认栈内Fragment数 <= 1时 , 优先滑动退出Activity , 而不是Fragment | ||
| 962 | + * | ||
| 963 | + * @return true: Activity优先滑动退出; false: Fragment优先滑动退出 | ||
| 964 | + */ | ||
| 965 | + @Override | ||
| 966 | + public boolean swipeBackPriority() { | ||
| 967 | + return mSwipeDelegate.swipeBackPriority(); | ||
| 968 | + } | ||
| 969 | + | ||
| 970 | + @Override | ||
| 971 | + public SwipeBackLayout getSwipeBackLayout() { | ||
| 972 | + return mSwipeDelegate.getSwipeBackLayout(); | ||
| 973 | + } | ||
| 974 | + | ||
| 674 | } | 975 | } |
| 675 | \ No newline at end of file | 976 | \ 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; |
| @@ -24,6 +28,16 @@ import com.cnlive.core.libs.base.util.ReflectUtil; | @@ -24,6 +28,16 @@ import com.cnlive.core.libs.base.util.ReflectUtil; | ||
| 24 | import com.cnlive.core.libs.base.frame.view.BaseView; | 28 | import com.cnlive.core.libs.base.frame.view.BaseView; |
| 25 | import com.cnlive.core.libs.base.util.StatusBarConfig; | 29 | import com.cnlive.core.libs.base.util.StatusBarConfig; |
| 26 | import com.cnlive.core.libs.base.util.StatusBarUtil; | 30 | import com.cnlive.core.libs.base.util.StatusBarUtil; |
| 31 | +import com.me.yokeyword.fragmentation.ExtraTransaction; | ||
| 32 | +import com.me.yokeyword.fragmentation.ISupportFragment; | ||
| 33 | +import com.me.yokeyword.fragmentation.SupportFragmentDelegate; | ||
| 34 | +import com.me.yokeyword.fragmentation.SupportHelper; | ||
| 35 | +import com.me.yokeyword.fragmentation.SwipeBackLayout; | ||
| 36 | +import com.me.yokeyword.fragmentation.anim.FragmentAnimator; | ||
| 37 | +import com.me.yokeyword.fragmentation_swipeback.core.ISwipeBackFragment; | ||
| 38 | +import com.me.yokeyword.fragmentation_swipeback.core.SwipeBackFragmentDelegate; | ||
| 39 | +import com.orhanobut.logger.Logger; | ||
| 40 | + | ||
| 27 | 41 | ||
| 28 | import static android.content.Context.INPUT_METHOD_SERVICE; | 42 | import static android.content.Context.INPUT_METHOD_SERVICE; |
| 29 | 43 | ||
| @@ -34,19 +48,26 @@ import static android.content.Context.INPUT_METHOD_SERVICE; | @@ -34,19 +48,26 @@ import static android.content.Context.INPUT_METHOD_SERVICE; | ||
| 34 | * @param <P> | 48 | * @param <P> |
| 35 | * @author ys | 49 | * @author ys |
| 36 | */ | 50 | */ |
| 37 | -public abstract class BaseFragment<V extends BaseView, P extends BasePresenter<V>> extends com.hannesdorfmann.mosby3.mvp.MvpFragment<V, P> { | 51 | +public abstract class BaseFragment<V extends BaseView, P extends BasePresenter<V>> extends com.hannesdorfmann.mosby3.mvp.MvpFragment<V, P> implements ISupportFragment, ISwipeBackFragment { |
| 38 | private V view; | 52 | private V view; |
| 39 | private P presenter; | 53 | private P presenter; |
| 40 | - protected final String TAG = this.getClass().getSimpleName(); | 54 | + public final String TAG = this.getClass().getSimpleName(); |
| 41 | public ViewDataBinding baseBinding; | 55 | public ViewDataBinding baseBinding; |
| 42 | public View baseView; | 56 | public View baseView; |
| 43 | public BaseActivity me; | 57 | public BaseActivity me; |
| 58 | + //fragment管理 | ||
| 59 | + private final SupportFragmentDelegate mDelegate = new SupportFragmentDelegate(this); | ||
| 60 | + //fragment滑动返回 | ||
| 61 | + private final SwipeBackFragmentDelegate mSwipeDelegate = new SwipeBackFragmentDelegate(this); | ||
| 44 | 62 | ||
| 45 | @Override | 63 | @Override |
| 46 | public void onCreate(Bundle savedInstanceState) { | 64 | public void onCreate(Bundle savedInstanceState) { |
| 47 | super.onCreate(savedInstanceState); | 65 | super.onCreate(savedInstanceState); |
| 48 | if (getActivity() == null) return; | 66 | if (getActivity() == null) return; |
| 49 | me = (BaseActivity) getActivity(); | 67 | me = (BaseActivity) getActivity(); |
| 68 | + mDelegate.onCreate(savedInstanceState); | ||
| 69 | + mSwipeDelegate.onCreate(savedInstanceState); | ||
| 70 | + setSwipeBackEnable(me.isOpenSwipBack()); | ||
| 50 | ARouter.getInstance().inject(this); | 71 | ARouter.getInstance().inject(this); |
| 51 | initFragmentStyle(); | 72 | initFragmentStyle(); |
| 52 | initParams(); | 73 | initParams(); |
| @@ -57,10 +78,18 @@ public abstract class BaseFragment<V extends BaseView, P extends BasePresenter<V | @@ -57,10 +78,18 @@ public abstract class BaseFragment<V extends BaseView, P extends BasePresenter<V | ||
| 57 | public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { | 78 | public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { |
| 58 | if (0 != getBindLayoutId()) { | 79 | if (0 != getBindLayoutId()) { |
| 59 | baseBinding = DataBindingUtil.inflate(inflater, getBindLayoutId(), container, false); | 80 | baseBinding = DataBindingUtil.inflate(inflater, getBindLayoutId(), container, false); |
| 60 | - return baseBinding.getRoot(); | 81 | + if (me.isOpenSwipBack()) { |
| 82 | + return attachToSwipeBack(baseBinding.getRoot()); | ||
| 83 | + } else { | ||
| 84 | + return baseBinding.getRoot(); | ||
| 85 | + } | ||
| 61 | } else if (0 != getViewLayoutId()) { | 86 | } else if (0 != getViewLayoutId()) { |
| 62 | baseView = inflater.inflate(getViewLayoutId(), container, false); | 87 | baseView = inflater.inflate(getViewLayoutId(), container, false); |
| 63 | - return baseView; | 88 | + if (me.isOpenSwipBack()) { |
| 89 | + return attachToSwipeBack(baseView); | ||
| 90 | + } else { | ||
| 91 | + return baseView; | ||
| 92 | + } | ||
| 64 | } | 93 | } |
| 65 | return super.onCreateView(inflater, container, savedInstanceState); | 94 | return super.onCreateView(inflater, container, savedInstanceState); |
| 66 | } | 95 | } |
| @@ -68,6 +97,7 @@ public abstract class BaseFragment<V extends BaseView, P extends BasePresenter<V | @@ -68,6 +97,7 @@ public abstract class BaseFragment<V extends BaseView, P extends BasePresenter<V | ||
| 68 | @Override | 97 | @Override |
| 69 | public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { | 98 | public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { |
| 70 | super.onViewCreated(view, savedInstanceState); | 99 | super.onViewCreated(view, savedInstanceState); |
| 100 | + mSwipeDelegate.onViewCreated(view, savedInstanceState); | ||
| 71 | if (null != getMvpView() && null != getPresenter()) { | 101 | if (null != getMvpView() && null != getPresenter()) { |
| 72 | initBindingData(); | 102 | initBindingData(); |
| 73 | initView(); | 103 | initView(); |
| @@ -153,48 +183,40 @@ public abstract class BaseFragment<V extends BaseView, P extends BasePresenter<V | @@ -153,48 +183,40 @@ public abstract class BaseFragment<V extends BaseView, P extends BasePresenter<V | ||
| 153 | */ | 183 | */ |
| 154 | protected void setStatusBarColor(@ColorRes int color, | 184 | protected void setStatusBarColor(@ColorRes int color, |
| 155 | @IntRange(from = 0, to = 255) int statusBarAlpha) { | 185 | @IntRange(from = 0, to = 255) int statusBarAlpha) { |
| 156 | - StatusBarUtil.setColor(getActivity(), ContextCompat.getColor(getActivity(), color), statusBarAlpha); | 186 | + me.setStatusBarColor(color, statusBarAlpha); |
| 157 | } | 187 | } |
| 158 | 188 | ||
| 159 | - /** | ||
| 160 | - * 设置状态栏字体颜色 | ||
| 161 | - */ | ||
| 162 | - protected void setStatusBarTextColor(int type) { | ||
| 163 | - if (type == StatusBarConfig.BLACK) { | ||
| 164 | - StatusBarUtil.setStatusBarWrite(getActivity()); | ||
| 165 | - } else if (type == StatusBarConfig.WHITE) { | ||
| 166 | - StatusBarUtil.setStatusBarDarkMode(getActivity()); | 189 | + @Override |
| 190 | + public void onDestroy() { | ||
| 191 | + mDelegate.onDestroy(); | ||
| 192 | + mSwipeDelegate.onDestroyView(); | ||
| 193 | + super.onDestroy(); | ||
| 194 | + if (null != baseBinding) { | ||
| 195 | + baseBinding.unbind(); | ||
| 167 | } | 196 | } |
| 168 | } | 197 | } |
| 169 | 198 | ||
| 170 | /** | 199 | /** |
| 171 | - * 隐藏软键盘 | 200 | + * 设置状态栏字体颜色 |
| 172 | */ | 201 | */ |
| 173 | - public void hideSoftInput() { | ||
| 174 | - InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(INPUT_METHOD_SERVICE); | ||
| 175 | - if (getActivity().getCurrentFocus() != null && null != imm) { | ||
| 176 | - imm.hideSoftInputFromWindow(getActivity().getCurrentFocus().getWindowToken(), 0); | ||
| 177 | - } | 202 | + protected void setStatusBarTextColor(int type) { |
| 203 | + me.setStatusBarTextColor(type); | ||
| 178 | } | 204 | } |
| 179 | 205 | ||
| 206 | + | ||
| 180 | /** | 207 | /** |
| 181 | * 显示软键盘 | 208 | * 显示软键盘 |
| 182 | */ | 209 | */ |
| 183 | public void showSoftInput() { | 210 | public void showSoftInput() { |
| 184 | - InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(INPUT_METHOD_SERVICE); | ||
| 185 | - if (getActivity().getCurrentFocus() != null && null != imm) { | ||
| 186 | - imm.showSoftInputFromInputMethod(getActivity().getCurrentFocus().getWindowToken(), 0); | ||
| 187 | - } | 211 | + me.showSoftInput(); |
| 188 | } | 212 | } |
| 189 | 213 | ||
| 190 | - /** | ||
| 191 | - * 显示软键盘 | ||
| 192 | - */ | ||
| 193 | - public void showSoftInput(View view) { | ||
| 194 | - // InputMethodManager.SHOW_FORCED); | ||
| 195 | - InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(INPUT_METHOD_SERVICE); | ||
| 196 | - imm.showSoftInput(view, InputMethodManager.SHOW_FORCED); | ||
| 197 | - } | 214 | +// /** |
| 215 | +// * 显示软键盘 | ||
| 216 | +// */ | ||
| 217 | +// public void showSoftInput(View view) { | ||
| 218 | +// me.showSoftInput(view); | ||
| 219 | +// } | ||
| 198 | 220 | ||
| 199 | 221 | ||
| 200 | /*********************************************************/ | 222 | /*********************************************************/ |
| @@ -238,4 +260,475 @@ public abstract class BaseFragment<V extends BaseView, P extends BasePresenter<V | @@ -238,4 +260,475 @@ public abstract class BaseFragment<V extends BaseView, P extends BasePresenter<V | ||
| 238 | return me.checkPermissions(permission); | 260 | return me.checkPermissions(permission); |
| 239 | } | 261 | } |
| 240 | 262 | ||
| 263 | + /************************************fragment管理********************************************/ | ||
| 264 | + @Override | ||
| 265 | + public SupportFragmentDelegate getSupportDelegate() { | ||
| 266 | + return mDelegate; | ||
| 267 | + } | ||
| 268 | + | ||
| 269 | + /** | ||
| 270 | + * Perform some extra transactions. | ||
| 271 | + * 额外的事务:自定义Tag,添加SharedElement动画,操作非回退栈Fragment | ||
| 272 | + */ | ||
| 273 | + @Override | ||
| 274 | + public ExtraTransaction extraTransaction() { | ||
| 275 | + return mDelegate.extraTransaction(); | ||
| 276 | + } | ||
| 277 | + | ||
| 278 | + @Override | ||
| 279 | + public void onAttach(Activity activity) { | ||
| 280 | + super.onAttach(activity); | ||
| 281 | + mDelegate.onAttach(activity); | ||
| 282 | + me = (BaseActivity) mDelegate.getActivity(); | ||
| 283 | + } | ||
| 284 | + | ||
| 285 | + @Override | ||
| 286 | + public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) { | ||
| 287 | + return mDelegate.onCreateAnimation(transit, enter, nextAnim); | ||
| 288 | + } | ||
| 289 | + | ||
| 290 | + @Override | ||
| 291 | + public void onActivityCreated(@Nullable Bundle savedInstanceState) { | ||
| 292 | + super.onActivityCreated(savedInstanceState); | ||
| 293 | + mDelegate.onActivityCreated(savedInstanceState); | ||
| 294 | + } | ||
| 295 | + | ||
| 296 | + @Override | ||
| 297 | + public void onSaveInstanceState(Bundle outState) { | ||
| 298 | + super.onSaveInstanceState(outState); | ||
| 299 | + mDelegate.onSaveInstanceState(outState); | ||
| 300 | + } | ||
| 301 | + | ||
| 302 | + @Override | ||
| 303 | + public void onResume() { | ||
| 304 | + super.onResume(); | ||
| 305 | + mDelegate.onResume(); | ||
| 306 | + } | ||
| 307 | + | ||
| 308 | + @Override | ||
| 309 | + public void onPause() { | ||
| 310 | + super.onPause(); | ||
| 311 | + mDelegate.onPause(); | ||
| 312 | + } | ||
| 313 | + | ||
| 314 | + @Override | ||
| 315 | + public void onDestroyView() { | ||
| 316 | + mDelegate.onDestroyView(); | ||
| 317 | + super.onDestroyView(); | ||
| 318 | + } | ||
| 319 | + | ||
| 320 | + @Override | ||
| 321 | + public void onHiddenChanged(boolean hidden) { | ||
| 322 | + super.onHiddenChanged(hidden); | ||
| 323 | + mDelegate.onHiddenChanged(hidden); | ||
| 324 | + mSwipeDelegate.onHiddenChanged(hidden); | ||
| 325 | + } | ||
| 326 | + | ||
| 327 | + @Override | ||
| 328 | + public void setUserVisibleHint(boolean isVisibleToUser) { | ||
| 329 | + super.setUserVisibleHint(isVisibleToUser); | ||
| 330 | + mDelegate.setUserVisibleHint(isVisibleToUser); | ||
| 331 | + } | ||
| 332 | + | ||
| 333 | + /*************************************log******************************************/ | ||
| 334 | + public void logError(Object info) { | ||
| 335 | + Logger.e(TAG, info); | ||
| 336 | + } | ||
| 337 | + | ||
| 338 | + public void logDebug(Object info) { | ||
| 339 | + Logger.d(TAG, info); | ||
| 340 | + } | ||
| 341 | + | ||
| 342 | + public void logWarn(Object info) { | ||
| 343 | + Logger.w(TAG, info); | ||
| 344 | + } | ||
| 345 | + | ||
| 346 | + public void logInfo(Object info) { | ||
| 347 | + Logger.i(TAG, info); | ||
| 348 | + } | ||
| 349 | + | ||
| 350 | + public void logVerbose(Object info) { | ||
| 351 | + Logger.v(TAG, info); | ||
| 352 | + } | ||
| 353 | + | ||
| 354 | + public void logJson(String json) { | ||
| 355 | + Logger.json(json); | ||
| 356 | + } | ||
| 357 | + | ||
| 358 | + public void logXml(String xml) { | ||
| 359 | + Logger.xml(xml); | ||
| 360 | + } | ||
| 361 | +/*********************************fragment 管理******************************************/ | ||
| 362 | + /** | ||
| 363 | + * Causes the Runnable r to be added to the action queue. | ||
| 364 | + * <p> | ||
| 365 | + * The runnable will be run after all the previous action has been run. | ||
| 366 | + * <p> | ||
| 367 | + * 前面的事务全部执行后 执行该Action | ||
| 368 | + * | ||
| 369 | + * @deprecated Use {@link #post(Runnable)} instead. | ||
| 370 | + */ | ||
| 371 | + @Deprecated | ||
| 372 | + @Override | ||
| 373 | + public void enqueueAction(Runnable runnable) { | ||
| 374 | + mDelegate.enqueueAction(runnable); | ||
| 375 | + } | ||
| 376 | + | ||
| 377 | + /** | ||
| 378 | + * Causes the Runnable r to be added to the action queue. | ||
| 379 | + * <p> | ||
| 380 | + * The runnable will be run after all the previous action has been run. | ||
| 381 | + * <p> | ||
| 382 | + * 前面的事务全部执行后 执行该Action | ||
| 383 | + */ | ||
| 384 | + @Override | ||
| 385 | + public void post(Runnable runnable) { | ||
| 386 | + mDelegate.post(runnable); | ||
| 387 | + } | ||
| 388 | + | ||
| 389 | + /** | ||
| 390 | + * Called when the enter-animation end. | ||
| 391 | + * 入栈动画 结束时,回调 | ||
| 392 | + */ | ||
| 393 | + @Override | ||
| 394 | + public void onEnterAnimationEnd(Bundle savedInstanceState) { | ||
| 395 | + mDelegate.onEnterAnimationEnd(savedInstanceState); | ||
| 396 | + } | ||
| 397 | + | ||
| 398 | + | ||
| 399 | + /** | ||
| 400 | + * Lazy initial,Called when fragment is first called. | ||
| 401 | + * <p> | ||
| 402 | + * 同级下的 懒加载 + ViewPager下的懒加载 的结合回调方法 | ||
| 403 | + */ | ||
| 404 | + @Override | ||
| 405 | + public void onLazyInitView(@Nullable Bundle savedInstanceState) { | ||
| 406 | + mDelegate.onLazyInitView(savedInstanceState); | ||
| 407 | + } | ||
| 408 | + | ||
| 409 | + /** | ||
| 410 | + * Called when the fragment is visible. | ||
| 411 | + * 当Fragment对用户可见时回调 | ||
| 412 | + * <p> | ||
| 413 | + * Is the combination of [onHiddenChanged() + onResume()/onPause() + setUserVisibleHint()] | ||
| 414 | + */ | ||
| 415 | + @Override | ||
| 416 | + public void onSupportVisible() { | ||
| 417 | + mDelegate.onSupportVisible(); | ||
| 418 | + } | ||
| 419 | + | ||
| 420 | + /** | ||
| 421 | + * Called when the fragment is invivible. | ||
| 422 | + * <p> | ||
| 423 | + * Is the combination of [onHiddenChanged() + onResume()/onPause() + setUserVisibleHint()] | ||
| 424 | + */ | ||
| 425 | + @Override | ||
| 426 | + public void onSupportInvisible() { | ||
| 427 | + mDelegate.onSupportInvisible(); | ||
| 428 | + } | ||
| 429 | + | ||
| 430 | + /** | ||
| 431 | + * Return true if the fragment has been supportVisible. | ||
| 432 | + */ | ||
| 433 | + @Override | ||
| 434 | + final public boolean isSupportVisible() { | ||
| 435 | + return mDelegate.isSupportVisible(); | ||
| 436 | + } | ||
| 437 | + | ||
| 438 | + /** | ||
| 439 | + * Set fragment animation with a higher priority than the ISupportActivity | ||
| 440 | + * 设定当前Fragmemt动画,优先级比在SupportActivity里高 | ||
| 441 | + */ | ||
| 442 | + @Override | ||
| 443 | + public FragmentAnimator onCreateFragmentAnimator() { | ||
| 444 | + return mDelegate.onCreateFragmentAnimator(); | ||
| 445 | + } | ||
| 446 | + | ||
| 447 | + /** | ||
| 448 | + * 获取设置的全局动画 copy | ||
| 449 | + * | ||
| 450 | + * @return FragmentAnimator | ||
| 451 | + */ | ||
| 452 | + @Override | ||
| 453 | + public FragmentAnimator getFragmentAnimator() { | ||
| 454 | + return mDelegate.getFragmentAnimator(); | ||
| 455 | + } | ||
| 456 | + | ||
| 457 | + /** | ||
| 458 | + * 设置Fragment内的全局动画 | ||
| 459 | + */ | ||
| 460 | + @Override | ||
| 461 | + public void setFragmentAnimator(FragmentAnimator fragmentAnimator) { | ||
| 462 | + mDelegate.setFragmentAnimator(fragmentAnimator); | ||
| 463 | + } | ||
| 464 | + | ||
| 465 | + /** | ||
| 466 | + * 按返回键触发,前提是SupportActivity的onBackPressed()方法能被调用 | ||
| 467 | + * | ||
| 468 | + * @return false则继续向上传递, true则消费掉该事件 | ||
| 469 | + */ | ||
| 470 | + @Override | ||
| 471 | + public boolean onBackPressedSupport() { | ||
| 472 | + return mDelegate.onBackPressedSupport(); | ||
| 473 | + } | ||
| 474 | + | ||
| 475 | + /** | ||
| 476 | + * 类似 {@link Activity#setResult(int, Intent)} | ||
| 477 | + * <p> | ||
| 478 | + * Similar to {@link Activity#setResult(int, Intent)} | ||
| 479 | + * | ||
| 480 | + * @see #startForResult(ISupportFragment, int) | ||
| 481 | + */ | ||
| 482 | + @Override | ||
| 483 | + public void setFragmentResult(int resultCode, Bundle bundle) { | ||
| 484 | + mDelegate.setFragmentResult(resultCode, bundle); | ||
| 485 | + } | ||
| 486 | + | ||
| 487 | + /** | ||
| 488 | + * 类似 {@link Activity#onActivityResult(int, int, Intent)} | ||
| 489 | + * <p> | ||
| 490 | + * Similar to {@link Activity#onActivityResult(int, int, Intent)} | ||
| 491 | + * | ||
| 492 | + * @see #startForResult(ISupportFragment, int) | ||
| 493 | + */ | ||
| 494 | + @Override | ||
| 495 | + public void onFragmentResult(int requestCode, int resultCode, Bundle data) { | ||
| 496 | + mDelegate.onFragmentResult(requestCode, resultCode, data); | ||
| 497 | + } | ||
| 498 | + | ||
| 499 | + /** | ||
| 500 | + * 在start(TargetFragment,LaunchMode)时,启动模式为SingleTask/SingleTop, 回调TargetFragment的该方法 | ||
| 501 | + * 类似 {@link Activity#onNewIntent(Intent)} | ||
| 502 | + * <p> | ||
| 503 | + * Similar to {@link Activity#onNewIntent(Intent)} | ||
| 504 | + * | ||
| 505 | + * @param args putNewBundle(Bundle newBundle) | ||
| 506 | + * @see #start(ISupportFragment, int) | ||
| 507 | + */ | ||
| 508 | + @Override | ||
| 509 | + public void onNewBundle(Bundle args) { | ||
| 510 | + mDelegate.onNewBundle(args); | ||
| 511 | + } | ||
| 512 | + | ||
| 513 | + /** | ||
| 514 | + * 添加NewBundle,用于启动模式为SingleTask/SingleTop时 | ||
| 515 | + * | ||
| 516 | + * @see #start(ISupportFragment, int) | ||
| 517 | + */ | ||
| 518 | + @Override | ||
| 519 | + public void putNewBundle(Bundle newBundle) { | ||
| 520 | + mDelegate.putNewBundle(newBundle); | ||
| 521 | + } | ||
| 522 | + | ||
| 523 | + | ||
| 524 | + /****************************************以下为可选方法(Optional methods)******************************************************/ | ||
| 525 | + | ||
| 526 | + /** | ||
| 527 | + * 隐藏软键盘 | ||
| 528 | + */ | ||
| 529 | + protected void hideSoftInput() { | ||
| 530 | + mDelegate.hideSoftInput(); | ||
| 531 | + } | ||
| 532 | + | ||
| 533 | + /** | ||
| 534 | + * 显示软键盘,调用该方法后,会在onPause时自动隐藏软键盘 | ||
| 535 | + */ | ||
| 536 | + protected void showSoftInput(final View view) { | ||
| 537 | + mDelegate.showSoftInput(view); | ||
| 538 | + } | ||
| 539 | + | ||
| 540 | + /** | ||
| 541 | + * 加载根Fragment, 即Activity内的第一个Fragment 或 Fragment内的第一个子Fragment | ||
| 542 | + * | ||
| 543 | + * @param containerId 容器id | ||
| 544 | + * @param toFragment 目标Fragment | ||
| 545 | + */ | ||
| 546 | + public void loadRootFragment(int containerId, ISupportFragment toFragment) { | ||
| 547 | + mDelegate.loadRootFragment(containerId, toFragment); | ||
| 548 | + } | ||
| 549 | + | ||
| 550 | + public void loadRootFragment(int containerId, ISupportFragment toFragment, boolean addToBackStack, boolean allowAnim) { | ||
| 551 | + mDelegate.loadRootFragment(containerId, toFragment, addToBackStack, allowAnim); | ||
| 552 | + } | ||
| 553 | + | ||
| 554 | + /** | ||
| 555 | + * 加载多个同级根Fragment,类似Wechat, QQ主页的场景 | ||
| 556 | + */ | ||
| 557 | + public void loadMultipleRootFragment(int containerId, int showPosition, ISupportFragment... toFragments) { | ||
| 558 | + mDelegate.loadMultipleRootFragment(containerId, showPosition, toFragments); | ||
| 559 | + } | ||
| 560 | + | ||
| 561 | + /** | ||
| 562 | + * show一个Fragment,hide其他同栈所有Fragment | ||
| 563 | + * 使用该方法时,要确保同级栈内无多余的Fragment,(只有通过loadMultipleRootFragment()载入的Fragment) | ||
| 564 | + * <p> | ||
| 565 | + * 建议使用更明确的{@link #showHideFragment(ISupportFragment, ISupportFragment)} | ||
| 566 | + * | ||
| 567 | + * @param showFragment 需要show的Fragment | ||
| 568 | + */ | ||
| 569 | + public void showHideFragment(ISupportFragment showFragment) { | ||
| 570 | + mDelegate.showHideFragment(showFragment); | ||
| 571 | + } | ||
| 572 | + | ||
| 573 | + /** | ||
| 574 | + * show一个Fragment,hide一个Fragment ; 主要用于类似微信主页那种 切换tab的情况 | ||
| 575 | + */ | ||
| 576 | + public void showHideFragment(ISupportFragment showFragment, ISupportFragment hideFragment) { | ||
| 577 | + mDelegate.showHideFragment(showFragment, hideFragment); | ||
| 578 | + } | ||
| 579 | + | ||
| 580 | + public void start(ISupportFragment toFragment) { | ||
| 581 | + mDelegate.start(toFragment); | ||
| 582 | + } | ||
| 583 | + | ||
| 584 | + /** | ||
| 585 | + * @param launchMode Similar to Activity's LaunchMode. | ||
| 586 | + */ | ||
| 587 | + public void start(final ISupportFragment toFragment, @LaunchMode int launchMode) { | ||
| 588 | + mDelegate.start(toFragment, launchMode); | ||
| 589 | + } | ||
| 590 | + | ||
| 591 | + /** | ||
| 592 | + * Launch an fragment for which you would like a result when it poped. | ||
| 593 | + */ | ||
| 594 | + public void startForResult(ISupportFragment toFragment, int requestCode) { | ||
| 595 | + mDelegate.startForResult(toFragment, requestCode); | ||
| 596 | + } | ||
| 597 | + | ||
| 598 | + /** | ||
| 599 | + * Start the target Fragment and pop itself | ||
| 600 | + */ | ||
| 601 | + public void startWithPop(ISupportFragment toFragment) { | ||
| 602 | + mDelegate.startWithPop(toFragment); | ||
| 603 | + } | ||
| 604 | + | ||
| 605 | + /** | ||
| 606 | + * @see #popTo(Class, boolean) | ||
| 607 | + * + | ||
| 608 | + * @see #start(ISupportFragment) | ||
| 609 | + */ | ||
| 610 | + public void startWithPopTo(ISupportFragment toFragment, Class<?> targetFragmentClass, boolean includeTargetFragment) { | ||
| 611 | + mDelegate.startWithPopTo(toFragment, targetFragmentClass, includeTargetFragment); | ||
| 612 | + } | ||
| 613 | + | ||
| 614 | + | ||
| 615 | + public void replaceFragment(ISupportFragment toFragment, boolean addToBackStack) { | ||
| 616 | + mDelegate.replaceFragment(toFragment, addToBackStack); | ||
| 617 | + } | ||
| 618 | + | ||
| 619 | + public void pop() { | ||
| 620 | + mDelegate.pop(); | ||
| 621 | + } | ||
| 622 | + | ||
| 623 | + /** | ||
| 624 | + * Pop the child fragment. | ||
| 625 | + */ | ||
| 626 | + public void popChild() { | ||
| 627 | + mDelegate.popChild(); | ||
| 628 | + } | ||
| 629 | + | ||
| 630 | + /** | ||
| 631 | + * Pop the last fragment transition from the manager's fragment | ||
| 632 | + * back stack. | ||
| 633 | + * <p> | ||
| 634 | + * 出栈到目标fragment | ||
| 635 | + * | ||
| 636 | + * @param targetFragmentClass 目标fragment | ||
| 637 | + * @param includeTargetFragment 是否包含该fragment | ||
| 638 | + */ | ||
| 639 | + public void popTo(Class<?> targetFragmentClass, boolean includeTargetFragment) { | ||
| 640 | + mDelegate.popTo(targetFragmentClass, includeTargetFragment); | ||
| 641 | + } | ||
| 642 | + | ||
| 643 | + /** | ||
| 644 | + * If you want to begin another FragmentTransaction immediately after popTo(), use this method. | ||
| 645 | + * 如果你想在出栈后, 立刻进行FragmentTransaction操作,请使用该方法 | ||
| 646 | + */ | ||
| 647 | + public void popTo(Class<?> targetFragmentClass, boolean includeTargetFragment, Runnable afterPopTransactionRunnable) { | ||
| 648 | + mDelegate.popTo(targetFragmentClass, includeTargetFragment, afterPopTransactionRunnable); | ||
| 649 | + } | ||
| 650 | + | ||
| 651 | + public void popTo(Class<?> targetFragmentClass, boolean includeTargetFragment, Runnable afterPopTransactionRunnable, int popAnim) { | ||
| 652 | + mDelegate.popTo(targetFragmentClass, includeTargetFragment, afterPopTransactionRunnable, popAnim); | ||
| 653 | + } | ||
| 654 | + | ||
| 655 | + public void popToChild(Class<?> targetFragmentClass, boolean includeTargetFragment) { | ||
| 656 | + mDelegate.popToChild(targetFragmentClass, includeTargetFragment); | ||
| 657 | + } | ||
| 658 | + | ||
| 659 | + public void popToChild(Class<?> targetFragmentClass, boolean includeTargetFragment, Runnable afterPopTransactionRunnable) { | ||
| 660 | + mDelegate.popToChild(targetFragmentClass, includeTargetFragment, afterPopTransactionRunnable); | ||
| 661 | + } | ||
| 662 | + | ||
| 663 | + public void popToChild(Class<?> targetFragmentClass, boolean includeTargetFragment, Runnable afterPopTransactionRunnable, int popAnim) { | ||
| 664 | + mDelegate.popToChild(targetFragmentClass, includeTargetFragment, afterPopTransactionRunnable, popAnim); | ||
| 665 | + } | ||
| 666 | + | ||
| 667 | + /** | ||
| 668 | + * 得到位于栈顶Fragment | ||
| 669 | + */ | ||
| 670 | + public ISupportFragment getTopFragment() { | ||
| 671 | + return SupportHelper.getTopFragment(getFragmentManager()); | ||
| 672 | + } | ||
| 673 | + | ||
| 674 | + public ISupportFragment getTopChildFragment() { | ||
| 675 | + return SupportHelper.getTopFragment(getChildFragmentManager()); | ||
| 676 | + } | ||
| 677 | + | ||
| 678 | + /** | ||
| 679 | + * @return 位于当前Fragment的前一个Fragment | ||
| 680 | + */ | ||
| 681 | + public ISupportFragment getPreFragment() { | ||
| 682 | + return SupportHelper.getPreFragment(this); | ||
| 683 | + } | ||
| 684 | + | ||
| 685 | + /** | ||
| 686 | + * 获取栈内的fragment对象 | ||
| 687 | + */ | ||
| 688 | + public <T extends ISupportFragment> T findFragment(Class<T> fragmentClass) { | ||
| 689 | + return SupportHelper.findFragment(getFragmentManager(), fragmentClass); | ||
| 690 | + } | ||
| 691 | + | ||
| 692 | + /** | ||
| 693 | + * 获取栈内的fragment对象 | ||
| 694 | + */ | ||
| 695 | + public <T extends ISupportFragment> T findChildFragment(Class<T> fragmentClass) { | ||
| 696 | + return SupportHelper.findFragment(getChildFragmentManager(), fragmentClass); | ||
| 697 | + } | ||
| 698 | + | ||
| 699 | + /*****************************侧滑返回************************************/ | ||
| 700 | + @Override | ||
| 701 | + public View attachToSwipeBack(View view) { | ||
| 702 | + return mSwipeDelegate.attachToSwipeBack(view); | ||
| 703 | + } | ||
| 704 | + | ||
| 705 | + public SwipeBackLayout getSwipeBackLayout() { | ||
| 706 | + return mSwipeDelegate.getSwipeBackLayout(); | ||
| 707 | + } | ||
| 708 | + | ||
| 709 | + /** | ||
| 710 | + * 是否可滑动 | ||
| 711 | + * | ||
| 712 | + * @param enable | ||
| 713 | + */ | ||
| 714 | + public void setSwipeBackEnable(boolean enable) { | ||
| 715 | + mSwipeDelegate.setSwipeBackEnable(enable); | ||
| 716 | + } | ||
| 717 | + | ||
| 718 | + @Override | ||
| 719 | + public void setEdgeLevel(SwipeBackLayout.EdgeLevel edgeLevel) { | ||
| 720 | + mSwipeDelegate.setEdgeLevel(edgeLevel); | ||
| 721 | + } | ||
| 722 | + | ||
| 723 | + @Override | ||
| 724 | + public void setEdgeLevel(int widthPixel) { | ||
| 725 | + mSwipeDelegate.setEdgeLevel(widthPixel); | ||
| 726 | + } | ||
| 727 | + | ||
| 728 | + /** | ||
| 729 | + * Set the offset of the parallax slip. | ||
| 730 | + */ | ||
| 731 | + public void setParallaxOffset(@FloatRange(from = 0.0f, to = 1.0f) float offset) { | ||
| 732 | + mSwipeDelegate.setParallaxOffset(offset); | ||
| 733 | + } | ||
| 241 | } | 734 | } |
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<V extends BaseView> extends MvpBasePresenter<V> { | @@ -17,4 +18,32 @@ public class BasePresenter<V extends BaseView> extends MvpBasePresenter<V> { | ||
| 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/me/yokeyword/fragmentation/ExtraTransaction.java
0 → 100644
| 1 | +package com.me.yokeyword.fragmentation; | ||
| 2 | + | ||
| 3 | +import android.os.Build; | ||
| 4 | +import android.view.View; | ||
| 5 | + | ||
| 6 | +import androidx.annotation.AnimRes; | ||
| 7 | +import androidx.annotation.AnimatorRes; | ||
| 8 | +import androidx.annotation.RequiresApi; | ||
| 9 | +import androidx.fragment.app.Fragment; | ||
| 10 | +import androidx.fragment.app.FragmentActivity; | ||
| 11 | +import androidx.fragment.app.FragmentManager; | ||
| 12 | + | ||
| 13 | +import com.me.yokeyword.fragmentation.helper.internal.TransactionRecord; | ||
| 14 | + | ||
| 15 | +import java.util.ArrayList; | ||
| 16 | + | ||
| 17 | + | ||
| 18 | +/** | ||
| 19 | + * Created by YoKey on 16/11/24. | ||
| 20 | + */ | ||
| 21 | +public abstract class ExtraTransaction { | ||
| 22 | + | ||
| 23 | + /** | ||
| 24 | + * @param tag Optional tag name for the fragment, to later retrieve the | ||
| 25 | + * fragment with {@link SupportHelper#findFragment(FragmentManager, String)} | ||
| 26 | + * , pop(String) | ||
| 27 | + * or FragmentManager.findFragmentByTag(String). | ||
| 28 | + */ | ||
| 29 | + public abstract ExtraTransaction setTag(String tag); | ||
| 30 | + | ||
| 31 | + /** | ||
| 32 | + * Set specific animation resources to run for the fragments that are | ||
| 33 | + * entering and exiting in this transaction. These animations will not be | ||
| 34 | + * played when popping the back stack. | ||
| 35 | + */ | ||
| 36 | + public abstract ExtraTransaction setCustomAnimations(@AnimatorRes @AnimRes int targetFragmentEnter, | ||
| 37 | + @AnimatorRes @AnimRes int currentFragmentPopExit); | ||
| 38 | + | ||
| 39 | + /** | ||
| 40 | + * Set specific animation resources to run for the fragments that are | ||
| 41 | + * entering and exiting in this transaction. The <code>currentFragmentPopEnter</code> | ||
| 42 | + * and <code>targetFragmentExit</code> animations will be played for targetFragmentEnter/currentFragmentPopExit | ||
| 43 | + * operations specifically when popping the back stack. | ||
| 44 | + */ | ||
| 45 | + public abstract ExtraTransaction setCustomAnimations(@AnimatorRes @AnimRes int targetFragmentEnter, | ||
| 46 | + @AnimatorRes @AnimRes int currentFragmentPopExit, | ||
| 47 | + @AnimatorRes @AnimRes int currentFragmentPopEnter, | ||
| 48 | + @AnimatorRes @AnimRes int targetFragmentExit); | ||
| 49 | + | ||
| 50 | + /** | ||
| 51 | + * Used with custom Transitions to map a View from a removed or hidden | ||
| 52 | + * Fragment to a View from a shown or added Fragment. | ||
| 53 | + * <var>sharedElement</var> must have a unique transitionName in the View hierarchy. | ||
| 54 | + * | ||
| 55 | + * @param sharedElement A View in a disappearing Fragment to match with a View in an | ||
| 56 | + * appearing Fragment. | ||
| 57 | + * @param sharedName The transitionName for a View in an appearing Fragment to match to the shared | ||
| 58 | + * element. | ||
| 59 | + * @see Fragment#setSharedElementReturnTransition(Object) | ||
| 60 | + * @see Fragment#setSharedElementEnterTransition(Object) | ||
| 61 | + */ | ||
| 62 | + @RequiresApi(Build.VERSION_CODES.LOLLIPOP_MR1) | ||
| 63 | + public abstract ExtraTransaction addSharedElement(View sharedElement, String sharedName); | ||
| 64 | + | ||
| 65 | + public abstract void loadRootFragment(int containerId, ISupportFragment toFragment); | ||
| 66 | + | ||
| 67 | + public abstract void loadRootFragment(int containerId, ISupportFragment toFragment, boolean addToBackStack, boolean allowAnim); | ||
| 68 | + | ||
| 69 | + public abstract void start(ISupportFragment toFragment); | ||
| 70 | + | ||
| 71 | + public abstract void startDontHideSelf(ISupportFragment toFragment); | ||
| 72 | + | ||
| 73 | + public abstract void startDontHideSelf(ISupportFragment toFragment, @ISupportFragment.LaunchMode int launchMode); | ||
| 74 | + | ||
| 75 | + public abstract void start(ISupportFragment toFragment, @ISupportFragment.LaunchMode int launchMode); | ||
| 76 | + | ||
| 77 | + public abstract void startForResult(ISupportFragment toFragment, int requestCode); | ||
| 78 | + | ||
| 79 | + public abstract void startForResultDontHideSelf(ISupportFragment toFragment, int requestCode); | ||
| 80 | + | ||
| 81 | + public abstract void startWithPop(ISupportFragment toFragment); | ||
| 82 | + | ||
| 83 | + public abstract void startWithPopTo(ISupportFragment toFragment, String targetFragmentTag, boolean includeTargetFragment); | ||
| 84 | + | ||
| 85 | + public abstract void replace(ISupportFragment toFragment); | ||
| 86 | + | ||
| 87 | + /** | ||
| 88 | + * 使用setTag()自定义Tag时,使用下面popTo()/popToChild()出栈 | ||
| 89 | + * | ||
| 90 | + * @param targetFragmentTag 通过setTag()设置的tag | ||
| 91 | + * @param includeTargetFragment 是否包含目标(Tag为targetFragmentTag)Fragment | ||
| 92 | + */ | ||
| 93 | + public abstract void popTo(String targetFragmentTag, boolean includeTargetFragment); | ||
| 94 | + | ||
| 95 | + public abstract void popTo(String targetFragmentTag, boolean includeTargetFragment, Runnable afterPopTransactionRunnable, int popAnim); | ||
| 96 | + | ||
| 97 | + public abstract void popToChild(String targetFragmentTag, boolean includeTargetFragment); | ||
| 98 | + | ||
| 99 | + public abstract void popToChild(String targetFragmentTag, boolean includeTargetFragment, Runnable afterPopTransactionRunnable, int popAnim); | ||
| 100 | + | ||
| 101 | + /** | ||
| 102 | + * Don't add this extraTransaction to the back stack. | ||
| 103 | + */ | ||
| 104 | + public abstract DontAddToBackStackTransaction dontAddToBackStack(); | ||
| 105 | + | ||
| 106 | + /** | ||
| 107 | + * 使用dontAddToBackStack() 加载Fragment时, 使用remove()移除Fragment | ||
| 108 | + */ | ||
| 109 | + public abstract void remove(ISupportFragment fragment, boolean showPreFragment); | ||
| 110 | + | ||
| 111 | + public interface DontAddToBackStackTransaction { | ||
| 112 | + /** | ||
| 113 | + * add() + hide(preFragment) | ||
| 114 | + */ | ||
| 115 | + void start(ISupportFragment toFragment); | ||
| 116 | + | ||
| 117 | + /** | ||
| 118 | + * Only add() | ||
| 119 | + */ | ||
| 120 | + void add(ISupportFragment toFragment); | ||
| 121 | + | ||
| 122 | + /** | ||
| 123 | + * replace() | ||
| 124 | + */ | ||
| 125 | + void replace(ISupportFragment toFragment); | ||
| 126 | + } | ||
| 127 | + | ||
| 128 | + /** | ||
| 129 | + * Impl | ||
| 130 | + */ | ||
| 131 | + final static class ExtraTransactionImpl<T extends ISupportFragment> extends ExtraTransaction implements DontAddToBackStackTransaction { | ||
| 132 | + private FragmentActivity mActivity; | ||
| 133 | + private T mSupportF; | ||
| 134 | + private Fragment mFragment; | ||
| 135 | + private TransactionDelegate mTransactionDelegate; | ||
| 136 | + private boolean mFromActivity; | ||
| 137 | + private TransactionRecord mRecord; | ||
| 138 | + | ||
| 139 | + ExtraTransactionImpl(FragmentActivity activity, T supportF, TransactionDelegate transactionDelegate, boolean fromActivity) { | ||
| 140 | + this.mActivity = activity; | ||
| 141 | + this.mSupportF = supportF; | ||
| 142 | + this.mFragment = (Fragment) supportF; | ||
| 143 | + this.mTransactionDelegate = transactionDelegate; | ||
| 144 | + this.mFromActivity = fromActivity; | ||
| 145 | + mRecord = new TransactionRecord(); | ||
| 146 | + } | ||
| 147 | + | ||
| 148 | + @Override | ||
| 149 | + public ExtraTransaction setTag(String tag) { | ||
| 150 | + mRecord.tag = tag; | ||
| 151 | + return this; | ||
| 152 | + } | ||
| 153 | + | ||
| 154 | + @Override | ||
| 155 | + public ExtraTransaction setCustomAnimations(@AnimRes int targetFragmentEnter | ||
| 156 | + , @AnimRes int currentFragmentPopExit) { | ||
| 157 | + mRecord.targetFragmentEnter = targetFragmentEnter; | ||
| 158 | + mRecord.currentFragmentPopExit = currentFragmentPopExit; | ||
| 159 | + mRecord.currentFragmentPopEnter = 0; | ||
| 160 | + mRecord.targetFragmentExit = 0; | ||
| 161 | + return this; | ||
| 162 | + } | ||
| 163 | + | ||
| 164 | + @Override | ||
| 165 | + public ExtraTransaction setCustomAnimations(@AnimRes int targetFragmentEnter, | ||
| 166 | + @AnimRes int currentFragmentPopExit, | ||
| 167 | + @AnimRes int currentFragmentPopEnter, | ||
| 168 | + @AnimRes int targetFragmentExit) { | ||
| 169 | + mRecord.targetFragmentEnter = targetFragmentEnter; | ||
| 170 | + mRecord.currentFragmentPopExit = currentFragmentPopExit; | ||
| 171 | + mRecord.currentFragmentPopEnter = currentFragmentPopEnter; | ||
| 172 | + mRecord.targetFragmentExit = targetFragmentExit; | ||
| 173 | + return this; | ||
| 174 | + } | ||
| 175 | + | ||
| 176 | + @Override | ||
| 177 | + public ExtraTransaction addSharedElement(View sharedElement, String sharedName) { | ||
| 178 | + if (mRecord.sharedElementList == null) { | ||
| 179 | + mRecord.sharedElementList = new ArrayList<>(); | ||
| 180 | + } | ||
| 181 | + mRecord.sharedElementList.add(new TransactionRecord.SharedElement(sharedElement, sharedName)); | ||
| 182 | + return this; | ||
| 183 | + } | ||
| 184 | + | ||
| 185 | + @Override | ||
| 186 | + public void loadRootFragment(int containerId, ISupportFragment toFragment) { | ||
| 187 | + loadRootFragment(containerId, toFragment, true, false); | ||
| 188 | + } | ||
| 189 | + | ||
| 190 | + @Override | ||
| 191 | + public void loadRootFragment(int containerId, ISupportFragment toFragment, boolean addToBackStack, boolean allowAnim) { | ||
| 192 | + toFragment.getSupportDelegate().mTransactionRecord = mRecord; | ||
| 193 | + mTransactionDelegate.loadRootTransaction(getFragmentManager(), containerId, toFragment, addToBackStack, allowAnim); | ||
| 194 | + } | ||
| 195 | + | ||
| 196 | + @Override | ||
| 197 | + public DontAddToBackStackTransaction dontAddToBackStack() { | ||
| 198 | + mRecord.dontAddToBackStack = true; | ||
| 199 | + return this; | ||
| 200 | + } | ||
| 201 | + | ||
| 202 | + @Override | ||
| 203 | + public void remove(ISupportFragment fragment, boolean showPreFragment) { | ||
| 204 | + mTransactionDelegate.remove(getFragmentManager(), (Fragment) fragment, showPreFragment); | ||
| 205 | + } | ||
| 206 | + | ||
| 207 | + @Override | ||
| 208 | + public void popTo(String targetFragmentTag, boolean includeTargetFragment) { | ||
| 209 | + popTo(targetFragmentTag, includeTargetFragment, null, TransactionDelegate.DEFAULT_POPTO_ANIM); | ||
| 210 | + } | ||
| 211 | + | ||
| 212 | + @Override | ||
| 213 | + public void popTo(String targetFragmentTag, boolean includeTargetFragment, Runnable afterPopTransactionRunnable, int popAnim) { | ||
| 214 | + mTransactionDelegate.popTo(targetFragmentTag, includeTargetFragment, afterPopTransactionRunnable, getFragmentManager(), popAnim); | ||
| 215 | + } | ||
| 216 | + | ||
| 217 | + @Override | ||
| 218 | + public void popToChild(String targetFragmentTag, boolean includeTargetFragment) { | ||
| 219 | + popToChild(targetFragmentTag, includeTargetFragment, null, TransactionDelegate.DEFAULT_POPTO_ANIM); | ||
| 220 | + } | ||
| 221 | + | ||
| 222 | + @Override | ||
| 223 | + public void popToChild(String targetFragmentTag, boolean includeTargetFragment, Runnable afterPopTransactionRunnable, int popAnim) { | ||
| 224 | + if (mFromActivity) { | ||
| 225 | + popTo(targetFragmentTag, includeTargetFragment, afterPopTransactionRunnable, popAnim); | ||
| 226 | + } else { | ||
| 227 | + mTransactionDelegate.popTo(targetFragmentTag, includeTargetFragment, afterPopTransactionRunnable, mFragment.getChildFragmentManager(), popAnim); | ||
| 228 | + } | ||
| 229 | + } | ||
| 230 | + | ||
| 231 | + @Override | ||
| 232 | + public void add(ISupportFragment toFragment) { | ||
| 233 | + toFragment.getSupportDelegate().mTransactionRecord = mRecord; | ||
| 234 | + mTransactionDelegate.dispatchStartTransaction(getFragmentManager(), mSupportF, toFragment, 0, ISupportFragment.STANDARD, TransactionDelegate.TYPE_ADD_WITHOUT_HIDE); | ||
| 235 | + } | ||
| 236 | + | ||
| 237 | + @Override | ||
| 238 | + public void start(ISupportFragment toFragment) { | ||
| 239 | + start(toFragment, ISupportFragment.STANDARD); | ||
| 240 | + } | ||
| 241 | + | ||
| 242 | + @Override | ||
| 243 | + public void startDontHideSelf(ISupportFragment toFragment) { | ||
| 244 | + toFragment.getSupportDelegate().mTransactionRecord = mRecord; | ||
| 245 | + mTransactionDelegate.dispatchStartTransaction(getFragmentManager(), mSupportF, toFragment, 0, ISupportFragment.STANDARD, TransactionDelegate.TYPE_ADD_WITHOUT_HIDE); | ||
| 246 | + } | ||
| 247 | + | ||
| 248 | + @Override | ||
| 249 | + public void startDontHideSelf(ISupportFragment toFragment, @ISupportFragment.LaunchMode int launchMode) { | ||
| 250 | + toFragment.getSupportDelegate().mTransactionRecord = mRecord; | ||
| 251 | + mTransactionDelegate.dispatchStartTransaction(getFragmentManager(), mSupportF, toFragment, 0, launchMode, TransactionDelegate.TYPE_ADD_WITHOUT_HIDE); | ||
| 252 | + } | ||
| 253 | + | ||
| 254 | + @Override | ||
| 255 | + public void start(ISupportFragment toFragment, @ISupportFragment.LaunchMode int launchMode) { | ||
| 256 | + toFragment.getSupportDelegate().mTransactionRecord = mRecord; | ||
| 257 | + mTransactionDelegate.dispatchStartTransaction(getFragmentManager(), mSupportF, toFragment, 0, launchMode, TransactionDelegate.TYPE_ADD); | ||
| 258 | + } | ||
| 259 | + | ||
| 260 | + @Override | ||
| 261 | + public void startForResult(ISupportFragment toFragment, int requestCode) { | ||
| 262 | + toFragment.getSupportDelegate().mTransactionRecord = mRecord; | ||
| 263 | + mTransactionDelegate.dispatchStartTransaction(getFragmentManager(), mSupportF, toFragment, requestCode, ISupportFragment.STANDARD, TransactionDelegate.TYPE_ADD_RESULT); | ||
| 264 | + } | ||
| 265 | + | ||
| 266 | + @Override | ||
| 267 | + public void startForResultDontHideSelf(ISupportFragment toFragment, int requestCode) { | ||
| 268 | + toFragment.getSupportDelegate().mTransactionRecord = mRecord; | ||
| 269 | + mTransactionDelegate.dispatchStartTransaction(getFragmentManager(), mSupportF, toFragment, requestCode, ISupportFragment.STANDARD, TransactionDelegate.TYPE_ADD_RESULT_WITHOUT_HIDE); | ||
| 270 | + } | ||
| 271 | + | ||
| 272 | + @Override | ||
| 273 | + public void startWithPop(ISupportFragment toFragment) { | ||
| 274 | + toFragment.getSupportDelegate().mTransactionRecord = mRecord; | ||
| 275 | + mTransactionDelegate.startWithPop(getFragmentManager(), mSupportF, toFragment); | ||
| 276 | + } | ||
| 277 | + | ||
| 278 | + @Override | ||
| 279 | + public void startWithPopTo(ISupportFragment toFragment, String targetFragmentTag, boolean includeTargetFragment) { | ||
| 280 | + toFragment.getSupportDelegate().mTransactionRecord = mRecord; | ||
| 281 | + mTransactionDelegate.startWithPopTo(getFragmentManager(), mSupportF, toFragment, targetFragmentTag, includeTargetFragment); | ||
| 282 | + } | ||
| 283 | + | ||
| 284 | + @Override | ||
| 285 | + public void replace(ISupportFragment toFragment) { | ||
| 286 | + toFragment.getSupportDelegate().mTransactionRecord = mRecord; | ||
| 287 | + mTransactionDelegate.dispatchStartTransaction(getFragmentManager(), mSupportF, toFragment, 0, ISupportFragment.STANDARD, TransactionDelegate.TYPE_REPLACE); | ||
| 288 | + } | ||
| 289 | + | ||
| 290 | + private FragmentManager getFragmentManager() { | ||
| 291 | + if (mFragment == null) { | ||
| 292 | + return mActivity.getSupportFragmentManager(); | ||
| 293 | + } | ||
| 294 | + return mFragment.getFragmentManager(); | ||
| 295 | + } | ||
| 296 | + } | ||
| 297 | +} |
core/base/src/main/java/com/me/yokeyword/fragmentation/Fragmentation.java
0 → 100644
| 1 | +package com.me.yokeyword.fragmentation; | ||
| 2 | + | ||
| 3 | +import androidx.annotation.IntDef; | ||
| 4 | + | ||
| 5 | +import com.me.yokeyword.fragmentation.helper.ExceptionHandler; | ||
| 6 | + | ||
| 7 | +import java.lang.annotation.Retention; | ||
| 8 | +import java.lang.annotation.RetentionPolicy; | ||
| 9 | + | ||
| 10 | + | ||
| 11 | +/** | ||
| 12 | + * Created by YoKey on 17/2/5. | ||
| 13 | + */ | ||
| 14 | +public class Fragmentation { | ||
| 15 | + /** | ||
| 16 | + * Dont display stack view. | ||
| 17 | + */ | ||
| 18 | + public static final int NONE = 0; | ||
| 19 | + /** | ||
| 20 | + * Shake it to display stack view. | ||
| 21 | + */ | ||
| 22 | + public static final int SHAKE = 1; | ||
| 23 | + /** | ||
| 24 | + * As a bubble display stack view. | ||
| 25 | + */ | ||
| 26 | + public static final int BUBBLE = 2; | ||
| 27 | + | ||
| 28 | + static volatile Fragmentation INSTANCE; | ||
| 29 | + | ||
| 30 | + private boolean debug; | ||
| 31 | + private int mode = BUBBLE; | ||
| 32 | + private ExceptionHandler handler; | ||
| 33 | + | ||
| 34 | + @IntDef({NONE, SHAKE, BUBBLE}) | ||
| 35 | + @Retention(RetentionPolicy.SOURCE) | ||
| 36 | + @interface StackViewMode { | ||
| 37 | + } | ||
| 38 | + | ||
| 39 | + public static Fragmentation getDefault() { | ||
| 40 | + if (INSTANCE == null) { | ||
| 41 | + synchronized (Fragmentation.class) { | ||
| 42 | + if (INSTANCE == null) { | ||
| 43 | + INSTANCE = new Fragmentation(new FragmentationBuilder()); | ||
| 44 | + } | ||
| 45 | + } | ||
| 46 | + } | ||
| 47 | + return INSTANCE; | ||
| 48 | + } | ||
| 49 | + | ||
| 50 | + Fragmentation(FragmentationBuilder builder) { | ||
| 51 | + debug = builder.debug; | ||
| 52 | + if (debug) { | ||
| 53 | + mode = builder.mode; | ||
| 54 | + } else { | ||
| 55 | + mode = NONE; | ||
| 56 | + } | ||
| 57 | + handler = builder.handler; | ||
| 58 | + } | ||
| 59 | + | ||
| 60 | + public boolean isDebug() { | ||
| 61 | + return debug; | ||
| 62 | + } | ||
| 63 | + | ||
| 64 | + public void setDebug(boolean debug) { | ||
| 65 | + this.debug = debug; | ||
| 66 | + } | ||
| 67 | + | ||
| 68 | + public ExceptionHandler getHandler() { | ||
| 69 | + return handler; | ||
| 70 | + } | ||
| 71 | + | ||
| 72 | + public void setHandler(ExceptionHandler handler) { | ||
| 73 | + this.handler = handler; | ||
| 74 | + } | ||
| 75 | + | ||
| 76 | + public int getMode() { | ||
| 77 | + return mode; | ||
| 78 | + } | ||
| 79 | + | ||
| 80 | + public void setMode(@StackViewMode int mode) { | ||
| 81 | + this.mode = mode; | ||
| 82 | + } | ||
| 83 | + | ||
| 84 | + public static FragmentationBuilder builder() { | ||
| 85 | + return new FragmentationBuilder(); | ||
| 86 | + } | ||
| 87 | + | ||
| 88 | + public static class FragmentationBuilder { | ||
| 89 | + private boolean debug; | ||
| 90 | + private int mode; | ||
| 91 | + private ExceptionHandler handler; | ||
| 92 | + | ||
| 93 | + /** | ||
| 94 | + * @param debug Suppressed Exception("Can not perform this action after onSaveInstanceState!") when debug=false | ||
| 95 | + */ | ||
| 96 | + public FragmentationBuilder debug(boolean debug) { | ||
| 97 | + this.debug = debug; | ||
| 98 | + return this; | ||
| 99 | + } | ||
| 100 | + | ||
| 101 | + /** | ||
| 102 | + * Sets the mode to display the stack view | ||
| 103 | + * <p> | ||
| 104 | + * None if debug(false). | ||
| 105 | + * <p> | ||
| 106 | + * Default:NONE | ||
| 107 | + */ | ||
| 108 | + public FragmentationBuilder stackViewMode(@StackViewMode int mode) { | ||
| 109 | + this.mode = mode; | ||
| 110 | + return this; | ||
| 111 | + } | ||
| 112 | + | ||
| 113 | + /** | ||
| 114 | + * @param handler Handled Exception("Can not perform this action after onSaveInstanceState!") when debug=false. | ||
| 115 | + */ | ||
| 116 | + public FragmentationBuilder handleException(ExceptionHandler handler) { | ||
| 117 | + this.handler = handler; | ||
| 118 | + return this; | ||
| 119 | + } | ||
| 120 | + | ||
| 121 | + public Fragmentation install() { | ||
| 122 | + Fragmentation.INSTANCE = new Fragmentation(this); | ||
| 123 | + return Fragmentation.INSTANCE; | ||
| 124 | + } | ||
| 125 | + } | ||
| 126 | +} |
core/base/src/main/java/com/me/yokeyword/fragmentation/ISupportActivity.java
0 → 100644
| 1 | +package com.me.yokeyword.fragmentation; | ||
| 2 | + | ||
| 3 | +import android.view.MotionEvent; | ||
| 4 | + | ||
| 5 | +import com.me.yokeyword.fragmentation.anim.FragmentAnimator; | ||
| 6 | + | ||
| 7 | + | ||
| 8 | +/** | ||
| 9 | + * Created by YoKey on 17/6/13. | ||
| 10 | + */ | ||
| 11 | + | ||
| 12 | +public interface ISupportActivity { | ||
| 13 | + SupportActivityDelegate getSupportDelegate(); | ||
| 14 | + | ||
| 15 | + ExtraTransaction extraTransaction(); | ||
| 16 | + | ||
| 17 | + FragmentAnimator getFragmentAnimator(); | ||
| 18 | + | ||
| 19 | + void setFragmentAnimator(FragmentAnimator fragmentAnimator); | ||
| 20 | + | ||
| 21 | + FragmentAnimator onCreateFragmentAnimator(); | ||
| 22 | + | ||
| 23 | + void post(Runnable runnable); | ||
| 24 | + | ||
| 25 | + void onBackPressed(); | ||
| 26 | + | ||
| 27 | + void onBackPressedSupport(); | ||
| 28 | + | ||
| 29 | + boolean dispatchTouchEvent(MotionEvent ev); | ||
| 30 | +} |
core/base/src/main/java/com/me/yokeyword/fragmentation/ISupportFragment.java
0 → 100644
| 1 | +package com.me.yokeyword.fragmentation; | ||
| 2 | + | ||
| 3 | +import android.os.Bundle; | ||
| 4 | + | ||
| 5 | +import androidx.annotation.IntDef; | ||
| 6 | +import androidx.annotation.Nullable; | ||
| 7 | + | ||
| 8 | +import com.me.yokeyword.fragmentation.anim.FragmentAnimator; | ||
| 9 | + | ||
| 10 | +import java.lang.annotation.Retention; | ||
| 11 | +import java.lang.annotation.RetentionPolicy; | ||
| 12 | + | ||
| 13 | + | ||
| 14 | +/** | ||
| 15 | + * Created by YoKey on 17/6/23. | ||
| 16 | + */ | ||
| 17 | + | ||
| 18 | +public interface ISupportFragment { | ||
| 19 | + // LaunchMode | ||
| 20 | + int STANDARD = 0; | ||
| 21 | + int SINGLETOP = 1; | ||
| 22 | + int SINGLETASK = 2; | ||
| 23 | + | ||
| 24 | + // ResultCode | ||
| 25 | + int RESULT_CANCELED = 0; | ||
| 26 | + int RESULT_OK = -1; | ||
| 27 | + | ||
| 28 | + @IntDef({STANDARD, SINGLETOP, SINGLETASK}) | ||
| 29 | + @Retention(RetentionPolicy.SOURCE) | ||
| 30 | + public @interface LaunchMode { | ||
| 31 | + } | ||
| 32 | + | ||
| 33 | + SupportFragmentDelegate getSupportDelegate(); | ||
| 34 | + | ||
| 35 | + ExtraTransaction extraTransaction(); | ||
| 36 | + | ||
| 37 | + void enqueueAction(Runnable runnable); | ||
| 38 | + | ||
| 39 | + void post(Runnable runnable); | ||
| 40 | + | ||
| 41 | + void onEnterAnimationEnd(@Nullable Bundle savedInstanceState); | ||
| 42 | + | ||
| 43 | + void onLazyInitView(@Nullable Bundle savedInstanceState); | ||
| 44 | + | ||
| 45 | + void onSupportVisible(); | ||
| 46 | + | ||
| 47 | + void onSupportInvisible(); | ||
| 48 | + | ||
| 49 | + boolean isSupportVisible(); | ||
| 50 | + | ||
| 51 | + FragmentAnimator onCreateFragmentAnimator(); | ||
| 52 | + | ||
| 53 | + FragmentAnimator getFragmentAnimator(); | ||
| 54 | + | ||
| 55 | + void setFragmentAnimator(FragmentAnimator fragmentAnimator); | ||
| 56 | + | ||
| 57 | + void setFragmentResult(int resultCode, Bundle bundle); | ||
| 58 | + | ||
| 59 | + void onFragmentResult(int requestCode, int resultCode, Bundle data); | ||
| 60 | + | ||
| 61 | + void onNewBundle(Bundle args); | ||
| 62 | + | ||
| 63 | + void putNewBundle(Bundle newBundle); | ||
| 64 | + | ||
| 65 | + boolean onBackPressedSupport(); | ||
| 66 | +} |
core/base/src/main/java/com/me/yokeyword/fragmentation/SupportActivity.java
0 → 100644
| 1 | +package com.me.yokeyword.fragmentation; | ||
| 2 | + | ||
| 3 | +import android.os.Bundle; | ||
| 4 | +import android.view.MotionEvent; | ||
| 5 | + | ||
| 6 | +import androidx.annotation.DrawableRes; | ||
| 7 | +import androidx.annotation.NonNull; | ||
| 8 | +import androidx.annotation.Nullable; | ||
| 9 | +import androidx.appcompat.app.AppCompatActivity; | ||
| 10 | + | ||
| 11 | +import com.me.yokeyword.fragmentation.anim.FragmentAnimator; | ||
| 12 | + | ||
| 13 | + | ||
| 14 | +/** | ||
| 15 | + * Base class for activities that use the support-based | ||
| 16 | + * {@link ISupportActivity} and | ||
| 17 | + * {@link AppCompatActivity} APIs. | ||
| 18 | + * <p> | ||
| 19 | + * Created by YoKey on 17/6/20. | ||
| 20 | + */ | ||
| 21 | +public class SupportActivity extends AppCompatActivity implements ISupportActivity { | ||
| 22 | + final SupportActivityDelegate mDelegate = new SupportActivityDelegate(this); | ||
| 23 | + | ||
| 24 | + @Override | ||
| 25 | + public SupportActivityDelegate getSupportDelegate() { | ||
| 26 | + return mDelegate; | ||
| 27 | + } | ||
| 28 | + | ||
| 29 | + /** | ||
| 30 | + * Perform some extra transactions. | ||
| 31 | + * 额外的事务:自定义Tag,添加SharedElement动画,操作非回退栈Fragment | ||
| 32 | + */ | ||
| 33 | + @Override | ||
| 34 | + public ExtraTransaction extraTransaction() { | ||
| 35 | + return mDelegate.extraTransaction(); | ||
| 36 | + } | ||
| 37 | + | ||
| 38 | + @Override | ||
| 39 | + protected void onCreate(@Nullable Bundle savedInstanceState) { | ||
| 40 | + super.onCreate(savedInstanceState); | ||
| 41 | + mDelegate.onCreate(savedInstanceState); | ||
| 42 | + } | ||
| 43 | + | ||
| 44 | + @Override | ||
| 45 | + protected void onPostCreate(@Nullable Bundle savedInstanceState) { | ||
| 46 | + super.onPostCreate(savedInstanceState); | ||
| 47 | + mDelegate.onPostCreate(savedInstanceState); | ||
| 48 | + } | ||
| 49 | + | ||
| 50 | + @Override | ||
| 51 | + protected void onDestroy() { | ||
| 52 | + mDelegate.onDestroy(); | ||
| 53 | + super.onDestroy(); | ||
| 54 | + } | ||
| 55 | + | ||
| 56 | + /** | ||
| 57 | + * Note: return mDelegate.dispatchTouchEvent(ev) || super.dispatchTouchEvent(ev); | ||
| 58 | + */ | ||
| 59 | + @Override | ||
| 60 | + public boolean dispatchTouchEvent(MotionEvent ev) { | ||
| 61 | + return mDelegate.dispatchTouchEvent(ev) || super.dispatchTouchEvent(ev); | ||
| 62 | + } | ||
| 63 | + | ||
| 64 | + /** | ||
| 65 | + * 不建议复写该方法,请使用 {@link #onBackPressedSupport} 代替 | ||
| 66 | + */ | ||
| 67 | + @Override | ||
| 68 | + final public void onBackPressed() { | ||
| 69 | + mDelegate.onBackPressed(); | ||
| 70 | + } | ||
| 71 | + | ||
| 72 | + /** | ||
| 73 | + * 该方法回调时机为,Activity回退栈内Fragment的数量 小于等于1 时,默认finish Activity | ||
| 74 | + * 请尽量复写该方法,避免复写onBackPress(),以保证SupportFragment内的onBackPressedSupport()回退事件正常执行 | ||
| 75 | + */ | ||
| 76 | + @Override | ||
| 77 | + public void onBackPressedSupport() { | ||
| 78 | + mDelegate.onBackPressedSupport(); | ||
| 79 | + } | ||
| 80 | + | ||
| 81 | + /** | ||
| 82 | + * 获取设置的全局动画 copy | ||
| 83 | + * | ||
| 84 | + * @return FragmentAnimator | ||
| 85 | + */ | ||
| 86 | + @Override | ||
| 87 | + public FragmentAnimator getFragmentAnimator() { | ||
| 88 | + return mDelegate.getFragmentAnimator(); | ||
| 89 | + } | ||
| 90 | + | ||
| 91 | + /** | ||
| 92 | + * Set all fragments animation. | ||
| 93 | + * 设置Fragment内的全局动画 | ||
| 94 | + */ | ||
| 95 | + @Override | ||
| 96 | + public void setFragmentAnimator(FragmentAnimator fragmentAnimator) { | ||
| 97 | + mDelegate.setFragmentAnimator(fragmentAnimator); | ||
| 98 | + } | ||
| 99 | + | ||
| 100 | + /** | ||
| 101 | + * Set all fragments animation. | ||
| 102 | + * 构建Fragment转场动画 | ||
| 103 | + * <p/> | ||
| 104 | + * 如果是在Activity内实现,则构建的是Activity内所有Fragment的转场动画, | ||
| 105 | + * 如果是在Fragment内实现,则构建的是该Fragment的转场动画,此时优先级 > Activity的onCreateFragmentAnimator() | ||
| 106 | + * | ||
| 107 | + * @return FragmentAnimator对象 | ||
| 108 | + */ | ||
| 109 | + @Override | ||
| 110 | + public FragmentAnimator onCreateFragmentAnimator() { | ||
| 111 | + return mDelegate.onCreateFragmentAnimator(); | ||
| 112 | + } | ||
| 113 | + | ||
| 114 | + @Override | ||
| 115 | + public void post(Runnable runnable) { | ||
| 116 | + mDelegate.post(runnable); | ||
| 117 | + } | ||
| 118 | + | ||
| 119 | + /****************************************以下为可选方法(Optional methods)******************************************************/ | ||
| 120 | + | ||
| 121 | + /** | ||
| 122 | + * 加载根Fragment, 即Activity内的第一个Fragment 或 Fragment内的第一个子Fragment | ||
| 123 | + * | ||
| 124 | + * @param containerId 容器id | ||
| 125 | + * @param toFragment 目标Fragment | ||
| 126 | + */ | ||
| 127 | + public void loadRootFragment(int containerId, @NonNull ISupportFragment toFragment) { | ||
| 128 | + mDelegate.loadRootFragment(containerId, toFragment); | ||
| 129 | + } | ||
| 130 | + | ||
| 131 | + public void loadRootFragment(int containerId, ISupportFragment toFragment, boolean addToBackStack, boolean allowAnimation) { | ||
| 132 | + mDelegate.loadRootFragment(containerId, toFragment, addToBackStack, allowAnimation); | ||
| 133 | + } | ||
| 134 | + | ||
| 135 | + /** | ||
| 136 | + * 加载多个同级根Fragment,类似Wechat, QQ主页的场景 | ||
| 137 | + */ | ||
| 138 | + public void loadMultipleRootFragment(int containerId, int showPosition, ISupportFragment... toFragments) { | ||
| 139 | + mDelegate.loadMultipleRootFragment(containerId, showPosition, toFragments); | ||
| 140 | + } | ||
| 141 | + | ||
| 142 | + /** | ||
| 143 | + * show一个Fragment,hide其他同栈所有Fragment | ||
| 144 | + * 使用该方法时,要确保同级栈内无多余的Fragment,(只有通过loadMultipleRootFragment()载入的Fragment) | ||
| 145 | + * <p> | ||
| 146 | + * 建议使用更明确的{@link #showHideFragment(ISupportFragment, ISupportFragment)} | ||
| 147 | + * | ||
| 148 | + * @param showFragment 需要show的Fragment | ||
| 149 | + */ | ||
| 150 | + public void showHideFragment(ISupportFragment showFragment) { | ||
| 151 | + mDelegate.showHideFragment(showFragment); | ||
| 152 | + } | ||
| 153 | + | ||
| 154 | + /** | ||
| 155 | + * show一个Fragment,hide一个Fragment ; 主要用于类似微信主页那种 切换tab的情况 | ||
| 156 | + */ | ||
| 157 | + public void showHideFragment(ISupportFragment showFragment, ISupportFragment hideFragment) { | ||
| 158 | + mDelegate.showHideFragment(showFragment, hideFragment); | ||
| 159 | + } | ||
| 160 | + | ||
| 161 | + /** | ||
| 162 | + * It is recommended to use {@link SupportFragment#start(ISupportFragment)}. | ||
| 163 | + */ | ||
| 164 | + public void start(ISupportFragment toFragment) { | ||
| 165 | + mDelegate.start(toFragment); | ||
| 166 | + } | ||
| 167 | + | ||
| 168 | + /** | ||
| 169 | + * It is recommended to use {@link SupportFragment#start(ISupportFragment, int)}. | ||
| 170 | + * | ||
| 171 | + * @param launchMode Similar to Activity's LaunchMode. | ||
| 172 | + */ | ||
| 173 | + public void start(ISupportFragment toFragment, @ISupportFragment.LaunchMode int launchMode) { | ||
| 174 | + mDelegate.start(toFragment, launchMode); | ||
| 175 | + } | ||
| 176 | + | ||
| 177 | + /** | ||
| 178 | + * It is recommended to use {@link SupportFragment#startForResult(ISupportFragment, int)}. | ||
| 179 | + * Launch an fragment for which you would like a result when it poped. | ||
| 180 | + */ | ||
| 181 | + public void startForResult(ISupportFragment toFragment, int requestCode) { | ||
| 182 | + mDelegate.startForResult(toFragment, requestCode); | ||
| 183 | + } | ||
| 184 | + | ||
| 185 | + /** | ||
| 186 | + * It is recommended to use {@link SupportFragment#startWithPop(ISupportFragment)}. | ||
| 187 | + * Start the target Fragment and pop itself | ||
| 188 | + */ | ||
| 189 | + public void startWithPop(ISupportFragment toFragment) { | ||
| 190 | + mDelegate.startWithPop(toFragment); | ||
| 191 | + } | ||
| 192 | + | ||
| 193 | + /** | ||
| 194 | + * It is recommended to use {@link SupportFragment#startWithPopTo(ISupportFragment, Class, boolean)}. | ||
| 195 | + * | ||
| 196 | + * @see #popTo(Class, boolean) | ||
| 197 | + * + | ||
| 198 | + * @see #start(ISupportFragment) | ||
| 199 | + */ | ||
| 200 | + public void startWithPopTo(ISupportFragment toFragment, Class<?> targetFragmentClass, boolean includeTargetFragment) { | ||
| 201 | + mDelegate.startWithPopTo(toFragment, targetFragmentClass, includeTargetFragment); | ||
| 202 | + } | ||
| 203 | + | ||
| 204 | + /** | ||
| 205 | + * It is recommended to use {@link SupportFragment#replaceFragment(ISupportFragment, boolean)}. | ||
| 206 | + */ | ||
| 207 | + public void replaceFragment(ISupportFragment toFragment, boolean addToBackStack) { | ||
| 208 | + mDelegate.replaceFragment(toFragment, addToBackStack); | ||
| 209 | + } | ||
| 210 | + | ||
| 211 | + /** | ||
| 212 | + * Pop the fragment. | ||
| 213 | + */ | ||
| 214 | + public void pop() { | ||
| 215 | + mDelegate.pop(); | ||
| 216 | + } | ||
| 217 | + | ||
| 218 | + /** | ||
| 219 | + * Pop the last fragment transition from the manager's fragment | ||
| 220 | + * back stack. | ||
| 221 | + * <p> | ||
| 222 | + * 出栈到目标fragment | ||
| 223 | + * | ||
| 224 | + * @param targetFragmentClass 目标fragment | ||
| 225 | + * @param includeTargetFragment 是否包含该fragment | ||
| 226 | + */ | ||
| 227 | + public void popTo(Class<?> targetFragmentClass, boolean includeTargetFragment) { | ||
| 228 | + mDelegate.popTo(targetFragmentClass, includeTargetFragment); | ||
| 229 | + } | ||
| 230 | + | ||
| 231 | + /** | ||
| 232 | + * If you want to begin another FragmentTransaction immediately after popTo(), use this method. | ||
| 233 | + * 如果你想在出栈后, 立刻进行FragmentTransaction操作,请使用该方法 | ||
| 234 | + */ | ||
| 235 | + public void popTo(Class<?> targetFragmentClass, boolean includeTargetFragment, Runnable afterPopTransactionRunnable) { | ||
| 236 | + mDelegate.popTo(targetFragmentClass, includeTargetFragment, afterPopTransactionRunnable); | ||
| 237 | + } | ||
| 238 | + | ||
| 239 | + public void popTo(Class<?> targetFragmentClass, boolean includeTargetFragment, Runnable afterPopTransactionRunnable, int popAnim) { | ||
| 240 | + mDelegate.popTo(targetFragmentClass, includeTargetFragment, afterPopTransactionRunnable, popAnim); | ||
| 241 | + } | ||
| 242 | + | ||
| 243 | + /** | ||
| 244 | + * 当Fragment根布局 没有 设定background属性时, | ||
| 245 | + * Fragmentation默认使用Theme的android:windowbackground作为Fragment的背景, | ||
| 246 | + * 可以通过该方法改变其内所有Fragment的默认背景。 | ||
| 247 | + */ | ||
| 248 | + public void setDefaultFragmentBackground(@DrawableRes int backgroundRes) { | ||
| 249 | + mDelegate.setDefaultFragmentBackground(backgroundRes); | ||
| 250 | + } | ||
| 251 | + | ||
| 252 | + /** | ||
| 253 | + * 得到位于栈顶Fragment | ||
| 254 | + */ | ||
| 255 | + public ISupportFragment getTopFragment() { | ||
| 256 | + return SupportHelper.getTopFragment(getSupportFragmentManager()); | ||
| 257 | + } | ||
| 258 | + | ||
| 259 | + /** | ||
| 260 | + * 获取栈内的fragment对象 | ||
| 261 | + */ | ||
| 262 | + public <T extends ISupportFragment> T findFragment(Class<T> fragmentClass) { | ||
| 263 | + return SupportHelper.findFragment(getSupportFragmentManager(), fragmentClass); | ||
| 264 | + } | ||
| 265 | +} |
core/base/src/main/java/com/me/yokeyword/fragmentation/SupportActivityDelegate.java
0 → 100644
| 1 | +package com.me.yokeyword.fragmentation; | ||
| 2 | + | ||
| 3 | +import android.os.Bundle; | ||
| 4 | +import android.view.MotionEvent; | ||
| 5 | + | ||
| 6 | +import androidx.annotation.DrawableRes; | ||
| 7 | +import androidx.annotation.Nullable; | ||
| 8 | +import androidx.core.app.ActivityCompat; | ||
| 9 | +import androidx.fragment.app.Fragment; | ||
| 10 | +import androidx.fragment.app.FragmentActivity; | ||
| 11 | +import androidx.fragment.app.FragmentManager; | ||
| 12 | +import androidx.fragment.app.FragmentationMagician; | ||
| 13 | + | ||
| 14 | +import com.me.yokeyword.fragmentation.anim.DefaultVerticalAnimator; | ||
| 15 | +import com.me.yokeyword.fragmentation.anim.FragmentAnimator; | ||
| 16 | +import com.me.yokeyword.fragmentation.debug.DebugStackDelegate; | ||
| 17 | +import com.me.yokeyword.fragmentation.queue.Action; | ||
| 18 | + | ||
| 19 | +public class SupportActivityDelegate { | ||
| 20 | + private ISupportActivity mSupport; | ||
| 21 | + private FragmentActivity mActivity; | ||
| 22 | + | ||
| 23 | + boolean mPopMultipleNoAnim = false; | ||
| 24 | + boolean mFragmentClickable = true; | ||
| 25 | + | ||
| 26 | + private TransactionDelegate mTransactionDelegate; | ||
| 27 | + private FragmentAnimator mFragmentAnimator; | ||
| 28 | + private int mDefaultFragmentBackground = 0; | ||
| 29 | + private DebugStackDelegate mDebugStackDelegate; | ||
| 30 | + | ||
| 31 | + public SupportActivityDelegate(ISupportActivity support) { | ||
| 32 | + if (!(support instanceof FragmentActivity)) | ||
| 33 | + throw new RuntimeException("Must extends FragmentActivity/AppCompatActivity"); | ||
| 34 | + this.mSupport = support; | ||
| 35 | + this.mActivity = (FragmentActivity) support; | ||
| 36 | + this.mDebugStackDelegate = new DebugStackDelegate(this.mActivity); | ||
| 37 | + } | ||
| 38 | + | ||
| 39 | + /** | ||
| 40 | + * Perform some extra transactions. | ||
| 41 | + * 额外的事务:自定义Tag,添加SharedElement动画,操作非回退栈Fragment | ||
| 42 | + */ | ||
| 43 | + public ExtraTransaction extraTransaction() { | ||
| 44 | + return new ExtraTransaction.ExtraTransactionImpl<>((FragmentActivity) mSupport, getTopFragment(), getTransactionDelegate(), true); | ||
| 45 | + } | ||
| 46 | + | ||
| 47 | + public void onCreate(@Nullable Bundle savedInstanceState) { | ||
| 48 | + mTransactionDelegate = getTransactionDelegate(); | ||
| 49 | + mFragmentAnimator = mSupport.onCreateFragmentAnimator(); | ||
| 50 | + mDebugStackDelegate.onCreate(Fragmentation.getDefault().getMode()); | ||
| 51 | + } | ||
| 52 | + | ||
| 53 | + public TransactionDelegate getTransactionDelegate() { | ||
| 54 | + if (mTransactionDelegate == null) { | ||
| 55 | + mTransactionDelegate = new TransactionDelegate(mSupport); | ||
| 56 | + } | ||
| 57 | + return mTransactionDelegate; | ||
| 58 | + } | ||
| 59 | + | ||
| 60 | + public void onPostCreate(@Nullable Bundle savedInstanceState) { | ||
| 61 | + mDebugStackDelegate.onPostCreate(Fragmentation.getDefault().getMode()); | ||
| 62 | + } | ||
| 63 | + | ||
| 64 | + /** | ||
| 65 | + * 获取设置的全局动画 copy | ||
| 66 | + * | ||
| 67 | + * @return FragmentAnimator | ||
| 68 | + */ | ||
| 69 | + public FragmentAnimator getFragmentAnimator() { | ||
| 70 | + return mFragmentAnimator.copy(); | ||
| 71 | + } | ||
| 72 | + | ||
| 73 | + /** | ||
| 74 | + * Set all fragments animation. | ||
| 75 | + * 设置Fragment内的全局动画 | ||
| 76 | + */ | ||
| 77 | + public void setFragmentAnimator(FragmentAnimator fragmentAnimator) { | ||
| 78 | + this.mFragmentAnimator = fragmentAnimator; | ||
| 79 | + | ||
| 80 | + for (Fragment fragment : FragmentationMagician.getActiveFragments(getSupportFragmentManager())) { | ||
| 81 | + if (fragment instanceof ISupportFragment) { | ||
| 82 | + ISupportFragment iF = (ISupportFragment) fragment; | ||
| 83 | + SupportFragmentDelegate delegate = iF.getSupportDelegate(); | ||
| 84 | + if (delegate.mAnimByActivity) { | ||
| 85 | + delegate.mFragmentAnimator = fragmentAnimator.copy(); | ||
| 86 | + if (delegate.mAnimHelper != null) { | ||
| 87 | + delegate.mAnimHelper.notifyChanged(delegate.mFragmentAnimator); | ||
| 88 | + } | ||
| 89 | + } | ||
| 90 | + } | ||
| 91 | + } | ||
| 92 | + } | ||
| 93 | + | ||
| 94 | + /** | ||
| 95 | + * Set all fragments animation. | ||
| 96 | + * 构建Fragment转场动画 | ||
| 97 | + * <p/> | ||
| 98 | + * 如果是在Activity内实现,则构建的是Activity内所有Fragment的转场动画, | ||
| 99 | + * 如果是在Fragment内实现,则构建的是该Fragment的转场动画,此时优先级 > Activity的onCreateFragmentAnimator() | ||
| 100 | + * | ||
| 101 | + * @return FragmentAnimator对象 | ||
| 102 | + */ | ||
| 103 | + public FragmentAnimator onCreateFragmentAnimator() { | ||
| 104 | + return new DefaultVerticalAnimator(); | ||
| 105 | + } | ||
| 106 | + | ||
| 107 | + /** | ||
| 108 | + * 当Fragment根布局 没有 设定background属性时, | ||
| 109 | + * Fragmentation默认使用Theme的android:windowbackground作为Fragment的背景, | ||
| 110 | + * 可以通过该方法改变Fragment背景。 | ||
| 111 | + */ | ||
| 112 | + public void setDefaultFragmentBackground(@DrawableRes int backgroundRes) { | ||
| 113 | + mDefaultFragmentBackground = backgroundRes; | ||
| 114 | + } | ||
| 115 | + | ||
| 116 | + public int getDefaultFragmentBackground() { | ||
| 117 | + return mDefaultFragmentBackground; | ||
| 118 | + } | ||
| 119 | + | ||
| 120 | + /** | ||
| 121 | + * 显示栈视图dialog,调试时使用 | ||
| 122 | + */ | ||
| 123 | + public void showFragmentStackHierarchyView() { | ||
| 124 | + mDebugStackDelegate.showFragmentStackHierarchyView(); | ||
| 125 | + } | ||
| 126 | + | ||
| 127 | + /** | ||
| 128 | + * 显示栈视图日志,调试时使用 | ||
| 129 | + */ | ||
| 130 | + public void logFragmentStackHierarchy(String TAG) { | ||
| 131 | + mDebugStackDelegate.logFragmentRecords(TAG); | ||
| 132 | + } | ||
| 133 | + | ||
| 134 | + /** | ||
| 135 | + * Causes the Runnable r to be added to the action queue. | ||
| 136 | + * <p> | ||
| 137 | + * The runnable will be run after all the previous action has been run. | ||
| 138 | + * <p> | ||
| 139 | + * 前面的事务全部执行后 执行该Action | ||
| 140 | + */ | ||
| 141 | + public void post(final Runnable runnable) { | ||
| 142 | + mTransactionDelegate.post(runnable); | ||
| 143 | + } | ||
| 144 | + | ||
| 145 | + /** | ||
| 146 | + * 不建议复写该方法,请使用 {@link #onBackPressedSupport} 代替 | ||
| 147 | + */ | ||
| 148 | + public void onBackPressed() { | ||
| 149 | + mTransactionDelegate.mActionQueue.enqueue(new Action(Action.ACTION_BACK) { | ||
| 150 | + @Override | ||
| 151 | + public void run() { | ||
| 152 | + if (!mFragmentClickable) { | ||
| 153 | + mFragmentClickable = true; | ||
| 154 | + } | ||
| 155 | + | ||
| 156 | + // 获取activeFragment:即从栈顶开始 状态为show的那个Fragment | ||
| 157 | + ISupportFragment activeFragment = SupportHelper.getActiveFragment(getSupportFragmentManager()); | ||
| 158 | + if (mTransactionDelegate.dispatchBackPressedEvent(activeFragment)) return; | ||
| 159 | + | ||
| 160 | + mSupport.onBackPressedSupport(); | ||
| 161 | + } | ||
| 162 | + }); | ||
| 163 | + } | ||
| 164 | + | ||
| 165 | + /** | ||
| 166 | + * 该方法回调时机为,Activity回退栈内Fragment的数量 小于等于1 时,默认finish Activity | ||
| 167 | + * 请尽量复写该方法,避免复写onBackPress(),以保证SupportFragment内的onBackPressedSupport()回退事件正常执行 | ||
| 168 | + */ | ||
| 169 | + public void onBackPressedSupport() { | ||
| 170 | + if (getSupportFragmentManager().getBackStackEntryCount() > 1) { | ||
| 171 | + pop(); | ||
| 172 | + } else { | ||
| 173 | + ActivityCompat.finishAfterTransition(mActivity); | ||
| 174 | + } | ||
| 175 | + } | ||
| 176 | + | ||
| 177 | + public void onDestroy() { | ||
| 178 | + mDebugStackDelegate.onDestroy(); | ||
| 179 | + } | ||
| 180 | + | ||
| 181 | + public boolean dispatchTouchEvent(MotionEvent ev) { | ||
| 182 | + // 防抖动(防止点击速度过快) | ||
| 183 | + return !mFragmentClickable; | ||
| 184 | + } | ||
| 185 | + | ||
| 186 | + /**********************************************************************************************/ | ||
| 187 | + | ||
| 188 | + /** | ||
| 189 | + * 加载根Fragment, 即Activity内的第一个Fragment 或 Fragment内的第一个子Fragment | ||
| 190 | + */ | ||
| 191 | + public void loadRootFragment(int containerId, ISupportFragment toFragment) { | ||
| 192 | + loadRootFragment(containerId, toFragment, true, false); | ||
| 193 | + } | ||
| 194 | + | ||
| 195 | + public void loadRootFragment(int containerId, ISupportFragment toFragment, boolean addToBackStack, boolean allowAnimation) { | ||
| 196 | + mTransactionDelegate.loadRootTransaction(getSupportFragmentManager(), containerId, toFragment, addToBackStack, allowAnimation); | ||
| 197 | + } | ||
| 198 | + | ||
| 199 | + /** | ||
| 200 | + * 加载多个同级根Fragment,类似Wechat, QQ主页的场景 | ||
| 201 | + */ | ||
| 202 | + public void loadMultipleRootFragment(int containerId, int showPosition, ISupportFragment... toFragments) { | ||
| 203 | + mTransactionDelegate.loadMultipleRootTransaction(getSupportFragmentManager(), containerId, showPosition, toFragments); | ||
| 204 | + } | ||
| 205 | + | ||
| 206 | + /** | ||
| 207 | + * show一个Fragment,hide其他同栈所有Fragment | ||
| 208 | + * 使用该方法时,要确保同级栈内无多余的Fragment,(只有通过loadMultipleRootFragment()载入的Fragment) | ||
| 209 | + * <p> | ||
| 210 | + * 建议使用更明确的{@link #showHideFragment(ISupportFragment, ISupportFragment)} | ||
| 211 | + * | ||
| 212 | + * @param showFragment 需要show的Fragment | ||
| 213 | + */ | ||
| 214 | + public void showHideFragment(ISupportFragment showFragment) { | ||
| 215 | + showHideFragment(showFragment, null); | ||
| 216 | + } | ||
| 217 | + | ||
| 218 | + /** | ||
| 219 | + * show一个Fragment,hide一个Fragment ; 主要用于类似微信主页那种 切换tab的情况 | ||
| 220 | + * | ||
| 221 | + * @param showFragment 需要show的Fragment | ||
| 222 | + * @param hideFragment 需要hide的Fragment | ||
| 223 | + */ | ||
| 224 | + public void showHideFragment(ISupportFragment showFragment, ISupportFragment hideFragment) { | ||
| 225 | + mTransactionDelegate.showHideFragment(getSupportFragmentManager(), showFragment, hideFragment); | ||
| 226 | + } | ||
| 227 | + | ||
| 228 | + public void start(ISupportFragment toFragment) { | ||
| 229 | + start(toFragment, ISupportFragment.STANDARD); | ||
| 230 | + } | ||
| 231 | + | ||
| 232 | + /** | ||
| 233 | + * @param launchMode Similar to Activity's LaunchMode. | ||
| 234 | + */ | ||
| 235 | + public void start(ISupportFragment toFragment, @ISupportFragment.LaunchMode int launchMode) { | ||
| 236 | + mTransactionDelegate.dispatchStartTransaction(getSupportFragmentManager(), getTopFragment(), toFragment, 0, launchMode, TransactionDelegate.TYPE_ADD); | ||
| 237 | + } | ||
| 238 | + | ||
| 239 | + /** | ||
| 240 | + * Launch an fragment for which you would like a result when it poped. | ||
| 241 | + */ | ||
| 242 | + public void startForResult(ISupportFragment toFragment, int requestCode) { | ||
| 243 | + mTransactionDelegate.dispatchStartTransaction(getSupportFragmentManager(), getTopFragment(), toFragment, requestCode, ISupportFragment.STANDARD, TransactionDelegate.TYPE_ADD_RESULT); | ||
| 244 | + } | ||
| 245 | + | ||
| 246 | + /** | ||
| 247 | + * Start the target Fragment and pop itself | ||
| 248 | + */ | ||
| 249 | + public void startWithPop(ISupportFragment toFragment) { | ||
| 250 | + mTransactionDelegate.startWithPop(getSupportFragmentManager(), getTopFragment(), toFragment); | ||
| 251 | + } | ||
| 252 | + | ||
| 253 | + public void startWithPopTo(ISupportFragment toFragment, Class<?> targetFragmentClass, boolean includeTargetFragment) { | ||
| 254 | + mTransactionDelegate.startWithPopTo(getSupportFragmentManager(), getTopFragment(), toFragment, targetFragmentClass.getName(), includeTargetFragment); | ||
| 255 | + } | ||
| 256 | + | ||
| 257 | + public void replaceFragment(ISupportFragment toFragment, boolean addToBackStack) { | ||
| 258 | + mTransactionDelegate.dispatchStartTransaction(getSupportFragmentManager(), getTopFragment(), toFragment, 0, ISupportFragment.STANDARD, addToBackStack ? TransactionDelegate.TYPE_REPLACE : TransactionDelegate.TYPE_REPLACE_DONT_BACK); | ||
| 259 | + } | ||
| 260 | + | ||
| 261 | + /** | ||
| 262 | + * Pop the child fragment. | ||
| 263 | + */ | ||
| 264 | + public void pop() { | ||
| 265 | + mTransactionDelegate.pop(getSupportFragmentManager()); | ||
| 266 | + } | ||
| 267 | + | ||
| 268 | + /** | ||
| 269 | + * Pop the last fragment transition from the manager's fragment | ||
| 270 | + * back stack. | ||
| 271 | + * <p> | ||
| 272 | + * 出栈到目标fragment | ||
| 273 | + * | ||
| 274 | + * @param targetFragmentClass 目标fragment | ||
| 275 | + * @param includeTargetFragment 是否包含该fragment | ||
| 276 | + */ | ||
| 277 | + public void popTo(Class<?> targetFragmentClass, boolean includeTargetFragment) { | ||
| 278 | + popTo(targetFragmentClass, includeTargetFragment, null); | ||
| 279 | + } | ||
| 280 | + | ||
| 281 | + /** | ||
| 282 | + * If you want to begin another FragmentTransaction immediately after popTo(), use this method. | ||
| 283 | + * 如果你想在出栈后, 立刻进行FragmentTransaction操作,请使用该方法 | ||
| 284 | + */ | ||
| 285 | + public void popTo(Class<?> targetFragmentClass, boolean includeTargetFragment, Runnable afterPopTransactionRunnable) { | ||
| 286 | + popTo(targetFragmentClass, includeTargetFragment, afterPopTransactionRunnable, TransactionDelegate.DEFAULT_POPTO_ANIM); | ||
| 287 | + } | ||
| 288 | + | ||
| 289 | + public void popTo(Class<?> targetFragmentClass, boolean includeTargetFragment, Runnable afterPopTransactionRunnable, int popAnim) { | ||
| 290 | + mTransactionDelegate.popTo(targetFragmentClass.getName(), includeTargetFragment, afterPopTransactionRunnable, getSupportFragmentManager(), popAnim); | ||
| 291 | + } | ||
| 292 | + | ||
| 293 | + private FragmentManager getSupportFragmentManager() { | ||
| 294 | + return mActivity.getSupportFragmentManager(); | ||
| 295 | + } | ||
| 296 | + | ||
| 297 | + private ISupportFragment getTopFragment() { | ||
| 298 | + return SupportHelper.getTopFragment(getSupportFragmentManager()); | ||
| 299 | + } | ||
| 300 | +} |
core/base/src/main/java/com/me/yokeyword/fragmentation/SupportFragment.java
0 → 100644
| 1 | +package com.me.yokeyword.fragmentation; | ||
| 2 | + | ||
| 3 | +import android.app.Activity; | ||
| 4 | +import android.content.Intent; | ||
| 5 | +import android.os.Bundle; | ||
| 6 | +import android.view.View; | ||
| 7 | +import android.view.animation.Animation; | ||
| 8 | + | ||
| 9 | +import androidx.annotation.Nullable; | ||
| 10 | +import androidx.fragment.app.Fragment; | ||
| 11 | + | ||
| 12 | +import com.me.yokeyword.fragmentation.anim.FragmentAnimator; | ||
| 13 | + | ||
| 14 | + | ||
| 15 | +/** | ||
| 16 | + * Base class for activities that use the support-based | ||
| 17 | + * {@link ISupportFragment} and | ||
| 18 | + * {@link Fragment} APIs. | ||
| 19 | + * Created by YoKey on 17/6/22. | ||
| 20 | + */ | ||
| 21 | +public class SupportFragment extends Fragment implements ISupportFragment { | ||
| 22 | + final SupportFragmentDelegate mDelegate = new SupportFragmentDelegate(this); | ||
| 23 | + protected SupportActivity _mActivity; | ||
| 24 | + | ||
| 25 | + @Override | ||
| 26 | + public SupportFragmentDelegate getSupportDelegate() { | ||
| 27 | + return mDelegate; | ||
| 28 | + } | ||
| 29 | + | ||
| 30 | + /** | ||
| 31 | + * Perform some extra transactions. | ||
| 32 | + * 额外的事务:自定义Tag,添加SharedElement动画,操作非回退栈Fragment | ||
| 33 | + */ | ||
| 34 | + @Override | ||
| 35 | + public ExtraTransaction extraTransaction() { | ||
| 36 | + return mDelegate.extraTransaction(); | ||
| 37 | + } | ||
| 38 | + | ||
| 39 | + @Override | ||
| 40 | + public void onAttach(Activity activity) { | ||
| 41 | + super.onAttach(activity); | ||
| 42 | + mDelegate.onAttach(activity); | ||
| 43 | + _mActivity = (SupportActivity) mDelegate.getActivity(); | ||
| 44 | + } | ||
| 45 | + | ||
| 46 | + @Override | ||
| 47 | + public void onCreate(@Nullable Bundle savedInstanceState) { | ||
| 48 | + super.onCreate(savedInstanceState); | ||
| 49 | + mDelegate.onCreate(savedInstanceState); | ||
| 50 | + } | ||
| 51 | + | ||
| 52 | + @Override | ||
| 53 | + public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) { | ||
| 54 | + return mDelegate.onCreateAnimation(transit, enter, nextAnim); | ||
| 55 | + } | ||
| 56 | + | ||
| 57 | + @Override | ||
| 58 | + public void onActivityCreated(@Nullable Bundle savedInstanceState) { | ||
| 59 | + super.onActivityCreated(savedInstanceState); | ||
| 60 | + mDelegate.onActivityCreated(savedInstanceState); | ||
| 61 | + } | ||
| 62 | + | ||
| 63 | + @Override | ||
| 64 | + public void onSaveInstanceState(Bundle outState) { | ||
| 65 | + super.onSaveInstanceState(outState); | ||
| 66 | + mDelegate.onSaveInstanceState(outState); | ||
| 67 | + } | ||
| 68 | + | ||
| 69 | + @Override | ||
| 70 | + public void onResume() { | ||
| 71 | + super.onResume(); | ||
| 72 | + mDelegate.onResume(); | ||
| 73 | + } | ||
| 74 | + | ||
| 75 | + @Override | ||
| 76 | + public void onPause() { | ||
| 77 | + super.onPause(); | ||
| 78 | + mDelegate.onPause(); | ||
| 79 | + } | ||
| 80 | + | ||
| 81 | + @Override | ||
| 82 | + public void onDestroyView() { | ||
| 83 | + mDelegate.onDestroyView(); | ||
| 84 | + super.onDestroyView(); | ||
| 85 | + } | ||
| 86 | + | ||
| 87 | + @Override | ||
| 88 | + public void onDestroy() { | ||
| 89 | + mDelegate.onDestroy(); | ||
| 90 | + super.onDestroy(); | ||
| 91 | + } | ||
| 92 | + | ||
| 93 | + @Override | ||
| 94 | + public void onHiddenChanged(boolean hidden) { | ||
| 95 | + super.onHiddenChanged(hidden); | ||
| 96 | + mDelegate.onHiddenChanged(hidden); | ||
| 97 | + } | ||
| 98 | + | ||
| 99 | + @Override | ||
| 100 | + public void setUserVisibleHint(boolean isVisibleToUser) { | ||
| 101 | + super.setUserVisibleHint(isVisibleToUser); | ||
| 102 | + mDelegate.setUserVisibleHint(isVisibleToUser); | ||
| 103 | + } | ||
| 104 | + | ||
| 105 | + /** | ||
| 106 | + * Causes the Runnable r to be added to the action queue. | ||
| 107 | + * <p> | ||
| 108 | + * The runnable will be run after all the previous action has been run. | ||
| 109 | + * <p> | ||
| 110 | + * 前面的事务全部执行后 执行该Action | ||
| 111 | + * | ||
| 112 | + * @deprecated Use {@link #post(Runnable)} instead. | ||
| 113 | + */ | ||
| 114 | + @Deprecated | ||
| 115 | + @Override | ||
| 116 | + public void enqueueAction(Runnable runnable) { | ||
| 117 | + mDelegate.enqueueAction(runnable); | ||
| 118 | + } | ||
| 119 | + | ||
| 120 | + /** | ||
| 121 | + * Causes the Runnable r to be added to the action queue. | ||
| 122 | + * <p> | ||
| 123 | + * The runnable will be run after all the previous action has been run. | ||
| 124 | + * <p> | ||
| 125 | + * 前面的事务全部执行后 执行该Action | ||
| 126 | + */ | ||
| 127 | + @Override | ||
| 128 | + public void post(Runnable runnable) { | ||
| 129 | + mDelegate.post(runnable); | ||
| 130 | + } | ||
| 131 | + | ||
| 132 | + /** | ||
| 133 | + * Called when the enter-animation end. | ||
| 134 | + * 入栈动画 结束时,回调 | ||
| 135 | + */ | ||
| 136 | + @Override | ||
| 137 | + public void onEnterAnimationEnd(Bundle savedInstanceState) { | ||
| 138 | + mDelegate.onEnterAnimationEnd(savedInstanceState); | ||
| 139 | + } | ||
| 140 | + | ||
| 141 | + | ||
| 142 | + /** | ||
| 143 | + * Lazy initial,Called when fragment is first called. | ||
| 144 | + * <p> | ||
| 145 | + * 同级下的 懒加载 + ViewPager下的懒加载 的结合回调方法 | ||
| 146 | + */ | ||
| 147 | + @Override | ||
| 148 | + public void onLazyInitView(@Nullable Bundle savedInstanceState) { | ||
| 149 | + mDelegate.onLazyInitView(savedInstanceState); | ||
| 150 | + } | ||
| 151 | + | ||
| 152 | + /** | ||
| 153 | + * Called when the fragment is visible. | ||
| 154 | + * 当Fragment对用户可见时回调 | ||
| 155 | + * <p> | ||
| 156 | + * Is the combination of [onHiddenChanged() + onResume()/onPause() + setUserVisibleHint()] | ||
| 157 | + */ | ||
| 158 | + @Override | ||
| 159 | + public void onSupportVisible() { | ||
| 160 | + mDelegate.onSupportVisible(); | ||
| 161 | + } | ||
| 162 | + | ||
| 163 | + /** | ||
| 164 | + * Called when the fragment is invivible. | ||
| 165 | + * <p> | ||
| 166 | + * Is the combination of [onHiddenChanged() + onResume()/onPause() + setUserVisibleHint()] | ||
| 167 | + */ | ||
| 168 | + @Override | ||
| 169 | + public void onSupportInvisible() { | ||
| 170 | + mDelegate.onSupportInvisible(); | ||
| 171 | + } | ||
| 172 | + | ||
| 173 | + /** | ||
| 174 | + * Return true if the fragment has been supportVisible. | ||
| 175 | + */ | ||
| 176 | + @Override | ||
| 177 | + final public boolean isSupportVisible() { | ||
| 178 | + return mDelegate.isSupportVisible(); | ||
| 179 | + } | ||
| 180 | + | ||
| 181 | + /** | ||
| 182 | + * Set fragment animation with a higher priority than the ISupportActivity | ||
| 183 | + * 设定当前Fragmemt动画,优先级比在SupportActivity里高 | ||
| 184 | + */ | ||
| 185 | + @Override | ||
| 186 | + public FragmentAnimator onCreateFragmentAnimator() { | ||
| 187 | + return mDelegate.onCreateFragmentAnimator(); | ||
| 188 | + } | ||
| 189 | + | ||
| 190 | + /** | ||
| 191 | + * 获取设置的全局动画 copy | ||
| 192 | + * | ||
| 193 | + * @return FragmentAnimator | ||
| 194 | + */ | ||
| 195 | + @Override | ||
| 196 | + public FragmentAnimator getFragmentAnimator() { | ||
| 197 | + return mDelegate.getFragmentAnimator(); | ||
| 198 | + } | ||
| 199 | + | ||
| 200 | + /** | ||
| 201 | + * 设置Fragment内的全局动画 | ||
| 202 | + */ | ||
| 203 | + @Override | ||
| 204 | + public void setFragmentAnimator(FragmentAnimator fragmentAnimator) { | ||
| 205 | + mDelegate.setFragmentAnimator(fragmentAnimator); | ||
| 206 | + } | ||
| 207 | + | ||
| 208 | + /** | ||
| 209 | + * 按返回键触发,前提是SupportActivity的onBackPressed()方法能被调用 | ||
| 210 | + * | ||
| 211 | + * @return false则继续向上传递, true则消费掉该事件 | ||
| 212 | + */ | ||
| 213 | + @Override | ||
| 214 | + public boolean onBackPressedSupport() { | ||
| 215 | + return mDelegate.onBackPressedSupport(); | ||
| 216 | + } | ||
| 217 | + | ||
| 218 | + /** | ||
| 219 | + * 类似 {@link Activity#setResult(int, Intent)} | ||
| 220 | + * <p> | ||
| 221 | + * Similar to {@link Activity#setResult(int, Intent)} | ||
| 222 | + * | ||
| 223 | + * @see #startForResult(ISupportFragment, int) | ||
| 224 | + */ | ||
| 225 | + @Override | ||
| 226 | + public void setFragmentResult(int resultCode, Bundle bundle) { | ||
| 227 | + mDelegate.setFragmentResult(resultCode, bundle); | ||
| 228 | + } | ||
| 229 | + | ||
| 230 | + /** | ||
| 231 | + * 类似 {@link Activity#onActivityResult(int, int, Intent)} | ||
| 232 | + * <p> | ||
| 233 | + * Similar to {@link Activity#onActivityResult(int, int, Intent)} | ||
| 234 | + * | ||
| 235 | + * @see #startForResult(ISupportFragment, int) | ||
| 236 | + */ | ||
| 237 | + @Override | ||
| 238 | + public void onFragmentResult(int requestCode, int resultCode, Bundle data) { | ||
| 239 | + mDelegate.onFragmentResult(requestCode, resultCode, data); | ||
| 240 | + } | ||
| 241 | + | ||
| 242 | + /** | ||
| 243 | + * 在start(TargetFragment,LaunchMode)时,启动模式为SingleTask/SingleTop, 回调TargetFragment的该方法 | ||
| 244 | + * 类似 {@link Activity#onNewIntent(Intent)} | ||
| 245 | + * <p> | ||
| 246 | + * Similar to {@link Activity#onNewIntent(Intent)} | ||
| 247 | + * | ||
| 248 | + * @param args putNewBundle(Bundle newBundle) | ||
| 249 | + * @see #start(ISupportFragment, int) | ||
| 250 | + */ | ||
| 251 | + @Override | ||
| 252 | + public void onNewBundle(Bundle args) { | ||
| 253 | + mDelegate.onNewBundle(args); | ||
| 254 | + } | ||
| 255 | + | ||
| 256 | + /** | ||
| 257 | + * 添加NewBundle,用于启动模式为SingleTask/SingleTop时 | ||
| 258 | + * | ||
| 259 | + * @see #start(ISupportFragment, int) | ||
| 260 | + */ | ||
| 261 | + @Override | ||
| 262 | + public void putNewBundle(Bundle newBundle) { | ||
| 263 | + mDelegate.putNewBundle(newBundle); | ||
| 264 | + } | ||
| 265 | + | ||
| 266 | + | ||
| 267 | + /****************************************以下为可选方法(Optional methods)******************************************************/ | ||
| 268 | + | ||
| 269 | + /** | ||
| 270 | + * 隐藏软键盘 | ||
| 271 | + */ | ||
| 272 | + protected void hideSoftInput() { | ||
| 273 | + mDelegate.hideSoftInput(); | ||
| 274 | + } | ||
| 275 | + | ||
| 276 | + /** | ||
| 277 | + * 显示软键盘,调用该方法后,会在onPause时自动隐藏软键盘 | ||
| 278 | + */ | ||
| 279 | + protected void showSoftInput(final View view) { | ||
| 280 | + mDelegate.showSoftInput(view); | ||
| 281 | + } | ||
| 282 | + | ||
| 283 | + /** | ||
| 284 | + * 加载根Fragment, 即Activity内的第一个Fragment 或 Fragment内的第一个子Fragment | ||
| 285 | + * | ||
| 286 | + * @param containerId 容器id | ||
| 287 | + * @param toFragment 目标Fragment | ||
| 288 | + */ | ||
| 289 | + public void loadRootFragment(int containerId, ISupportFragment toFragment) { | ||
| 290 | + mDelegate.loadRootFragment(containerId, toFragment); | ||
| 291 | + } | ||
| 292 | + | ||
| 293 | + public void loadRootFragment(int containerId, ISupportFragment toFragment, boolean addToBackStack, boolean allowAnim) { | ||
| 294 | + mDelegate.loadRootFragment(containerId, toFragment, addToBackStack, allowAnim); | ||
| 295 | + } | ||
| 296 | + | ||
| 297 | + /** | ||
| 298 | + * 加载多个同级根Fragment,类似Wechat, QQ主页的场景 | ||
| 299 | + */ | ||
| 300 | + public void loadMultipleRootFragment(int containerId, int showPosition, ISupportFragment... toFragments) { | ||
| 301 | + mDelegate.loadMultipleRootFragment(containerId, showPosition, toFragments); | ||
| 302 | + } | ||
| 303 | + | ||
| 304 | + /** | ||
| 305 | + * show一个Fragment,hide其他同栈所有Fragment | ||
| 306 | + * 使用该方法时,要确保同级栈内无多余的Fragment,(只有通过loadMultipleRootFragment()载入的Fragment) | ||
| 307 | + * <p> | ||
| 308 | + * 建议使用更明确的{@link #showHideFragment(ISupportFragment, ISupportFragment)} | ||
| 309 | + * | ||
| 310 | + * @param showFragment 需要show的Fragment | ||
| 311 | + */ | ||
| 312 | + public void showHideFragment(ISupportFragment showFragment) { | ||
| 313 | + mDelegate.showHideFragment(showFragment); | ||
| 314 | + } | ||
| 315 | + | ||
| 316 | + /** | ||
| 317 | + * show一个Fragment,hide一个Fragment ; 主要用于类似微信主页那种 切换tab的情况 | ||
| 318 | + */ | ||
| 319 | + public void showHideFragment(ISupportFragment showFragment, ISupportFragment hideFragment) { | ||
| 320 | + mDelegate.showHideFragment(showFragment, hideFragment); | ||
| 321 | + } | ||
| 322 | + | ||
| 323 | + public void start(ISupportFragment toFragment) { | ||
| 324 | + mDelegate.start(toFragment); | ||
| 325 | + } | ||
| 326 | + | ||
| 327 | + /** | ||
| 328 | + * @param launchMode Similar to Activity's LaunchMode. | ||
| 329 | + */ | ||
| 330 | + public void start(final ISupportFragment toFragment, @LaunchMode int launchMode) { | ||
| 331 | + mDelegate.start(toFragment, launchMode); | ||
| 332 | + } | ||
| 333 | + | ||
| 334 | + /** | ||
| 335 | + * Launch an fragment for which you would like a result when it poped. | ||
| 336 | + */ | ||
| 337 | + public void startForResult(ISupportFragment toFragment, int requestCode) { | ||
| 338 | + mDelegate.startForResult(toFragment, requestCode); | ||
| 339 | + } | ||
| 340 | + | ||
| 341 | + /** | ||
| 342 | + * Start the target Fragment and pop itself | ||
| 343 | + */ | ||
| 344 | + public void startWithPop(ISupportFragment toFragment) { | ||
| 345 | + mDelegate.startWithPop(toFragment); | ||
| 346 | + } | ||
| 347 | + | ||
| 348 | + /** | ||
| 349 | + * @see #popTo(Class, boolean) | ||
| 350 | + * + | ||
| 351 | + * @see #start(ISupportFragment) | ||
| 352 | + */ | ||
| 353 | + public void startWithPopTo(ISupportFragment toFragment, Class<?> targetFragmentClass, boolean includeTargetFragment) { | ||
| 354 | + mDelegate.startWithPopTo(toFragment, targetFragmentClass, includeTargetFragment); | ||
| 355 | + } | ||
| 356 | + | ||
| 357 | + | ||
| 358 | + public void replaceFragment(ISupportFragment toFragment, boolean addToBackStack) { | ||
| 359 | + mDelegate.replaceFragment(toFragment, addToBackStack); | ||
| 360 | + } | ||
| 361 | + | ||
| 362 | + public void pop() { | ||
| 363 | + mDelegate.pop(); | ||
| 364 | + } | ||
| 365 | + | ||
| 366 | + /** | ||
| 367 | + * Pop the child fragment. | ||
| 368 | + */ | ||
| 369 | + public void popChild() { | ||
| 370 | + mDelegate.popChild(); | ||
| 371 | + } | ||
| 372 | + | ||
| 373 | + /** | ||
| 374 | + * Pop the last fragment transition from the manager's fragment | ||
| 375 | + * back stack. | ||
| 376 | + * <p> | ||
| 377 | + * 出栈到目标fragment | ||
| 378 | + * | ||
| 379 | + * @param targetFragmentClass 目标fragment | ||
| 380 | + * @param includeTargetFragment 是否包含该fragment | ||
| 381 | + */ | ||
| 382 | + public void popTo(Class<?> targetFragmentClass, boolean includeTargetFragment) { | ||
| 383 | + mDelegate.popTo(targetFragmentClass, includeTargetFragment); | ||
| 384 | + } | ||
| 385 | + | ||
| 386 | + /** | ||
| 387 | + * If you want to begin another FragmentTransaction immediately after popTo(), use this method. | ||
| 388 | + * 如果你想在出栈后, 立刻进行FragmentTransaction操作,请使用该方法 | ||
| 389 | + */ | ||
| 390 | + public void popTo(Class<?> targetFragmentClass, boolean includeTargetFragment, Runnable afterPopTransactionRunnable) { | ||
| 391 | + mDelegate.popTo(targetFragmentClass, includeTargetFragment, afterPopTransactionRunnable); | ||
| 392 | + } | ||
| 393 | + | ||
| 394 | + public void popTo(Class<?> targetFragmentClass, boolean includeTargetFragment, Runnable afterPopTransactionRunnable, int popAnim) { | ||
| 395 | + mDelegate.popTo(targetFragmentClass, includeTargetFragment, afterPopTransactionRunnable, popAnim); | ||
| 396 | + } | ||
| 397 | + | ||
| 398 | + public void popToChild(Class<?> targetFragmentClass, boolean includeTargetFragment) { | ||
| 399 | + mDelegate.popToChild(targetFragmentClass, includeTargetFragment); | ||
| 400 | + } | ||
| 401 | + | ||
| 402 | + public void popToChild(Class<?> targetFragmentClass, boolean includeTargetFragment, Runnable afterPopTransactionRunnable) { | ||
| 403 | + mDelegate.popToChild(targetFragmentClass, includeTargetFragment, afterPopTransactionRunnable); | ||
| 404 | + } | ||
| 405 | + | ||
| 406 | + public void popToChild(Class<?> targetFragmentClass, boolean includeTargetFragment, Runnable afterPopTransactionRunnable, int popAnim) { | ||
| 407 | + mDelegate.popToChild(targetFragmentClass, includeTargetFragment, afterPopTransactionRunnable, popAnim); | ||
| 408 | + } | ||
| 409 | + | ||
| 410 | + /** | ||
| 411 | + * 得到位于栈顶Fragment | ||
| 412 | + */ | ||
| 413 | + public ISupportFragment getTopFragment() { | ||
| 414 | + return SupportHelper.getTopFragment(getFragmentManager()); | ||
| 415 | + } | ||
| 416 | + | ||
| 417 | + public ISupportFragment getTopChildFragment() { | ||
| 418 | + return SupportHelper.getTopFragment(getChildFragmentManager()); | ||
| 419 | + } | ||
| 420 | + | ||
| 421 | + /** | ||
| 422 | + * @return 位于当前Fragment的前一个Fragment | ||
| 423 | + */ | ||
| 424 | + public ISupportFragment getPreFragment() { | ||
| 425 | + return SupportHelper.getPreFragment(this); | ||
| 426 | + } | ||
| 427 | + | ||
| 428 | + /** | ||
| 429 | + * 获取栈内的fragment对象 | ||
| 430 | + */ | ||
| 431 | + public <T extends ISupportFragment> T findFragment(Class<T> fragmentClass) { | ||
| 432 | + return SupportHelper.findFragment(getFragmentManager(), fragmentClass); | ||
| 433 | + } | ||
| 434 | + | ||
| 435 | + /** | ||
| 436 | + * 获取栈内的fragment对象 | ||
| 437 | + */ | ||
| 438 | + public <T extends ISupportFragment> T findChildFragment(Class<T> fragmentClass) { | ||
| 439 | + return SupportHelper.findFragment(getChildFragmentManager(), fragmentClass); | ||
| 440 | + } | ||
| 441 | +} |
core/base/src/main/java/com/me/yokeyword/fragmentation/SupportFragmentDelegate.java
0 → 100644
| 1 | +package com.me.yokeyword.fragmentation; | ||
| 2 | + | ||
| 3 | +import android.app.Activity; | ||
| 4 | +import android.content.Intent; | ||
| 5 | +import android.content.res.TypedArray; | ||
| 6 | +import android.os.Bundle; | ||
| 7 | +import android.os.Handler; | ||
| 8 | +import android.os.Looper; | ||
| 9 | +import android.view.View; | ||
| 10 | +import android.view.animation.Animation; | ||
| 11 | +import android.view.animation.AnimationUtils; | ||
| 12 | + | ||
| 13 | +import androidx.annotation.Nullable; | ||
| 14 | +import androidx.fragment.app.Fragment; | ||
| 15 | +import androidx.fragment.app.FragmentActivity; | ||
| 16 | +import androidx.fragment.app.FragmentManager; | ||
| 17 | +import androidx.fragment.app.FragmentTransaction; | ||
| 18 | + | ||
| 19 | +import com.me.yokeyword.fragmentation.anim.FragmentAnimator; | ||
| 20 | +import com.me.yokeyword.fragmentation.helper.internal.AnimatorHelper; | ||
| 21 | +import com.me.yokeyword.fragmentation.helper.internal.ResultRecord; | ||
| 22 | +import com.me.yokeyword.fragmentation.helper.internal.TransactionRecord; | ||
| 23 | +import com.me.yokeyword.fragmentation.helper.internal.VisibleDelegate; | ||
| 24 | + | ||
| 25 | + | ||
| 26 | +public class SupportFragmentDelegate { | ||
| 27 | + private static final long NOT_FOUND_ANIM_TIME = 300L; | ||
| 28 | + | ||
| 29 | + static final int STATUS_UN_ROOT = 0; | ||
| 30 | + static final int STATUS_ROOT_ANIM_DISABLE = 1; | ||
| 31 | + static final int STATUS_ROOT_ANIM_ENABLE = 2; | ||
| 32 | + | ||
| 33 | + private int mRootStatus = STATUS_UN_ROOT; | ||
| 34 | + | ||
| 35 | + private boolean mIsSharedElement; | ||
| 36 | + FragmentAnimator mFragmentAnimator; | ||
| 37 | + AnimatorHelper mAnimHelper; | ||
| 38 | + boolean mLockAnim; | ||
| 39 | + private int mCustomEnterAnim = Integer.MIN_VALUE, mCustomExitAnim = Integer.MIN_VALUE, mCustomPopExitAnim = Integer.MIN_VALUE; | ||
| 40 | + | ||
| 41 | + private Handler mHandler; | ||
| 42 | + private boolean mFirstCreateView = true; | ||
| 43 | + private boolean mReplaceMode; | ||
| 44 | + private boolean mIsHidden = true; | ||
| 45 | + int mContainerId; | ||
| 46 | + | ||
| 47 | + private TransactionDelegate mTransactionDelegate; | ||
| 48 | + TransactionRecord mTransactionRecord; | ||
| 49 | + // SupportVisible | ||
| 50 | + private VisibleDelegate mVisibleDelegate; | ||
| 51 | + Bundle mNewBundle; | ||
| 52 | + private Bundle mSaveInstanceState; | ||
| 53 | + | ||
| 54 | + private ISupportFragment mSupportF; | ||
| 55 | + private Fragment mFragment; | ||
| 56 | + protected FragmentActivity _mActivity; | ||
| 57 | + private ISupportActivity mSupport; | ||
| 58 | + boolean mAnimByActivity = true; | ||
| 59 | + EnterAnimListener mEnterAnimListener; | ||
| 60 | + | ||
| 61 | + private boolean mRootViewClickable; | ||
| 62 | + | ||
| 63 | + public SupportFragmentDelegate(ISupportFragment support) { | ||
| 64 | + if (!(support instanceof Fragment)) | ||
| 65 | + throw new RuntimeException("Must extends Fragment"); | ||
| 66 | + this.mSupportF = support; | ||
| 67 | + this.mFragment = (Fragment) support; | ||
| 68 | + } | ||
| 69 | + | ||
| 70 | + /** | ||
| 71 | + * Perform some extra transactions. | ||
| 72 | + * 额外的事务:自定义Tag,添加SharedElement动画,操作非回退栈Fragment | ||
| 73 | + */ | ||
| 74 | + public ExtraTransaction extraTransaction() { | ||
| 75 | + if (mTransactionDelegate == null) | ||
| 76 | + throw new RuntimeException(mFragment.getClass().getSimpleName() + " not attach!"); | ||
| 77 | + | ||
| 78 | + return new ExtraTransaction.ExtraTransactionImpl<>((FragmentActivity) mSupport, mSupportF, mTransactionDelegate, false); | ||
| 79 | + } | ||
| 80 | + | ||
| 81 | + public void onAttach(Activity activity) { | ||
| 82 | + if (activity instanceof ISupportActivity) { | ||
| 83 | + this.mSupport = (ISupportActivity) activity; | ||
| 84 | + this._mActivity = (FragmentActivity) activity; | ||
| 85 | + mTransactionDelegate = mSupport.getSupportDelegate().getTransactionDelegate(); | ||
| 86 | + } else { | ||
| 87 | + throw new RuntimeException(activity.getClass().getSimpleName() + " must impl ISupportActivity!"); | ||
| 88 | + } | ||
| 89 | + } | ||
| 90 | + | ||
| 91 | + public void onCreate(@Nullable Bundle savedInstanceState) { | ||
| 92 | + getVisibleDelegate().onCreate(savedInstanceState); | ||
| 93 | + | ||
| 94 | + Bundle bundle = mFragment.getArguments(); | ||
| 95 | + if (bundle != null) { | ||
| 96 | + mRootStatus = bundle.getInt(TransactionDelegate.FRAGMENTATION_ARG_ROOT_STATUS, STATUS_UN_ROOT); | ||
| 97 | + mIsSharedElement = bundle.getBoolean(TransactionDelegate.FRAGMENTATION_ARG_IS_SHARED_ELEMENT, false); | ||
| 98 | + mContainerId = bundle.getInt(TransactionDelegate.FRAGMENTATION_ARG_CONTAINER); | ||
| 99 | + mReplaceMode = bundle.getBoolean(TransactionDelegate.FRAGMENTATION_ARG_REPLACE, false); | ||
| 100 | + mCustomEnterAnim = bundle.getInt(TransactionDelegate.FRAGMENTATION_ARG_CUSTOM_ENTER_ANIM, Integer.MIN_VALUE); | ||
| 101 | + mCustomExitAnim = bundle.getInt(TransactionDelegate.FRAGMENTATION_ARG_CUSTOM_EXIT_ANIM, Integer.MIN_VALUE); | ||
| 102 | + mCustomPopExitAnim = bundle.getInt(TransactionDelegate.FRAGMENTATION_ARG_CUSTOM_POP_EXIT_ANIM, Integer.MIN_VALUE); | ||
| 103 | + } | ||
| 104 | + | ||
| 105 | + if (savedInstanceState == null) { | ||
| 106 | + getFragmentAnimator(); | ||
| 107 | + } else { | ||
| 108 | + savedInstanceState.setClassLoader(getClass().getClassLoader()); | ||
| 109 | + mSaveInstanceState = savedInstanceState; | ||
| 110 | + mFragmentAnimator = savedInstanceState.getParcelable(TransactionDelegate.FRAGMENTATION_STATE_SAVE_ANIMATOR); | ||
| 111 | + mIsHidden = savedInstanceState.getBoolean(TransactionDelegate.FRAGMENTATION_STATE_SAVE_IS_HIDDEN); | ||
| 112 | + mContainerId = savedInstanceState.getInt(TransactionDelegate.FRAGMENTATION_ARG_CONTAINER); | ||
| 113 | + } | ||
| 114 | + | ||
| 115 | + mAnimHelper = new AnimatorHelper(_mActivity.getApplicationContext(), mFragmentAnimator); | ||
| 116 | + | ||
| 117 | + final Animation enter = getEnterAnim(); | ||
| 118 | + if (enter == null) return; | ||
| 119 | + | ||
| 120 | + getEnterAnim().setAnimationListener(new Animation.AnimationListener() { | ||
| 121 | + | ||
| 122 | + @Override | ||
| 123 | + public void onAnimationStart(Animation animation) { | ||
| 124 | + mSupport.getSupportDelegate().mFragmentClickable = false; // 开启防抖动 | ||
| 125 | + | ||
| 126 | + mHandler.postDelayed(new Runnable() { | ||
| 127 | + @Override | ||
| 128 | + public void run() { | ||
| 129 | + mSupport.getSupportDelegate().mFragmentClickable = true; | ||
| 130 | + } | ||
| 131 | + }, enter.getDuration()); | ||
| 132 | + } | ||
| 133 | + | ||
| 134 | + @Override | ||
| 135 | + public void onAnimationEnd(Animation animation) { | ||
| 136 | + } | ||
| 137 | + | ||
| 138 | + @Override | ||
| 139 | + public void onAnimationRepeat(Animation animation) { | ||
| 140 | + | ||
| 141 | + } | ||
| 142 | + }); | ||
| 143 | + } | ||
| 144 | + | ||
| 145 | + public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) { | ||
| 146 | + if ((mSupport.getSupportDelegate().mPopMultipleNoAnim || mLockAnim)) { | ||
| 147 | + if (transit == FragmentTransaction.TRANSIT_FRAGMENT_CLOSE && enter) { | ||
| 148 | + return mAnimHelper.getNoneAnimFixed(); | ||
| 149 | + } | ||
| 150 | + return mAnimHelper.getNoneAnim(); | ||
| 151 | + } | ||
| 152 | + if (transit == FragmentTransaction.TRANSIT_FRAGMENT_OPEN) { | ||
| 153 | + if (enter) { | ||
| 154 | + Animation enterAnim; | ||
| 155 | + if (mRootStatus == STATUS_ROOT_ANIM_DISABLE) { | ||
| 156 | + enterAnim = mAnimHelper.getNoneAnim(); | ||
| 157 | + } else { | ||
| 158 | + enterAnim = mAnimHelper.enterAnim; | ||
| 159 | + fixAnimationListener(enterAnim); | ||
| 160 | + } | ||
| 161 | + return enterAnim; | ||
| 162 | + } else { | ||
| 163 | + return mAnimHelper.popExitAnim; | ||
| 164 | + } | ||
| 165 | + } else if (transit == FragmentTransaction.TRANSIT_FRAGMENT_CLOSE) { | ||
| 166 | + return enter ? mAnimHelper.popEnterAnim : mAnimHelper.exitAnim; | ||
| 167 | + } else { | ||
| 168 | + if (mIsSharedElement && enter) { | ||
| 169 | + compatSharedElements(); | ||
| 170 | + } | ||
| 171 | + | ||
| 172 | + if (!enter) { | ||
| 173 | + return mAnimHelper.compatChildFragmentExitAnim(mFragment); | ||
| 174 | + } | ||
| 175 | + | ||
| 176 | + return null; | ||
| 177 | + } | ||
| 178 | + } | ||
| 179 | + | ||
| 180 | + public void onSaveInstanceState(Bundle outState) { | ||
| 181 | + getVisibleDelegate().onSaveInstanceState(outState); | ||
| 182 | + outState.putParcelable(TransactionDelegate.FRAGMENTATION_STATE_SAVE_ANIMATOR, mFragmentAnimator); | ||
| 183 | + outState.putBoolean(TransactionDelegate.FRAGMENTATION_STATE_SAVE_IS_HIDDEN, mFragment.isHidden()); | ||
| 184 | + outState.putInt(TransactionDelegate.FRAGMENTATION_ARG_CONTAINER, mContainerId); | ||
| 185 | + } | ||
| 186 | + | ||
| 187 | + public void onActivityCreated(@Nullable Bundle savedInstanceState) { | ||
| 188 | + getVisibleDelegate().onActivityCreated(savedInstanceState); | ||
| 189 | + | ||
| 190 | + View view = mFragment.getView(); | ||
| 191 | + if (view != null) { | ||
| 192 | + mRootViewClickable = view.isClickable(); | ||
| 193 | + view.setClickable(true); | ||
| 194 | + setBackground(view); | ||
| 195 | + } | ||
| 196 | + | ||
| 197 | + | ||
| 198 | + if (savedInstanceState != null | ||
| 199 | + || mRootStatus == STATUS_ROOT_ANIM_DISABLE | ||
| 200 | + || (mFragment.getTag() != null && mFragment.getTag().startsWith("android:switcher:")) | ||
| 201 | + || (mReplaceMode && !mFirstCreateView)) { | ||
| 202 | + notifyEnterAnimEnd(); | ||
| 203 | + } else if (mCustomEnterAnim != Integer.MIN_VALUE) { | ||
| 204 | + fixAnimationListener(mCustomEnterAnim == 0 ? | ||
| 205 | + mAnimHelper.getNoneAnim() : AnimationUtils.loadAnimation(_mActivity, mCustomEnterAnim)); | ||
| 206 | + } | ||
| 207 | + | ||
| 208 | + if (mFirstCreateView) { | ||
| 209 | + mFirstCreateView = false; | ||
| 210 | + } | ||
| 211 | + } | ||
| 212 | + | ||
| 213 | + public void onResume() { | ||
| 214 | + getVisibleDelegate().onResume(); | ||
| 215 | + } | ||
| 216 | + | ||
| 217 | + public void onPause() { | ||
| 218 | + getVisibleDelegate().onPause(); | ||
| 219 | + } | ||
| 220 | + | ||
| 221 | + public void onDestroyView() { | ||
| 222 | + mSupport.getSupportDelegate().mFragmentClickable = true; | ||
| 223 | + getVisibleDelegate().onDestroyView(); | ||
| 224 | + getHandler().removeCallbacks(mNotifyEnterAnimEndRunnable); | ||
| 225 | + } | ||
| 226 | + | ||
| 227 | + public void onDestroy() { | ||
| 228 | + mTransactionDelegate.handleResultRecord(mFragment); | ||
| 229 | + } | ||
| 230 | + | ||
| 231 | + public void onHiddenChanged(boolean hidden) { | ||
| 232 | + getVisibleDelegate().onHiddenChanged(hidden); | ||
| 233 | + } | ||
| 234 | + | ||
| 235 | + public void setUserVisibleHint(boolean isVisibleToUser) { | ||
| 236 | + getVisibleDelegate().setUserVisibleHint(isVisibleToUser); | ||
| 237 | + } | ||
| 238 | + | ||
| 239 | + /** | ||
| 240 | + * Causes the Runnable r to be added to the action queue. | ||
| 241 | + * <p> | ||
| 242 | + * The runnable will be run after all the previous action has been run. | ||
| 243 | + * <p> | ||
| 244 | + * 前面的事务全部执行后 执行该Action | ||
| 245 | + * | ||
| 246 | + * @deprecated Use {@link #post(Runnable)} instead. | ||
| 247 | + */ | ||
| 248 | + @Deprecated | ||
| 249 | + public void enqueueAction(Runnable runnable) { | ||
| 250 | + post(runnable); | ||
| 251 | + } | ||
| 252 | + | ||
| 253 | + /** | ||
| 254 | + * Causes the Runnable r to be added to the action queue. | ||
| 255 | + * <p> | ||
| 256 | + * The runnable will be run after all the previous action has been run. | ||
| 257 | + * <p> | ||
| 258 | + * 前面的事务全部执行后 执行该Action | ||
| 259 | + */ | ||
| 260 | + public void post(final Runnable runnable) { | ||
| 261 | + mTransactionDelegate.post(runnable); | ||
| 262 | + } | ||
| 263 | + | ||
| 264 | + /** | ||
| 265 | + * Called when the enter-animation end. | ||
| 266 | + * 入栈动画 结束时,回调 | ||
| 267 | + */ | ||
| 268 | + public void onEnterAnimationEnd(Bundle savedInstanceState) { | ||
| 269 | + } | ||
| 270 | + | ||
| 271 | + /** | ||
| 272 | + * Lazy initial,Called when fragment is first visible. | ||
| 273 | + * <p> | ||
| 274 | + * 同级下的 懒加载 + ViewPager下的懒加载 的结合回调方法 | ||
| 275 | + */ | ||
| 276 | + public void onLazyInitView(@Nullable Bundle savedInstanceState) { | ||
| 277 | + } | ||
| 278 | + | ||
| 279 | + /** | ||
| 280 | + * Called when the fragment is visible. | ||
| 281 | + * <p> | ||
| 282 | + * 当Fragment对用户可见时回调 | ||
| 283 | + * <p> | ||
| 284 | + * Is the combination of [onHiddenChanged() + onResume()/onPause() + setUserVisibleHint()] | ||
| 285 | + */ | ||
| 286 | + public void onSupportVisible() { | ||
| 287 | + } | ||
| 288 | + | ||
| 289 | + /** | ||
| 290 | + * Called when the fragment is invivible. | ||
| 291 | + * <p> | ||
| 292 | + * Is the combination of [onHiddenChanged() + onResume()/onPause() + setUserVisibleHint()] | ||
| 293 | + */ | ||
| 294 | + public void onSupportInvisible() { | ||
| 295 | + } | ||
| 296 | + | ||
| 297 | + /** | ||
| 298 | + * Return true if the fragment has been supportVisible. | ||
| 299 | + */ | ||
| 300 | + final public boolean isSupportVisible() { | ||
| 301 | + return getVisibleDelegate().isSupportVisible(); | ||
| 302 | + } | ||
| 303 | + | ||
| 304 | + /** | ||
| 305 | + * Set fragment animation with a higher priority than the ISupportActivity | ||
| 306 | + * 设定当前Fragmemt动画,优先级比在ISupportActivity里高 | ||
| 307 | + */ | ||
| 308 | + public FragmentAnimator onCreateFragmentAnimator() { | ||
| 309 | + return mSupport.getFragmentAnimator(); | ||
| 310 | + } | ||
| 311 | + | ||
| 312 | + /** | ||
| 313 | + * 获取设置的全局动画 | ||
| 314 | + * | ||
| 315 | + * @return FragmentAnimator | ||
| 316 | + */ | ||
| 317 | + public FragmentAnimator getFragmentAnimator() { | ||
| 318 | + if (mSupport == null) | ||
| 319 | + throw new RuntimeException("Fragment has not been attached to Activity!"); | ||
| 320 | + | ||
| 321 | + if (mFragmentAnimator == null) { | ||
| 322 | + mFragmentAnimator = mSupportF.onCreateFragmentAnimator(); | ||
| 323 | + if (mFragmentAnimator == null) { | ||
| 324 | + mFragmentAnimator = mSupport.getFragmentAnimator(); | ||
| 325 | + } | ||
| 326 | + } | ||
| 327 | + return mFragmentAnimator; | ||
| 328 | + } | ||
| 329 | + | ||
| 330 | + /** | ||
| 331 | + * Set the fragment animation. | ||
| 332 | + */ | ||
| 333 | + public void setFragmentAnimator(FragmentAnimator fragmentAnimator) { | ||
| 334 | + this.mFragmentAnimator = fragmentAnimator; | ||
| 335 | + if (mAnimHelper != null) { | ||
| 336 | + mAnimHelper.notifyChanged(fragmentAnimator); | ||
| 337 | + } | ||
| 338 | + mAnimByActivity = false; | ||
| 339 | + } | ||
| 340 | + | ||
| 341 | + /** | ||
| 342 | + * 类似 {@link Activity#setResult(int, Intent)} | ||
| 343 | + * <p> | ||
| 344 | + * Similar to {@link Activity#setResult(int, Intent)} | ||
| 345 | + * | ||
| 346 | + * @see #startForResult(ISupportFragment, int) | ||
| 347 | + */ | ||
| 348 | + public void setFragmentResult(int resultCode, Bundle bundle) { | ||
| 349 | + Bundle args = mFragment.getArguments(); | ||
| 350 | + if (args == null || !args.containsKey(TransactionDelegate.FRAGMENTATION_ARG_RESULT_RECORD)) { | ||
| 351 | + return; | ||
| 352 | + } | ||
| 353 | + | ||
| 354 | + ResultRecord resultRecord = args.getParcelable(TransactionDelegate.FRAGMENTATION_ARG_RESULT_RECORD); | ||
| 355 | + if (resultRecord != null) { | ||
| 356 | + resultRecord.resultCode = resultCode; | ||
| 357 | + resultRecord.resultBundle = bundle; | ||
| 358 | + } | ||
| 359 | + } | ||
| 360 | + | ||
| 361 | + /** | ||
| 362 | + * 类似 {@link Activity#onActivityResult(int, int, Intent)} | ||
| 363 | + * <p> | ||
| 364 | + * Similar to {@link Activity#onActivityResult(int, int, Intent)} | ||
| 365 | + * | ||
| 366 | + * @see #startForResult(ISupportFragment, int) | ||
| 367 | + */ | ||
| 368 | + public void onFragmentResult(int requestCode, int resultCode, Bundle data) { | ||
| 369 | + } | ||
| 370 | + | ||
| 371 | + /** | ||
| 372 | + * 在start(TargetFragment,LaunchMode)时,启动模式为SingleTask/SingleTop, 回调TargetFragment的该方法 | ||
| 373 | + * 类似 {@link Activity#onNewIntent(Intent)} | ||
| 374 | + * <p> | ||
| 375 | + * Similar to {@link Activity#onNewIntent(Intent)} | ||
| 376 | + * | ||
| 377 | + * @param args putNewBundle(Bundle newBundle) | ||
| 378 | + * @see #start(ISupportFragment, int) | ||
| 379 | + */ | ||
| 380 | + public void onNewBundle(Bundle args) { | ||
| 381 | + } | ||
| 382 | + | ||
| 383 | + /** | ||
| 384 | + * 添加NewBundle,用于启动模式为SingleTask/SingleTop时 | ||
| 385 | + * | ||
| 386 | + * @see #start(ISupportFragment, int) | ||
| 387 | + */ | ||
| 388 | + public void putNewBundle(Bundle newBundle) { | ||
| 389 | + this.mNewBundle = newBundle; | ||
| 390 | + } | ||
| 391 | + | ||
| 392 | + /** | ||
| 393 | + * Back Event | ||
| 394 | + * | ||
| 395 | + * @return false则继续向上传递, true则消费掉该事件 | ||
| 396 | + */ | ||
| 397 | + public boolean onBackPressedSupport() { | ||
| 398 | + return false; | ||
| 399 | + } | ||
| 400 | + | ||
| 401 | + /**********************************************************************************************/ | ||
| 402 | + | ||
| 403 | + /** | ||
| 404 | + * 隐藏软键盘 | ||
| 405 | + */ | ||
| 406 | + public void hideSoftInput() { | ||
| 407 | + Activity activity = mFragment.getActivity(); | ||
| 408 | + if (activity == null) return; | ||
| 409 | + View view = activity.getWindow().getDecorView(); | ||
| 410 | + SupportHelper.hideSoftInput(view); | ||
| 411 | + } | ||
| 412 | + | ||
| 413 | + /** | ||
| 414 | + * 显示软键盘,调用该方法后,会在onPause时自动隐藏软键盘 | ||
| 415 | + */ | ||
| 416 | + public void showSoftInput(View view) { | ||
| 417 | + SupportHelper.showSoftInput(view); | ||
| 418 | + } | ||
| 419 | + | ||
| 420 | + | ||
| 421 | + /** | ||
| 422 | + * 加载根Fragment, 即Activity内的第一个Fragment 或 Fragment内的第一个子Fragment | ||
| 423 | + */ | ||
| 424 | + public void loadRootFragment(int containerId, ISupportFragment toFragment) { | ||
| 425 | + loadRootFragment(containerId, toFragment, true, false); | ||
| 426 | + } | ||
| 427 | + | ||
| 428 | + public void loadRootFragment(int containerId, ISupportFragment toFragment, boolean addToBackStack, boolean allowAnim) { | ||
| 429 | + mTransactionDelegate.loadRootTransaction(getChildFragmentManager(), containerId, toFragment, addToBackStack, allowAnim); | ||
| 430 | + } | ||
| 431 | + | ||
| 432 | + /** | ||
| 433 | + * 加载多个同级根Fragment,类似Wechat, QQ主页的场景 | ||
| 434 | + */ | ||
| 435 | + public void loadMultipleRootFragment(int containerId, int showPosition, ISupportFragment... toFragments) { | ||
| 436 | + mTransactionDelegate.loadMultipleRootTransaction(getChildFragmentManager(), containerId, showPosition, toFragments); | ||
| 437 | + } | ||
| 438 | + | ||
| 439 | + /** | ||
| 440 | + * show一个Fragment,hide其他同栈所有Fragment | ||
| 441 | + * 使用该方法时,要确保同级栈内无多余的Fragment,(只有通过loadMultipleRootFragment()载入的Fragment) | ||
| 442 | + * <p> | ||
| 443 | + * 建议使用更明确的{@link #showHideFragment(ISupportFragment, ISupportFragment)} | ||
| 444 | + */ | ||
| 445 | + public void showHideFragment(ISupportFragment showFragment) { | ||
| 446 | + showHideFragment(showFragment, null); | ||
| 447 | + } | ||
| 448 | + | ||
| 449 | + /** | ||
| 450 | + * show一个Fragment,hide一个Fragment ; 主要用于类似微信主页那种 切换tab的情况 | ||
| 451 | + */ | ||
| 452 | + public void showHideFragment(ISupportFragment showFragment, ISupportFragment hideFragment) { | ||
| 453 | + mTransactionDelegate.showHideFragment(getChildFragmentManager(), showFragment, hideFragment); | ||
| 454 | + } | ||
| 455 | + | ||
| 456 | + public void start(ISupportFragment toFragment) { | ||
| 457 | + start(toFragment, ISupportFragment.STANDARD); | ||
| 458 | + } | ||
| 459 | + | ||
| 460 | + /** | ||
| 461 | + * @param launchMode Similar to Activity's LaunchMode. | ||
| 462 | + */ | ||
| 463 | + public void start(final ISupportFragment toFragment, @ISupportFragment.LaunchMode int launchMode) { | ||
| 464 | + mTransactionDelegate.dispatchStartTransaction(mFragment.getFragmentManager(), mSupportF, toFragment, 0, launchMode, TransactionDelegate.TYPE_ADD); | ||
| 465 | + } | ||
| 466 | + | ||
| 467 | + /** | ||
| 468 | + * Launch an fragment for which you would like a result when it poped. | ||
| 469 | + */ | ||
| 470 | + public void startForResult(ISupportFragment toFragment, int requestCode) { | ||
| 471 | + mTransactionDelegate.dispatchStartTransaction(mFragment.getFragmentManager(), mSupportF, toFragment, requestCode, ISupportFragment.STANDARD, TransactionDelegate.TYPE_ADD_RESULT); | ||
| 472 | + } | ||
| 473 | + | ||
| 474 | + /** | ||
| 475 | + * Start the target Fragment and pop itself | ||
| 476 | + */ | ||
| 477 | + public void startWithPop(ISupportFragment toFragment) { | ||
| 478 | + mTransactionDelegate.startWithPop(mFragment.getFragmentManager(), mSupportF, toFragment); | ||
| 479 | + } | ||
| 480 | + | ||
| 481 | + public void startWithPopTo(ISupportFragment toFragment, Class<?> targetFragmentClass, boolean includeTargetFragment) { | ||
| 482 | + mTransactionDelegate.startWithPopTo(mFragment.getFragmentManager(), mSupportF, toFragment, targetFragmentClass.getName(), includeTargetFragment); | ||
| 483 | + } | ||
| 484 | + | ||
| 485 | + public void replaceFragment(ISupportFragment toFragment, boolean addToBackStack) { | ||
| 486 | + mTransactionDelegate.dispatchStartTransaction(mFragment.getFragmentManager(), mSupportF, toFragment, 0, ISupportFragment.STANDARD, addToBackStack ? TransactionDelegate.TYPE_REPLACE : TransactionDelegate.TYPE_REPLACE_DONT_BACK); | ||
| 487 | + } | ||
| 488 | + | ||
| 489 | + public void startChild(ISupportFragment toFragment) { | ||
| 490 | + startChild(toFragment, ISupportFragment.STANDARD); | ||
| 491 | + } | ||
| 492 | + | ||
| 493 | + public void startChild(final ISupportFragment toFragment, @ISupportFragment.LaunchMode int launchMode) { | ||
| 494 | + mTransactionDelegate.dispatchStartTransaction(getChildFragmentManager(), getTopFragment(), toFragment, 0, launchMode, TransactionDelegate.TYPE_ADD); | ||
| 495 | + } | ||
| 496 | + | ||
| 497 | + public void startChildForResult(ISupportFragment toFragment, int requestCode) { | ||
| 498 | + mTransactionDelegate.dispatchStartTransaction(getChildFragmentManager(), getTopFragment(), toFragment, requestCode, ISupportFragment.STANDARD, TransactionDelegate.TYPE_ADD_RESULT); | ||
| 499 | + } | ||
| 500 | + | ||
| 501 | + public void startChildWithPop(ISupportFragment toFragment) { | ||
| 502 | + mTransactionDelegate.startWithPop(getChildFragmentManager(), getTopFragment(), toFragment); | ||
| 503 | + } | ||
| 504 | + | ||
| 505 | + public void replaceChildFragment(ISupportFragment toFragment, boolean addToBackStack) { | ||
| 506 | + mTransactionDelegate.dispatchStartTransaction(getChildFragmentManager(), getTopFragment(), toFragment, 0, ISupportFragment.STANDARD, addToBackStack ? TransactionDelegate.TYPE_REPLACE : TransactionDelegate.TYPE_REPLACE_DONT_BACK); | ||
| 507 | + } | ||
| 508 | + | ||
| 509 | + public void pop() { | ||
| 510 | + mTransactionDelegate.pop(mFragment.getFragmentManager()); | ||
| 511 | + } | ||
| 512 | + | ||
| 513 | + /** | ||
| 514 | + * Pop the child fragment. | ||
| 515 | + */ | ||
| 516 | + public void popChild() { | ||
| 517 | + mTransactionDelegate.pop(getChildFragmentManager()); | ||
| 518 | + } | ||
| 519 | + | ||
| 520 | + /** | ||
| 521 | + * Pop the last fragment transition from the manager's fragment | ||
| 522 | + * back stack. | ||
| 523 | + * <p> | ||
| 524 | + * 出栈到目标fragment | ||
| 525 | + * | ||
| 526 | + * @param targetFragmentClass 目标fragment | ||
| 527 | + * @param includeTargetFragment 是否包含该fragment | ||
| 528 | + */ | ||
| 529 | + public void popTo(Class<?> targetFragmentClass, boolean includeTargetFragment) { | ||
| 530 | + popTo(targetFragmentClass, includeTargetFragment, null); | ||
| 531 | + } | ||
| 532 | + | ||
| 533 | + /** | ||
| 534 | + * If you want to begin another FragmentTransaction immediately after popTo(), use this method. | ||
| 535 | + * 如果你想在出栈后, 立刻进行FragmentTransaction操作,请使用该方法 | ||
| 536 | + */ | ||
| 537 | + public void popTo(Class<?> targetFragmentClass, boolean includeTargetFragment, Runnable afterPopTransactionRunnable) { | ||
| 538 | + popTo(targetFragmentClass, includeTargetFragment, afterPopTransactionRunnable, TransactionDelegate.DEFAULT_POPTO_ANIM); | ||
| 539 | + } | ||
| 540 | + | ||
| 541 | + public void popTo(Class<?> targetFragmentClass, boolean includeTargetFragment, Runnable afterPopTransactionRunnable, int popAnim) { | ||
| 542 | + mTransactionDelegate.popTo(targetFragmentClass.getName(), includeTargetFragment, afterPopTransactionRunnable, mFragment.getFragmentManager(), popAnim); | ||
| 543 | + } | ||
| 544 | + | ||
| 545 | + public void popToChild(Class<?> targetFragmentClass, boolean includeTargetFragment) { | ||
| 546 | + popToChild(targetFragmentClass, includeTargetFragment, null); | ||
| 547 | + } | ||
| 548 | + | ||
| 549 | + public void popToChild(Class<?> targetFragmentClass, boolean includeTargetFragment, Runnable afterPopTransactionRunnable) { | ||
| 550 | + popToChild(targetFragmentClass, includeTargetFragment, afterPopTransactionRunnable, TransactionDelegate.DEFAULT_POPTO_ANIM); | ||
| 551 | + } | ||
| 552 | + | ||
| 553 | + public void popToChild(Class<?> targetFragmentClass, boolean includeTargetFragment, Runnable afterPopTransactionRunnable, int popAnim) { | ||
| 554 | + mTransactionDelegate.popTo(targetFragmentClass.getName(), includeTargetFragment, afterPopTransactionRunnable, getChildFragmentManager(), popAnim); | ||
| 555 | + } | ||
| 556 | + | ||
| 557 | + public void popQuiet() { | ||
| 558 | + mTransactionDelegate.popQuiet(mFragment.getFragmentManager(), mFragment); | ||
| 559 | + } | ||
| 560 | + | ||
| 561 | + private FragmentManager getChildFragmentManager() { | ||
| 562 | + return mFragment.getChildFragmentManager(); | ||
| 563 | + } | ||
| 564 | + | ||
| 565 | + private ISupportFragment getTopFragment() { | ||
| 566 | + return SupportHelper.getTopFragment(getChildFragmentManager()); | ||
| 567 | + } | ||
| 568 | + | ||
| 569 | + private void fixAnimationListener(Animation enterAnim) { | ||
| 570 | + // AnimationListener is not reliable. | ||
| 571 | + getHandler().postDelayed(mNotifyEnterAnimEndRunnable, enterAnim.getDuration()); | ||
| 572 | + mSupport.getSupportDelegate().mFragmentClickable = true; | ||
| 573 | + | ||
| 574 | + if (mEnterAnimListener != null) { | ||
| 575 | + getHandler().post(new Runnable() { | ||
| 576 | + @Override | ||
| 577 | + public void run() { | ||
| 578 | + mEnterAnimListener.onEnterAnimStart(); | ||
| 579 | + mEnterAnimListener = null; | ||
| 580 | + } | ||
| 581 | + }); | ||
| 582 | + } | ||
| 583 | + } | ||
| 584 | + | ||
| 585 | + private Runnable mNotifyEnterAnimEndRunnable = new Runnable() { | ||
| 586 | + @Override | ||
| 587 | + public void run() { | ||
| 588 | + if (mFragment == null) return; | ||
| 589 | + mSupportF.onEnterAnimationEnd(mSaveInstanceState); | ||
| 590 | + | ||
| 591 | + if (mRootViewClickable) return; | ||
| 592 | + final View view = mFragment.getView(); | ||
| 593 | + if (view == null) return; | ||
| 594 | + ISupportFragment preFragment = SupportHelper.getPreFragment(mFragment); | ||
| 595 | + if (preFragment == null) return; | ||
| 596 | + | ||
| 597 | + long prePopExitDuration = preFragment.getSupportDelegate().getPopExitAnimDuration(); | ||
| 598 | + long enterDuration = getEnterAnimDuration(); | ||
| 599 | + | ||
| 600 | + mHandler.postDelayed(new Runnable() { | ||
| 601 | + @Override | ||
| 602 | + public void run() { | ||
| 603 | + view.setClickable(false); | ||
| 604 | + } | ||
| 605 | + }, prePopExitDuration - enterDuration); | ||
| 606 | + } | ||
| 607 | + }; | ||
| 608 | + | ||
| 609 | + private void compatSharedElements() { | ||
| 610 | + notifyEnterAnimEnd(); | ||
| 611 | + } | ||
| 612 | + | ||
| 613 | + public void setBackground(View view) { | ||
| 614 | + if ((mFragment.getTag() != null && mFragment.getTag().startsWith("android:switcher:")) || | ||
| 615 | + mRootStatus != STATUS_UN_ROOT || | ||
| 616 | + view.getBackground() != null) { | ||
| 617 | + return; | ||
| 618 | + } | ||
| 619 | + | ||
| 620 | + int defaultBg = mSupport.getSupportDelegate().getDefaultFragmentBackground(); | ||
| 621 | + if (defaultBg == 0) { | ||
| 622 | + int background = getWindowBackground(); | ||
| 623 | + view.setBackgroundResource(background); | ||
| 624 | + } else { | ||
| 625 | + view.setBackgroundResource(defaultBg); | ||
| 626 | + } | ||
| 627 | + } | ||
| 628 | + | ||
| 629 | + private int getWindowBackground() { | ||
| 630 | + TypedArray a = _mActivity.getTheme().obtainStyledAttributes(new int[]{ | ||
| 631 | + android.R.attr.windowBackground | ||
| 632 | + }); | ||
| 633 | + int background = a.getResourceId(0, 0); | ||
| 634 | + a.recycle(); | ||
| 635 | + return background; | ||
| 636 | + } | ||
| 637 | + | ||
| 638 | + private void notifyEnterAnimEnd() { | ||
| 639 | + getHandler().post(mNotifyEnterAnimEndRunnable); | ||
| 640 | + mSupport.getSupportDelegate().mFragmentClickable = true; | ||
| 641 | + } | ||
| 642 | + | ||
| 643 | + private Handler getHandler() { | ||
| 644 | + if (mHandler == null) { | ||
| 645 | + mHandler = new Handler(Looper.getMainLooper()); | ||
| 646 | + } | ||
| 647 | + return mHandler; | ||
| 648 | + } | ||
| 649 | + | ||
| 650 | + public VisibleDelegate getVisibleDelegate() { | ||
| 651 | + if (mVisibleDelegate == null) { | ||
| 652 | + mVisibleDelegate = new VisibleDelegate(mSupportF); | ||
| 653 | + } | ||
| 654 | + return mVisibleDelegate; | ||
| 655 | + } | ||
| 656 | + | ||
| 657 | + public FragmentActivity getActivity() { | ||
| 658 | + return _mActivity; | ||
| 659 | + } | ||
| 660 | + | ||
| 661 | + private Animation getEnterAnim() { | ||
| 662 | + if (mCustomEnterAnim == Integer.MIN_VALUE) { | ||
| 663 | + if (mAnimHelper != null && mAnimHelper.enterAnim != null) { | ||
| 664 | + return mAnimHelper.enterAnim; | ||
| 665 | + } | ||
| 666 | + } else { | ||
| 667 | + try { | ||
| 668 | + return AnimationUtils.loadAnimation(_mActivity, mCustomEnterAnim); | ||
| 669 | + } catch (Exception e) { | ||
| 670 | + e.printStackTrace(); | ||
| 671 | + } | ||
| 672 | + } | ||
| 673 | + return null; | ||
| 674 | + } | ||
| 675 | + | ||
| 676 | + private long getEnterAnimDuration() { | ||
| 677 | + Animation enter = getEnterAnim(); | ||
| 678 | + if (enter != null) { | ||
| 679 | + return enter.getDuration(); | ||
| 680 | + } | ||
| 681 | + return NOT_FOUND_ANIM_TIME; | ||
| 682 | + } | ||
| 683 | + | ||
| 684 | + public long getExitAnimDuration() { | ||
| 685 | + if (mCustomExitAnim == Integer.MIN_VALUE) { | ||
| 686 | + if (mAnimHelper != null && mAnimHelper.exitAnim != null) { | ||
| 687 | + return mAnimHelper.exitAnim.getDuration(); | ||
| 688 | + } | ||
| 689 | + } else { | ||
| 690 | + try { | ||
| 691 | + return AnimationUtils.loadAnimation(_mActivity, mCustomExitAnim).getDuration(); | ||
| 692 | + } catch (Exception e) { | ||
| 693 | + e.printStackTrace(); | ||
| 694 | + } | ||
| 695 | + | ||
| 696 | + } | ||
| 697 | + return NOT_FOUND_ANIM_TIME; | ||
| 698 | + } | ||
| 699 | + | ||
| 700 | + private long getPopExitAnimDuration() { | ||
| 701 | + if (mCustomPopExitAnim == Integer.MIN_VALUE) { | ||
| 702 | + if (mAnimHelper != null && mAnimHelper.popExitAnim != null) { | ||
| 703 | + return mAnimHelper.popExitAnim.getDuration(); | ||
| 704 | + } | ||
| 705 | + } else { | ||
| 706 | + try { | ||
| 707 | + return AnimationUtils.loadAnimation(_mActivity, mCustomPopExitAnim).getDuration(); | ||
| 708 | + } catch (Exception e) { | ||
| 709 | + e.printStackTrace(); | ||
| 710 | + } | ||
| 711 | + | ||
| 712 | + } | ||
| 713 | + return NOT_FOUND_ANIM_TIME; | ||
| 714 | + } | ||
| 715 | + | ||
| 716 | + @Nullable | ||
| 717 | + Animation getExitAnim() { | ||
| 718 | + if (mCustomExitAnim == Integer.MIN_VALUE) { | ||
| 719 | + if (mAnimHelper != null && mAnimHelper.exitAnim != null) { | ||
| 720 | + return mAnimHelper.exitAnim; | ||
| 721 | + } | ||
| 722 | + } else { | ||
| 723 | + try { | ||
| 724 | + return AnimationUtils.loadAnimation(_mActivity, mCustomExitAnim); | ||
| 725 | + } catch (Exception e) { | ||
| 726 | + e.printStackTrace(); | ||
| 727 | + } | ||
| 728 | + } | ||
| 729 | + return null; | ||
| 730 | + } | ||
| 731 | + | ||
| 732 | + interface EnterAnimListener { | ||
| 733 | + void onEnterAnimStart(); | ||
| 734 | + } | ||
| 735 | +} | ||
| 0 | \ No newline at end of file | 736 | \ No newline at end of file |
core/base/src/main/java/com/me/yokeyword/fragmentation/SupportHelper.java
0 → 100644
| 1 | +package com.me.yokeyword.fragmentation; | ||
| 2 | + | ||
| 3 | +import android.content.Context; | ||
| 4 | +import android.view.View; | ||
| 5 | +import android.view.inputmethod.InputMethodManager; | ||
| 6 | + | ||
| 7 | +import androidx.fragment.app.Fragment; | ||
| 8 | +import androidx.fragment.app.FragmentManager; | ||
| 9 | +import androidx.fragment.app.FragmentationMagician; | ||
| 10 | + | ||
| 11 | +import java.util.ArrayList; | ||
| 12 | +import java.util.List; | ||
| 13 | + | ||
| 14 | +/** | ||
| 15 | + * Created by YoKey on 17/6/13. | ||
| 16 | + */ | ||
| 17 | + | ||
| 18 | +public class SupportHelper { | ||
| 19 | + private static final long SHOW_SPACE = 200L; | ||
| 20 | + | ||
| 21 | + private SupportHelper() { | ||
| 22 | + } | ||
| 23 | + | ||
| 24 | + /** | ||
| 25 | + * 显示软键盘 | ||
| 26 | + */ | ||
| 27 | + public static void showSoftInput(final View view) { | ||
| 28 | + if (view == null || view.getContext() == null) return; | ||
| 29 | + final InputMethodManager imm = (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); | ||
| 30 | + view.requestFocus(); | ||
| 31 | + view.postDelayed(new Runnable() { | ||
| 32 | + @Override | ||
| 33 | + public void run() { | ||
| 34 | + imm.showSoftInput(view, InputMethodManager.SHOW_FORCED); | ||
| 35 | + } | ||
| 36 | + }, SHOW_SPACE); | ||
| 37 | + } | ||
| 38 | + | ||
| 39 | + /** | ||
| 40 | + * 隐藏软键盘 | ||
| 41 | + */ | ||
| 42 | + public static void hideSoftInput(View view) { | ||
| 43 | + if (view == null || view.getContext() == null) return; | ||
| 44 | + InputMethodManager imm = (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); | ||
| 45 | + imm.hideSoftInputFromWindow(view.getWindowToken(), 0); | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | + /** | ||
| 49 | + * 显示栈视图dialog,调试时使用 | ||
| 50 | + */ | ||
| 51 | + public static void showFragmentStackHierarchyView(ISupportActivity support) { | ||
| 52 | + support.getSupportDelegate().showFragmentStackHierarchyView(); | ||
| 53 | + } | ||
| 54 | + | ||
| 55 | + /** | ||
| 56 | + * 显示栈视图日志,调试时使用 | ||
| 57 | + */ | ||
| 58 | + public static void logFragmentStackHierarchy(ISupportActivity support, String TAG) { | ||
| 59 | + support.getSupportDelegate().logFragmentStackHierarchy(TAG); | ||
| 60 | + } | ||
| 61 | + | ||
| 62 | + /** | ||
| 63 | + * 获得栈顶SupportFragment | ||
| 64 | + */ | ||
| 65 | + public static ISupportFragment getTopFragment(FragmentManager fragmentManager) { | ||
| 66 | + return getTopFragment(fragmentManager, 0); | ||
| 67 | + } | ||
| 68 | + | ||
| 69 | + public static ISupportFragment getTopFragment(FragmentManager fragmentManager, int containerId) { | ||
| 70 | + List<Fragment> fragmentList = FragmentationMagician.getActiveFragments(fragmentManager); | ||
| 71 | + if (fragmentList == null) return null; | ||
| 72 | + | ||
| 73 | + for (int i = fragmentList.size() - 1; i >= 0; i--) { | ||
| 74 | + Fragment fragment = fragmentList.get(i); | ||
| 75 | + if (fragment instanceof ISupportFragment) { | ||
| 76 | + ISupportFragment iFragment = (ISupportFragment) fragment; | ||
| 77 | + if (containerId == 0) return iFragment; | ||
| 78 | + | ||
| 79 | + if (containerId == iFragment.getSupportDelegate().mContainerId) { | ||
| 80 | + return iFragment; | ||
| 81 | + } | ||
| 82 | + } | ||
| 83 | + } | ||
| 84 | + return null; | ||
| 85 | + } | ||
| 86 | + | ||
| 87 | + /** | ||
| 88 | + * 获取目标Fragment的前一个SupportFragment | ||
| 89 | + * | ||
| 90 | + * @param fragment 目标Fragment | ||
| 91 | + */ | ||
| 92 | + public static ISupportFragment getPreFragment(Fragment fragment) { | ||
| 93 | + FragmentManager fragmentManager = fragment.getFragmentManager(); | ||
| 94 | + if (fragmentManager == null) return null; | ||
| 95 | + | ||
| 96 | + List<Fragment> fragmentList = FragmentationMagician.getActiveFragments(fragmentManager); | ||
| 97 | + if (fragmentList == null) return null; | ||
| 98 | + | ||
| 99 | + int index = fragmentList.indexOf(fragment); | ||
| 100 | + for (int i = index - 1; i >= 0; i--) { | ||
| 101 | + Fragment preFragment = fragmentList.get(i); | ||
| 102 | + if (preFragment instanceof ISupportFragment) { | ||
| 103 | + return (ISupportFragment) preFragment; | ||
| 104 | + } | ||
| 105 | + } | ||
| 106 | + return null; | ||
| 107 | + } | ||
| 108 | + | ||
| 109 | + /** | ||
| 110 | + * Same as fragmentManager.findFragmentByTag(fragmentClass.getName()); | ||
| 111 | + * find Fragment from FragmentStack | ||
| 112 | + */ | ||
| 113 | + @SuppressWarnings("unchecked") | ||
| 114 | + public static <T extends ISupportFragment> T findFragment(FragmentManager fragmentManager, Class<T> fragmentClass) { | ||
| 115 | + return findStackFragment(fragmentClass, null, fragmentManager); | ||
| 116 | + } | ||
| 117 | + | ||
| 118 | + /** | ||
| 119 | + * Same as fragmentManager.findFragmentByTag(fragmentTag); | ||
| 120 | + * <p> | ||
| 121 | + * find Fragment from FragmentStack | ||
| 122 | + */ | ||
| 123 | + @SuppressWarnings("unchecked") | ||
| 124 | + public static <T extends ISupportFragment> T findFragment(FragmentManager fragmentManager, String fragmentTag) { | ||
| 125 | + return findStackFragment(null, fragmentTag, fragmentManager); | ||
| 126 | + } | ||
| 127 | + | ||
| 128 | + /** | ||
| 129 | + * 从栈顶开始,寻找FragmentManager以及其所有子栈, 直到找到状态为show & userVisible的Fragment | ||
| 130 | + */ | ||
| 131 | + public static ISupportFragment getActiveFragment(FragmentManager fragmentManager) { | ||
| 132 | + return getActiveFragment(fragmentManager, null); | ||
| 133 | + } | ||
| 134 | + | ||
| 135 | + @SuppressWarnings("unchecked") | ||
| 136 | + static <T extends ISupportFragment> T findStackFragment(Class<T> fragmentClass, String toFragmentTag, FragmentManager fragmentManager) { | ||
| 137 | + Fragment fragment = null; | ||
| 138 | + | ||
| 139 | + if (toFragmentTag == null) { | ||
| 140 | + List<Fragment> fragmentList = FragmentationMagician.getActiveFragments(fragmentManager); | ||
| 141 | + if (fragmentList == null) return null; | ||
| 142 | + | ||
| 143 | + int sizeChildFrgList = fragmentList.size(); | ||
| 144 | + | ||
| 145 | + for (int i = sizeChildFrgList - 1; i >= 0; i--) { | ||
| 146 | + Fragment brotherFragment = fragmentList.get(i); | ||
| 147 | + if (brotherFragment instanceof ISupportFragment && brotherFragment.getClass().getName().equals(fragmentClass.getName())) { | ||
| 148 | + fragment = brotherFragment; | ||
| 149 | + break; | ||
| 150 | + } | ||
| 151 | + } | ||
| 152 | + } else { | ||
| 153 | + fragment = fragmentManager.findFragmentByTag(toFragmentTag); | ||
| 154 | + if (fragment == null) return null; | ||
| 155 | + } | ||
| 156 | + return (T) fragment; | ||
| 157 | + } | ||
| 158 | + | ||
| 159 | + private static ISupportFragment getActiveFragment(FragmentManager fragmentManager, ISupportFragment parentFragment) { | ||
| 160 | + List<Fragment> fragmentList = FragmentationMagician.getActiveFragments(fragmentManager); | ||
| 161 | + if (fragmentList == null) { | ||
| 162 | + return parentFragment; | ||
| 163 | + } | ||
| 164 | + for (int i = fragmentList.size() - 1; i >= 0; i--) { | ||
| 165 | + Fragment fragment = fragmentList.get(i); | ||
| 166 | + if (fragment instanceof ISupportFragment) { | ||
| 167 | + if (fragment.isResumed() && !fragment.isHidden() && fragment.getUserVisibleHint()) { | ||
| 168 | + return getActiveFragment(fragment.getChildFragmentManager(), (ISupportFragment) fragment); | ||
| 169 | + } | ||
| 170 | + } | ||
| 171 | + } | ||
| 172 | + return parentFragment; | ||
| 173 | + } | ||
| 174 | + | ||
| 175 | + /** | ||
| 176 | + * Get the topFragment from BackStack | ||
| 177 | + */ | ||
| 178 | + public static ISupportFragment getBackStackTopFragment(FragmentManager fragmentManager) { | ||
| 179 | + return getBackStackTopFragment(fragmentManager, 0); | ||
| 180 | + } | ||
| 181 | + | ||
| 182 | + /** | ||
| 183 | + * Get the topFragment from BackStack | ||
| 184 | + */ | ||
| 185 | + public static ISupportFragment getBackStackTopFragment(FragmentManager fragmentManager, int containerId) { | ||
| 186 | + int count = fragmentManager.getBackStackEntryCount(); | ||
| 187 | + | ||
| 188 | + for (int i = count - 1; i >= 0; i--) { | ||
| 189 | + FragmentManager.BackStackEntry entry = fragmentManager.getBackStackEntryAt(i); | ||
| 190 | + Fragment fragment = fragmentManager.findFragmentByTag(entry.getName()); | ||
| 191 | + if (fragment instanceof ISupportFragment) { | ||
| 192 | + ISupportFragment supportFragment = (ISupportFragment) fragment; | ||
| 193 | + if (containerId == 0) return supportFragment; | ||
| 194 | + | ||
| 195 | + if (containerId == supportFragment.getSupportDelegate().mContainerId) { | ||
| 196 | + return supportFragment; | ||
| 197 | + } | ||
| 198 | + } | ||
| 199 | + } | ||
| 200 | + return null; | ||
| 201 | + } | ||
| 202 | + | ||
| 203 | + @SuppressWarnings("unchecked") | ||
| 204 | + static <T extends ISupportFragment> T findBackStackFragment(Class<T> fragmentClass, String toFragmentTag, FragmentManager fragmentManager) { | ||
| 205 | + int count = fragmentManager.getBackStackEntryCount(); | ||
| 206 | + | ||
| 207 | + if (toFragmentTag == null) { | ||
| 208 | + toFragmentTag = fragmentClass.getName(); | ||
| 209 | + } | ||
| 210 | + | ||
| 211 | + for (int i = count - 1; i >= 0; i--) { | ||
| 212 | + FragmentManager.BackStackEntry entry = fragmentManager.getBackStackEntryAt(i); | ||
| 213 | + | ||
| 214 | + if (toFragmentTag.equals(entry.getName())) { | ||
| 215 | + Fragment fragment = fragmentManager.findFragmentByTag(entry.getName()); | ||
| 216 | + if (fragment instanceof ISupportFragment) { | ||
| 217 | + return (T) fragment; | ||
| 218 | + } | ||
| 219 | + } | ||
| 220 | + } | ||
| 221 | + return null; | ||
| 222 | + } | ||
| 223 | + | ||
| 224 | + static List<Fragment> getWillPopFragments(FragmentManager fm, String targetTag, boolean includeTarget) { | ||
| 225 | + Fragment target = fm.findFragmentByTag(targetTag); | ||
| 226 | + List<Fragment> willPopFragments = new ArrayList<>(); | ||
| 227 | + | ||
| 228 | + List<Fragment> fragmentList = FragmentationMagician.getActiveFragments(fm); | ||
| 229 | + if (fragmentList == null) return willPopFragments; | ||
| 230 | + | ||
| 231 | + int size = fragmentList.size(); | ||
| 232 | + | ||
| 233 | + int startIndex = -1; | ||
| 234 | + for (int i = size - 1; i >= 0; i--) { | ||
| 235 | + if (target == fragmentList.get(i)) { | ||
| 236 | + if (includeTarget) { | ||
| 237 | + startIndex = i; | ||
| 238 | + } else if (i + 1 < size) { | ||
| 239 | + startIndex = i + 1; | ||
| 240 | + } | ||
| 241 | + break; | ||
| 242 | + } | ||
| 243 | + } | ||
| 244 | + | ||
| 245 | + if (startIndex == -1) return willPopFragments; | ||
| 246 | + | ||
| 247 | + for (int i = size - 1; i >= startIndex; i--) { | ||
| 248 | + Fragment fragment = fragmentList.get(i); | ||
| 249 | + if (fragment != null && fragment.getView() != null) { | ||
| 250 | + willPopFragments.add(fragment); | ||
| 251 | + } | ||
| 252 | + } | ||
| 253 | + return willPopFragments; | ||
| 254 | + } | ||
| 255 | +} |
core/base/src/main/java/com/me/yokeyword/fragmentation/SwipeBackLayout.java
0 → 100644
| 1 | +package com.me.yokeyword.fragmentation; | ||
| 2 | + | ||
| 3 | +import android.content.Context; | ||
| 4 | +import android.content.res.TypedArray; | ||
| 5 | +import android.graphics.Canvas; | ||
| 6 | +import android.graphics.Rect; | ||
| 7 | +import android.graphics.drawable.Drawable; | ||
| 8 | +import android.util.AttributeSet; | ||
| 9 | +import android.util.DisplayMetrics; | ||
| 10 | +import android.view.MotionEvent; | ||
| 11 | +import android.view.View; | ||
| 12 | +import android.view.ViewGroup; | ||
| 13 | +import android.view.WindowManager; | ||
| 14 | +import android.widget.FrameLayout; | ||
| 15 | + | ||
| 16 | +import androidx.annotation.FloatRange; | ||
| 17 | +import androidx.annotation.IntDef; | ||
| 18 | +import androidx.core.view.ViewCompat; | ||
| 19 | +import androidx.customview.widget.ViewDragHelper; | ||
| 20 | +import androidx.fragment.app.Fragment; | ||
| 21 | +import androidx.fragment.app.FragmentActivity; | ||
| 22 | +import androidx.fragment.app.FragmentationMagician; | ||
| 23 | + | ||
| 24 | +import com.cnlive.strike.base.R; | ||
| 25 | +import com.me.yokeyword.fragmentation_swipeback.core.ISwipeBackActivity; | ||
| 26 | + | ||
| 27 | +import java.lang.annotation.Retention; | ||
| 28 | +import java.lang.annotation.RetentionPolicy; | ||
| 29 | +import java.lang.reflect.Field; | ||
| 30 | +import java.util.ArrayList; | ||
| 31 | +import java.util.List; | ||
| 32 | + | ||
| 33 | + | ||
| 34 | +/** | ||
| 35 | + * Thx https://github.com/ikew0ng/SwipeBackLayout. | ||
| 36 | + * <p> | ||
| 37 | + * Created by YoKey on 16/4/19. | ||
| 38 | + */ | ||
| 39 | +public class SwipeBackLayout extends FrameLayout { | ||
| 40 | + /** | ||
| 41 | + * Edge flag indicating that the left edge should be affected. | ||
| 42 | + */ | ||
| 43 | + public static final int EDGE_LEFT = ViewDragHelper.EDGE_LEFT; | ||
| 44 | + | ||
| 45 | + /** | ||
| 46 | + * Edge flag indicating that the right edge should be affected. | ||
| 47 | + */ | ||
| 48 | + public static final int EDGE_RIGHT = ViewDragHelper.EDGE_RIGHT; | ||
| 49 | + | ||
| 50 | + public static final int EDGE_ALL = EDGE_LEFT | EDGE_RIGHT; | ||
| 51 | + | ||
| 52 | + | ||
| 53 | + /** | ||
| 54 | + * A view is not currently being dragged or animating as a result of a | ||
| 55 | + * fling/snap. | ||
| 56 | + */ | ||
| 57 | + public static final int STATE_IDLE = ViewDragHelper.STATE_IDLE; | ||
| 58 | + | ||
| 59 | + /** | ||
| 60 | + * A view is currently being dragged. The position is currently changing as | ||
| 61 | + * a result of user input or simulated user input. | ||
| 62 | + */ | ||
| 63 | + public static final int STATE_DRAGGING = ViewDragHelper.STATE_DRAGGING; | ||
| 64 | + | ||
| 65 | + /** | ||
| 66 | + * A view is currently settling into place as a result of a fling or | ||
| 67 | + * predefined non-interactive motion. | ||
| 68 | + */ | ||
| 69 | + public static final int STATE_SETTLING = ViewDragHelper.STATE_SETTLING; | ||
| 70 | + | ||
| 71 | + /** | ||
| 72 | + * A view is currently drag finished. | ||
| 73 | + */ | ||
| 74 | + public static final int STATE_FINISHED = 3; | ||
| 75 | + | ||
| 76 | + private static final int DEFAULT_SCRIM_COLOR = 0x99000000; | ||
| 77 | + private static final float DEFAULT_PARALLAX = 0.33f; | ||
| 78 | + private static final int FULL_ALPHA = 255; | ||
| 79 | + private static final float DEFAULT_SCROLL_THRESHOLD = 0.4f; | ||
| 80 | + private static final int OVERSCROLL_DISTANCE = 10; | ||
| 81 | + | ||
| 82 | + private float mScrollFinishThreshold = DEFAULT_SCROLL_THRESHOLD; | ||
| 83 | + | ||
| 84 | + private ViewDragHelper mHelper; | ||
| 85 | + | ||
| 86 | + private float mScrollPercent; | ||
| 87 | + private float mScrimOpacity; | ||
| 88 | + | ||
| 89 | + private FragmentActivity mActivity; | ||
| 90 | + private View mContentView; | ||
| 91 | + private ISupportFragment mFragment; | ||
| 92 | + private Fragment mPreFragment; | ||
| 93 | + | ||
| 94 | + private Drawable mShadowLeft; | ||
| 95 | + private Drawable mShadowRight; | ||
| 96 | + private Rect mTmpRect = new Rect(); | ||
| 97 | + | ||
| 98 | + private int mEdgeFlag; | ||
| 99 | + private boolean mEnable = true; | ||
| 100 | + private int mCurrentSwipeOrientation; | ||
| 101 | + private float mParallaxOffset = DEFAULT_PARALLAX; | ||
| 102 | + | ||
| 103 | + private boolean mCallOnDestroyView; | ||
| 104 | + | ||
| 105 | + private boolean mInLayout; | ||
| 106 | + | ||
| 107 | + private int mContentLeft; | ||
| 108 | + private int mContentTop; | ||
| 109 | + private float mSwipeAlpha = 0.5f; | ||
| 110 | + | ||
| 111 | + /** | ||
| 112 | + * The set of listeners to be sent events through. | ||
| 113 | + */ | ||
| 114 | + private List<OnSwipeListener> mListeners; | ||
| 115 | + | ||
| 116 | + private Context mContext; | ||
| 117 | + | ||
| 118 | + public enum EdgeLevel { | ||
| 119 | + MAX, MIN, MED | ||
| 120 | + } | ||
| 121 | + | ||
| 122 | + public SwipeBackLayout(Context context) { | ||
| 123 | + this(context, null); | ||
| 124 | + } | ||
| 125 | + | ||
| 126 | + public SwipeBackLayout(Context context, AttributeSet attrs) { | ||
| 127 | + this(context, attrs, 0); | ||
| 128 | + } | ||
| 129 | + | ||
| 130 | + public SwipeBackLayout(Context context, AttributeSet attrs, int defStyleAttr) { | ||
| 131 | + super(context, attrs, defStyleAttr); | ||
| 132 | + this.mContext = context; | ||
| 133 | + init(); | ||
| 134 | + } | ||
| 135 | + | ||
| 136 | + private void init() { | ||
| 137 | + mHelper = ViewDragHelper.create(this, new ViewDragCallback()); | ||
| 138 | + setShadow(R.drawable.shadow_left, EDGE_LEFT); | ||
| 139 | + setEdgeOrientation(EDGE_LEFT); | ||
| 140 | + } | ||
| 141 | + | ||
| 142 | + /** | ||
| 143 | + * Get ViewDragHelper | ||
| 144 | + */ | ||
| 145 | + public ViewDragHelper getViewDragHelper() { | ||
| 146 | + return mHelper; | ||
| 147 | + } | ||
| 148 | + | ||
| 149 | + /** | ||
| 150 | + * 滑动中,上一个页面View的阴影透明度 | ||
| 151 | + * | ||
| 152 | + * @param alpha 0.0f:无阴影, 1.0f:较重的阴影, 默认:0.5f | ||
| 153 | + */ | ||
| 154 | + public void setSwipeAlpha(@FloatRange(from = 0.0f, to = 1.0f) float alpha) { | ||
| 155 | + this.mSwipeAlpha = alpha; | ||
| 156 | + } | ||
| 157 | + | ||
| 158 | + /** | ||
| 159 | + * Set scroll threshold, we will close the activity, when scrollPercent over | ||
| 160 | + * this value | ||
| 161 | + * | ||
| 162 | + * @param threshold | ||
| 163 | + */ | ||
| 164 | + public void setScrollThresHold(@FloatRange(from = 0.0f, to = 1.0f) float threshold) { | ||
| 165 | + if (threshold >= 1.0f || threshold <= 0) { | ||
| 166 | + throw new IllegalArgumentException("Threshold value should be between 0 and 1.0"); | ||
| 167 | + } | ||
| 168 | + mScrollFinishThreshold = threshold; | ||
| 169 | + } | ||
| 170 | + | ||
| 171 | + public void setParallaxOffset(float offset) { | ||
| 172 | + this.mParallaxOffset = offset; | ||
| 173 | + } | ||
| 174 | + | ||
| 175 | + /** | ||
| 176 | + * Enable edge tracking for the selected edges of the parent view. | ||
| 177 | + * The callback's {@link ViewDragHelper.Callback#onEdgeTouched(int, int)} and | ||
| 178 | + * {@link ViewDragHelper.Callback#onEdgeDragStarted(int, int)} methods will only be invoked | ||
| 179 | + * for edges for which edge tracking has been enabled. | ||
| 180 | + * | ||
| 181 | + * @param orientation Combination of edge flags describing the edges to watch | ||
| 182 | + * @see #EDGE_LEFT | ||
| 183 | + * @see #EDGE_RIGHT | ||
| 184 | + */ | ||
| 185 | + public void setEdgeOrientation(@EdgeOrientation int orientation) { | ||
| 186 | + mEdgeFlag = orientation; | ||
| 187 | + mHelper.setEdgeTrackingEnabled(orientation); | ||
| 188 | + | ||
| 189 | + if (orientation == EDGE_RIGHT || orientation == EDGE_ALL) { | ||
| 190 | + setShadow(R.drawable.shadow_right, EDGE_RIGHT); | ||
| 191 | + } | ||
| 192 | + } | ||
| 193 | + | ||
| 194 | + @IntDef({EDGE_LEFT, EDGE_RIGHT, EDGE_ALL}) | ||
| 195 | + @Retention(RetentionPolicy.SOURCE) | ||
| 196 | + public @interface EdgeOrientation { | ||
| 197 | + } | ||
| 198 | + | ||
| 199 | + /** | ||
| 200 | + * Set a drawable used for edge shadow. | ||
| 201 | + */ | ||
| 202 | + public void setShadow(Drawable shadow, int edgeFlag) { | ||
| 203 | + if ((edgeFlag & EDGE_LEFT) != 0) { | ||
| 204 | + mShadowLeft = shadow; | ||
| 205 | + } else if ((edgeFlag & EDGE_RIGHT) != 0) { | ||
| 206 | + mShadowRight = shadow; | ||
| 207 | + } | ||
| 208 | + invalidate(); | ||
| 209 | + } | ||
| 210 | + | ||
| 211 | + /** | ||
| 212 | + * Set a drawable used for edge shadow. | ||
| 213 | + */ | ||
| 214 | + public void setShadow(int resId, int edgeFlag) { | ||
| 215 | + setShadow(getResources().getDrawable(resId), edgeFlag); | ||
| 216 | + } | ||
| 217 | + | ||
| 218 | + /** | ||
| 219 | + * Add a callback to be invoked when a swipe event is sent to this view. | ||
| 220 | + * | ||
| 221 | + * @param listener the swipe listener to attach to this view | ||
| 222 | + */ | ||
| 223 | + public void addSwipeListener(OnSwipeListener listener) { | ||
| 224 | + if (mListeners == null) { | ||
| 225 | + mListeners = new ArrayList<>(); | ||
| 226 | + } | ||
| 227 | + mListeners.add(listener); | ||
| 228 | + } | ||
| 229 | + | ||
| 230 | + /** | ||
| 231 | + * Removes a listener from the set of listeners | ||
| 232 | + * | ||
| 233 | + * @param listener | ||
| 234 | + */ | ||
| 235 | + public void removeSwipeListener(OnSwipeListener listener) { | ||
| 236 | + if (mListeners == null) { | ||
| 237 | + return; | ||
| 238 | + } | ||
| 239 | + mListeners.remove(listener); | ||
| 240 | + } | ||
| 241 | + | ||
| 242 | + public interface OnSwipeListener { | ||
| 243 | + /** | ||
| 244 | + * Invoke when state change | ||
| 245 | + * | ||
| 246 | + * @param state flag to describe scroll state | ||
| 247 | + * @see #STATE_IDLE | ||
| 248 | + * @see #STATE_DRAGGING | ||
| 249 | + * @see #STATE_SETTLING | ||
| 250 | + * @see #STATE_FINISHED | ||
| 251 | + */ | ||
| 252 | + void onDragStateChange(int state); | ||
| 253 | + | ||
| 254 | + /** | ||
| 255 | + * Invoke when edge touched | ||
| 256 | + * | ||
| 257 | + * @param oritentationEdgeFlag edge flag describing the edge being touched | ||
| 258 | + * @see #EDGE_LEFT | ||
| 259 | + * @see #EDGE_RIGHT | ||
| 260 | + */ | ||
| 261 | + void onEdgeTouch(int oritentationEdgeFlag); | ||
| 262 | + | ||
| 263 | + /** | ||
| 264 | + * Invoke when scroll percent over the threshold for the first time | ||
| 265 | + * | ||
| 266 | + * @param scrollPercent scroll percent of this view | ||
| 267 | + */ | ||
| 268 | + void onDragScrolled(float scrollPercent); | ||
| 269 | + } | ||
| 270 | + | ||
| 271 | + @Override | ||
| 272 | + protected boolean drawChild(Canvas canvas, View child, long drawingTime) { | ||
| 273 | + boolean isDrawView = child == mContentView; | ||
| 274 | + boolean drawChild = super.drawChild(canvas, child, drawingTime); | ||
| 275 | + if (isDrawView && mScrimOpacity > 0 && mHelper.getViewDragState() != ViewDragHelper.STATE_IDLE) { | ||
| 276 | + drawShadow(canvas, child); | ||
| 277 | + drawScrim(canvas, child); | ||
| 278 | + } | ||
| 279 | + return drawChild; | ||
| 280 | + } | ||
| 281 | + | ||
| 282 | + private void drawShadow(Canvas canvas, View child) { | ||
| 283 | + final Rect childRect = mTmpRect; | ||
| 284 | + child.getHitRect(childRect); | ||
| 285 | + | ||
| 286 | + if ((mCurrentSwipeOrientation & EDGE_LEFT) != 0) { | ||
| 287 | + mShadowLeft.setBounds(childRect.left - mShadowLeft.getIntrinsicWidth(), childRect.top, childRect.left, childRect.bottom); | ||
| 288 | + mShadowLeft.setAlpha((int) (mScrimOpacity * FULL_ALPHA)); | ||
| 289 | + mShadowLeft.draw(canvas); | ||
| 290 | + } else if ((mCurrentSwipeOrientation & EDGE_RIGHT) != 0) { | ||
| 291 | + mShadowRight.setBounds(childRect.right, childRect.top, childRect.right + mShadowRight.getIntrinsicWidth(), childRect.bottom); | ||
| 292 | + mShadowRight.setAlpha((int) (mScrimOpacity * FULL_ALPHA)); | ||
| 293 | + mShadowRight.draw(canvas); | ||
| 294 | + } | ||
| 295 | + } | ||
| 296 | + | ||
| 297 | + private void drawScrim(Canvas canvas, View child) { | ||
| 298 | + final int baseAlpha = (DEFAULT_SCRIM_COLOR & 0xff000000) >>> 24; | ||
| 299 | + final int alpha = (int) (baseAlpha * mScrimOpacity * mSwipeAlpha); | ||
| 300 | + final int color = alpha << 24; | ||
| 301 | + | ||
| 302 | + if ((mCurrentSwipeOrientation & EDGE_LEFT) != 0) { | ||
| 303 | + canvas.clipRect(0, 0, child.getLeft(), getHeight()); | ||
| 304 | + } else if ((mCurrentSwipeOrientation & EDGE_RIGHT) != 0) { | ||
| 305 | + canvas.clipRect(child.getRight(), 0, getRight(), getHeight()); | ||
| 306 | + } | ||
| 307 | + canvas.drawColor(color); | ||
| 308 | + } | ||
| 309 | + | ||
| 310 | + @Override | ||
| 311 | + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { | ||
| 312 | + mInLayout = true; | ||
| 313 | + if (mContentView != null) { | ||
| 314 | + mContentView.layout(mContentLeft, mContentTop, | ||
| 315 | + mContentLeft + mContentView.getMeasuredWidth(), | ||
| 316 | + mContentTop + mContentView.getMeasuredHeight()); | ||
| 317 | + } | ||
| 318 | + mInLayout = false; | ||
| 319 | + } | ||
| 320 | + | ||
| 321 | + @Override | ||
| 322 | + public void requestLayout() { | ||
| 323 | + if (!mInLayout) { | ||
| 324 | + super.requestLayout(); | ||
| 325 | + } | ||
| 326 | + } | ||
| 327 | + | ||
| 328 | + @Override | ||
| 329 | + public void computeScroll() { | ||
| 330 | + mScrimOpacity = 1 - mScrollPercent; | ||
| 331 | + if (mScrimOpacity >= 0) { | ||
| 332 | + if (mHelper.continueSettling(true)) { | ||
| 333 | + ViewCompat.postInvalidateOnAnimation(this); | ||
| 334 | + } | ||
| 335 | + | ||
| 336 | + if (mPreFragment != null && mPreFragment.getView() != null) { | ||
| 337 | + if (mCallOnDestroyView) { | ||
| 338 | + mPreFragment.getView().setX(0); | ||
| 339 | + return; | ||
| 340 | + } | ||
| 341 | + | ||
| 342 | + if (mHelper.getCapturedView() != null) { | ||
| 343 | + int leftOffset = (int) ((mHelper.getCapturedView().getLeft() - getWidth()) * mParallaxOffset * mScrimOpacity); | ||
| 344 | + mPreFragment.getView().setX(leftOffset > 0 ? 0 : leftOffset); | ||
| 345 | + } | ||
| 346 | + } | ||
| 347 | + } | ||
| 348 | + } | ||
| 349 | + | ||
| 350 | + /** | ||
| 351 | + * hide | ||
| 352 | + */ | ||
| 353 | + public void internalCallOnDestroyView() { | ||
| 354 | + mCallOnDestroyView = true; | ||
| 355 | + } | ||
| 356 | + | ||
| 357 | + public void setFragment(final ISupportFragment fragment, View view) { | ||
| 358 | + this.mFragment = fragment; | ||
| 359 | + mContentView = view; | ||
| 360 | + } | ||
| 361 | + | ||
| 362 | + public void hiddenFragment() { | ||
| 363 | + if (mPreFragment != null && mPreFragment.getView() != null) { | ||
| 364 | + mPreFragment.getView().setVisibility(GONE); | ||
| 365 | + } | ||
| 366 | + } | ||
| 367 | + | ||
| 368 | + public void attachToActivity(FragmentActivity activity) { | ||
| 369 | + mActivity = activity; | ||
| 370 | + TypedArray a = activity.getTheme().obtainStyledAttributes(new int[]{ | ||
| 371 | + android.R.attr.windowBackground | ||
| 372 | + }); | ||
| 373 | + int background = a.getResourceId(0, 0); | ||
| 374 | + a.recycle(); | ||
| 375 | + | ||
| 376 | + ViewGroup decor = (ViewGroup) activity.getWindow().getDecorView(); | ||
| 377 | + ViewGroup decorChild = (ViewGroup) decor.getChildAt(0); | ||
| 378 | + decorChild.setBackgroundResource(background); | ||
| 379 | + decor.removeView(decorChild); | ||
| 380 | + addView(decorChild); | ||
| 381 | + setContentView(decorChild); | ||
| 382 | + decor.addView(this); | ||
| 383 | + } | ||
| 384 | + | ||
| 385 | + public void attachToFragment(ISupportFragment fragment, View view) { | ||
| 386 | + addView(view); | ||
| 387 | + setFragment(fragment, view); | ||
| 388 | + } | ||
| 389 | + | ||
| 390 | + private void setContentView(View view) { | ||
| 391 | + mContentView = view; | ||
| 392 | + } | ||
| 393 | + | ||
| 394 | + public void setEnableGesture(boolean enable) { | ||
| 395 | + mEnable = enable; | ||
| 396 | + } | ||
| 397 | + | ||
| 398 | + public void setEdgeLevel(EdgeLevel edgeLevel) { | ||
| 399 | + validateEdgeLevel(-1, edgeLevel); | ||
| 400 | + } | ||
| 401 | + | ||
| 402 | + public void setEdgeLevel(int widthPixel) { | ||
| 403 | + validateEdgeLevel(widthPixel, null); | ||
| 404 | + } | ||
| 405 | + | ||
| 406 | + private void validateEdgeLevel(int widthPixel, EdgeLevel edgeLevel) { | ||
| 407 | + try { | ||
| 408 | + DisplayMetrics metrics = new DisplayMetrics(); | ||
| 409 | + WindowManager windowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); | ||
| 410 | + windowManager.getDefaultDisplay().getMetrics(metrics); | ||
| 411 | + Field mEdgeSize = mHelper.getClass().getDeclaredField("mEdgeSize"); | ||
| 412 | + mEdgeSize.setAccessible(true); | ||
| 413 | + if (widthPixel >= 0) { | ||
| 414 | + mEdgeSize.setInt(mHelper, widthPixel); | ||
| 415 | + } else { | ||
| 416 | + if (edgeLevel == EdgeLevel.MAX) { | ||
| 417 | + mEdgeSize.setInt(mHelper, metrics.widthPixels); | ||
| 418 | + } else if (edgeLevel == EdgeLevel.MED) { | ||
| 419 | + mEdgeSize.setInt(mHelper, metrics.widthPixels / 2); | ||
| 420 | + } else { | ||
| 421 | + mEdgeSize.setInt(mHelper, ((int) (20 * metrics.density + 0.5f))); | ||
| 422 | + } | ||
| 423 | + } | ||
| 424 | + } catch (NoSuchFieldException e) { | ||
| 425 | + e.printStackTrace(); | ||
| 426 | + } catch (IllegalAccessException e) { | ||
| 427 | + e.printStackTrace(); | ||
| 428 | + } | ||
| 429 | + } | ||
| 430 | + | ||
| 431 | + private class ViewDragCallback extends ViewDragHelper.Callback { | ||
| 432 | + | ||
| 433 | + @Override | ||
| 434 | + public boolean tryCaptureView(View child, int pointerId) { | ||
| 435 | + boolean dragEnable = mHelper.isEdgeTouched(mEdgeFlag, pointerId); | ||
| 436 | + if (dragEnable) { | ||
| 437 | + if (mHelper.isEdgeTouched(EDGE_LEFT, pointerId)) { | ||
| 438 | + mCurrentSwipeOrientation = EDGE_LEFT; | ||
| 439 | + } else if (mHelper.isEdgeTouched(EDGE_RIGHT, pointerId)) { | ||
| 440 | + mCurrentSwipeOrientation = EDGE_RIGHT; | ||
| 441 | + } | ||
| 442 | + | ||
| 443 | + if (mListeners != null) { | ||
| 444 | + for (OnSwipeListener listener : mListeners) { | ||
| 445 | + listener.onEdgeTouch(mCurrentSwipeOrientation); | ||
| 446 | + } | ||
| 447 | + } | ||
| 448 | + | ||
| 449 | + if (mPreFragment == null) { | ||
| 450 | + if (mFragment != null) { | ||
| 451 | + List<Fragment> fragmentList = FragmentationMagician.getActiveFragments(((Fragment) mFragment).getFragmentManager()); | ||
| 452 | + if (fragmentList != null && fragmentList.size() > 1) { | ||
| 453 | + int index = fragmentList.indexOf(mFragment); | ||
| 454 | + for (int i = index - 1; i >= 0; i--) { | ||
| 455 | + Fragment fragment = fragmentList.get(i); | ||
| 456 | + if (fragment != null && fragment.getView() != null) { | ||
| 457 | + fragment.getView().setVisibility(VISIBLE); | ||
| 458 | + mPreFragment = fragment; | ||
| 459 | + break; | ||
| 460 | + } | ||
| 461 | + } | ||
| 462 | + } | ||
| 463 | + } | ||
| 464 | + } else { | ||
| 465 | + View preView = mPreFragment.getView(); | ||
| 466 | + if (preView != null && preView.getVisibility() != VISIBLE) { | ||
| 467 | + preView.setVisibility(VISIBLE); | ||
| 468 | + } | ||
| 469 | + } | ||
| 470 | + } | ||
| 471 | + return dragEnable; | ||
| 472 | + } | ||
| 473 | + | ||
| 474 | + @Override | ||
| 475 | + public int clampViewPositionHorizontal(View child, int left, int dx) { | ||
| 476 | + int ret = 0; | ||
| 477 | + if ((mCurrentSwipeOrientation & EDGE_LEFT) != 0) { | ||
| 478 | + ret = Math.min(child.getWidth(), Math.max(left, 0)); | ||
| 479 | + } else if ((mCurrentSwipeOrientation & EDGE_RIGHT) != 0) { | ||
| 480 | + ret = Math.min(0, Math.max(left, -child.getWidth())); | ||
| 481 | + } | ||
| 482 | + return ret; | ||
| 483 | + } | ||
| 484 | + | ||
| 485 | + @Override | ||
| 486 | + public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) { | ||
| 487 | + super.onViewPositionChanged(changedView, left, top, dx, dy); | ||
| 488 | + | ||
| 489 | + if ((mCurrentSwipeOrientation & EDGE_LEFT) != 0) { | ||
| 490 | + mScrollPercent = Math.abs((float) left / (mContentView.getWidth() + mShadowLeft.getIntrinsicWidth())); | ||
| 491 | + } else if ((mCurrentSwipeOrientation & EDGE_RIGHT) != 0) { | ||
| 492 | + mScrollPercent = Math.abs((float) left / (mContentView.getWidth() + mShadowRight.getIntrinsicWidth())); | ||
| 493 | + } | ||
| 494 | + mContentLeft = left; | ||
| 495 | + mContentTop = top; | ||
| 496 | + invalidate(); | ||
| 497 | + | ||
| 498 | + if (mListeners != null && mHelper.getViewDragState() == STATE_DRAGGING && mScrollPercent <= 1 && mScrollPercent > 0) { | ||
| 499 | + for (OnSwipeListener listener : mListeners) { | ||
| 500 | + listener.onDragScrolled(mScrollPercent); | ||
| 501 | + } | ||
| 502 | + } | ||
| 503 | + | ||
| 504 | + if (mScrollPercent > 1) { | ||
| 505 | + if (mFragment != null) { | ||
| 506 | + if (mCallOnDestroyView) return; | ||
| 507 | + | ||
| 508 | + if (!((Fragment) mFragment).isDetached()) { | ||
| 509 | + onDragFinished(); | ||
| 510 | + mFragment.getSupportDelegate().popQuiet(); | ||
| 511 | + } | ||
| 512 | + } else { | ||
| 513 | + if (!mActivity.isFinishing()) { | ||
| 514 | + onDragFinished(); | ||
| 515 | + mActivity.finish(); | ||
| 516 | + mActivity.overridePendingTransition(0, 0); | ||
| 517 | + } | ||
| 518 | + } | ||
| 519 | + } | ||
| 520 | + } | ||
| 521 | + | ||
| 522 | + @Override | ||
| 523 | + public int getViewHorizontalDragRange(View child) { | ||
| 524 | + if (mFragment != null) { | ||
| 525 | + return 1; | ||
| 526 | + } | ||
| 527 | + if (mActivity instanceof ISwipeBackActivity && ((ISwipeBackActivity) mActivity).swipeBackPriority()) { | ||
| 528 | + return 1; | ||
| 529 | + } | ||
| 530 | + return 0; | ||
| 531 | + } | ||
| 532 | + | ||
| 533 | + @Override | ||
| 534 | + public void onViewReleased(View releasedChild, float xvel, float yvel) { | ||
| 535 | + final int childWidth = releasedChild.getWidth(); | ||
| 536 | + | ||
| 537 | + int left = 0, top = 0; | ||
| 538 | + if ((mCurrentSwipeOrientation & EDGE_LEFT) != 0) { | ||
| 539 | + left = xvel > 0 || xvel == 0 && mScrollPercent > mScrollFinishThreshold ? (childWidth | ||
| 540 | + + mShadowLeft.getIntrinsicWidth() + OVERSCROLL_DISTANCE) : 0; | ||
| 541 | + } else if ((mCurrentSwipeOrientation & EDGE_RIGHT) != 0) { | ||
| 542 | + left = xvel < 0 || xvel == 0 && mScrollPercent > mScrollFinishThreshold ? -(childWidth | ||
| 543 | + + mShadowRight.getIntrinsicWidth() + OVERSCROLL_DISTANCE) : 0; | ||
| 544 | + } | ||
| 545 | + | ||
| 546 | + mHelper.settleCapturedViewAt(left, top); | ||
| 547 | + invalidate(); | ||
| 548 | + } | ||
| 549 | + | ||
| 550 | + @Override | ||
| 551 | + public void onViewDragStateChanged(int state) { | ||
| 552 | + super.onViewDragStateChanged(state); | ||
| 553 | + if (mListeners != null) { | ||
| 554 | + for (OnSwipeListener listener : mListeners) { | ||
| 555 | + listener.onDragStateChange(state); | ||
| 556 | + } | ||
| 557 | + } | ||
| 558 | + } | ||
| 559 | + | ||
| 560 | + @Override | ||
| 561 | + public void onEdgeTouched(int edgeFlags, int pointerId) { | ||
| 562 | + super.onEdgeTouched(edgeFlags, pointerId); | ||
| 563 | + if ((mEdgeFlag & edgeFlags) != 0) { | ||
| 564 | + mCurrentSwipeOrientation = edgeFlags; | ||
| 565 | + } | ||
| 566 | + } | ||
| 567 | + } | ||
| 568 | + | ||
| 569 | + private void onDragFinished() { | ||
| 570 | + if (mListeners != null) { | ||
| 571 | + for (OnSwipeListener listener : mListeners) { | ||
| 572 | + listener.onDragStateChange(STATE_FINISHED); | ||
| 573 | + } | ||
| 574 | + } | ||
| 575 | + } | ||
| 576 | + | ||
| 577 | + @Override | ||
| 578 | + public boolean onInterceptTouchEvent(MotionEvent ev) { | ||
| 579 | + if (!mEnable) return super.onInterceptTouchEvent(ev); | ||
| 580 | + try { | ||
| 581 | + return mHelper.shouldInterceptTouchEvent(ev); | ||
| 582 | + } catch (Exception ignored) { | ||
| 583 | + ignored.printStackTrace(); | ||
| 584 | + } | ||
| 585 | + return false; | ||
| 586 | + } | ||
| 587 | + | ||
| 588 | + @Override | ||
| 589 | + public boolean onTouchEvent(MotionEvent event) { | ||
| 590 | + if (!mEnable) return super.onTouchEvent(event); | ||
| 591 | + try { | ||
| 592 | + mHelper.processTouchEvent(event); | ||
| 593 | + return true; | ||
| 594 | + } catch (Exception ignored) { | ||
| 595 | + ignored.printStackTrace(); | ||
| 596 | + } | ||
| 597 | + return false; | ||
| 598 | + } | ||
| 599 | +} |