Fragment工具类 - MvpFragmentManager
2020-08-27 本文已影响0人
魔女小姐的猫
使用简便
/**
* MvpFragmentManager 添加Fragment的工具类
* addOrShowFragment() 添加Fragment方法
*
* @param FragmentManager manager 布局管理器
* @param Class<? extends BaseFragment> willShowFragment 将要进入的Fragment
* @param BaseFragment preFragment 将要退出的Fragment(可以为null)
* @param @IdRes int containerId 放置Fragment的容器FrameLayout
*/
MvpFragmentManager.addOrShowFragment(getSupportFragmentManager(), MenuFragment.class, null, R.id.home_menu_fl);
BaseFragment 抽象类
package com.example.mvplib.fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.RelativeLayout;
import android.widget.Toast;
import androidx.annotation.IdRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.appcompat.widget.ContentFrameLayout;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.fragment.app.Fragment;
import com.example.mvplib.R;
public abstract class BaseFragment extends Fragment {
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
//获取布局
if(getLayoutId() == 0){
return null;
}
View v = inflater.inflate(getLayoutId(),container,false);
String viewClassName = v.getClass().getName();
if(viewClassName.equals(RelativeLayout.class.getName())
|| viewClassName.equals(ConstraintLayout.class.getName())
|| viewClassName.equals(FrameLayout.class.getName())
|| viewClassName.equals(ContentFrameLayout.class.getName())){
return v;
}else{
FrameLayout frameLayout = new FrameLayout(getContext());
frameLayout.addView(v);
frameLayout.setTag("wrap");
return frameLayout;
}
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
//绑定控件 支持3.6(bingView)
if(view.getTag() != null){
bindView(((ViewGroup)view).getChildAt(0));
}else{
bindView(view);
}
initView();
}
protected void bindView(View view){
}
@Override
public void onDestroyView() {
super.onDestroyView();
}
protected abstract int getLayoutId();
protected void initView(){ }
//绑定控件 findViewById
public <T extends View> T findViewById(@IdRes int id){
return getView().findViewById(id);
}
//Toast 土司
protected void showToast(String content){
Toast.makeText(getContext(),content,Toast.LENGTH_SHORT).show();
}
protected void showToast(@StringRes int id){
Toast.makeText(getContext(),id,Toast.LENGTH_SHORT).show();
}
//是否显示动画
public boolean isNeedAnimation(){
return true;
}
public int getEnterAnimation(){
return R.anim.common_page_right_in;
}
public int getExitAnimation(){
return R.anim.common_page_left_out;
}
public int getPopEnterAnimation(){
return R.anim.common_page_left_in;
}
public int getPopExitAnimation(){
return R.anim.common_page_right_out;
}
//是否进入到回退栈
public boolean isNeedAddToBackStack(){
return true;
}
/**
* 对上一个fragment 如何进行处理
*/
public Action getActionFroPreFragment(){
return Action.HIDE;
}
public enum Action{
NONE,HIDE,DETACH,REMOVE
}
}
MvpFragmentManager 类
package com.example.mvplib.fragment;
import androidx.annotation.IdRes;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
public class MvpFragmentManager {
/**
* add -- remove
*
* replace -> (add remove)
*
*
* show --> hide
* attach --> detach
*
*
*
* 某一次操作,add B hide A
*
* 返回时: remove B show A
*/
public static BaseFragment addOrShowFragment(FragmentManager manager, Class<? extends BaseFragment> willShowFragment,BaseFragment preFragment,@IdRes int containerId){
FragmentTransaction transaction = manager.beginTransaction();
try {
String tag = willShowFragment.getName();
BaseFragment willShowFragmentInstance = (BaseFragment) manager.findFragmentByTag(tag);
if(willShowFragmentInstance == null){ // 当前activity 已经添加了 该fragment
willShowFragmentInstance = willShowFragment.newInstance();
/**
* `17: 18 从 A 进入B 此时事务里面记录的 将要显示的fragment 是B ,上一个是A 。 提交过后,这个事务这个记录是不不是已经被记录了。17: 20 的时候
* 按返回键。拿出 17:18 分记录的那个事务,进行逆向操作。
*
* 比如:从A 里面 要显示B 。 B 就是将要显示的fragment .A 就是上一个 fragment
* 第一个 enter : 表示将要显示的 fragment 进入的动画
* 第二个 exit : 新fragment 进入,上一个fragment 退出的动画
* 第三个 popEnter : 表示按返回键时上一个fragment 弹进的动画
* 第四个 popExit: 表示按返回键时 将要显示的fragment 被弹出的动画
*/
transaction.setCustomAnimations(
willShowFragmentInstance.isNeedAnimation() ? willShowFragmentInstance.getEnterAnimation() : 0,
(preFragment == null ? 0 : (preFragment.isNeedAnimation() ? preFragment.getExitAnimation() :0)),
(preFragment == null ? 0 : (preFragment .isNeedAnimation() ? preFragment.getPopEnterAnimation() : 0))
, willShowFragmentInstance .isNeedAnimation() ? willShowFragmentInstance.getPopExitAnimation() : 0);
transaction.add(containerId,willShowFragmentInstance, tag);
if(willShowFragmentInstance.isNeedAddToBackStack()){
transaction.addToBackStack(tag); // 把这一次事务添加到回退栈里面
}
}else{ // 当前 activity 已经添加过这个fragment
int count = manager.getBackStackEntryCount(); // 获取回退栈里面 事务的个数
FragmentManager.BackStackEntry entry = null;
for(int i = 0; i < count; i++){
entry = manager.getBackStackEntryAt(i);
if(entry.getName().equals(tag)){
manager.popBackStackImmediate(tag,0);
return willShowFragmentInstance;
}
}
if(count > 0){
manager.popBackStackImmediate(manager.getBackStackEntryAt(0).getName(),FragmentManager.POP_BACK_STACK_INCLUSIVE);
return willShowFragmentInstance;
}else{
if(!willShowFragmentInstance.isAdded()){ // 如果没有添加
transaction.add(containerId,willShowFragmentInstance, tag);
}
if(willShowFragmentInstance.isDetached()){ // 如果从activity detach 了
transaction.attach(willShowFragmentInstance);
}
if(willShowFragmentInstance.isHidden()){// 如果被隐藏了
transaction.show(willShowFragmentInstance);
}
}
}
handPreFragment(transaction,preFragment,willShowFragmentInstance);
transaction.commit();
return willShowFragmentInstance; // 把自己(即将要显示的) 返回出去。
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private static void handPreFragment(FragmentTransaction transaction,BaseFragment preFragment,BaseFragment willShowFragment){
if(preFragment != null){
switch (willShowFragment.getActionFroPreFragment()){
case REMOVE:{
transaction.remove(preFragment);
break;
}
case DETACH:{
transaction.detach(preFragment);
break;
}
case HIDE:{
transaction.hide(preFragment);
break;
}
}
}
}
}
四种动画
R.anim.common_page_right_in
<?xml version="1.0" encoding="utf-8"?>
<!--<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="500"
android:propertyName="x"
android:valueFrom="640"
android:valueTo="0"
android:valueType="floatType" />
</set> -->
<set>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXDelta="100%"
android:toXDelta="0"
android:interpolator="@android:anim/decelerate_interpolator"
android:duration="500"/>
</set>
R.anim.common_page_left_out
<?xml version="1.0" encoding="utf-8"?>
<set>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXDelta="0"
android:toXDelta="-100%"
android:interpolator="@android:anim/decelerate_interpolator"
android:duration="500"/>
</set>
R.anim.common_page_left_in
<?xml version="1.0" encoding="utf-8"?>
<set>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXDelta="-100%"
android:toXDelta="0"
android:interpolator="@android:anim/decelerate_interpolator"
android:duration="500"/>
</set>
R.anim.common_page_right_out
<?xml version="1.0" encoding="utf-8"?>
<!-- <set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="500"
android:propertyName="x"
android:valueFrom="0"
android:valueTo="640"
android:valueType="floatType" />
</set> -->
<set>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXDelta="0"
android:toXDelta="100%"
android:interpolator="@android:anim/decelerate_interpolator"
android:duration="500"/>
</set>