From d539dcc2505b9e45ae4014b03b2253e3c4882c6a Mon Sep 17 00:00:00 2001 From: cgspine Date: Mon, 27 Apr 2020 15:50:44 +0800 Subject: [PATCH] keep methods in QMUIFragmentActivity --- .../com/qmuiteam/qmui/arch/QMUIFragment.java | 13 +- .../qmui/arch/QMUIFragmentActivity.java | 122 ++++++++++++++++++ 2 files changed, 133 insertions(+), 2 deletions(-) diff --git a/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragment.java b/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragment.java index 39be1f2aa..98ea78c81 100644 --- a/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragment.java +++ b/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragment.java @@ -22,6 +22,7 @@ import android.content.Intent; import android.os.Bundle; import android.util.Log; +import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -152,7 +153,7 @@ public void run() { private OnBackPressedCallback mOnBackPressedCallback = new OnBackPressedCallback(true) { @Override public void handleOnBackPressed() { - QMUIFragment.this.handleOnBackPressed(); + QMUIFragment.this.onBackPressed(); } }; @@ -914,7 +915,7 @@ public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, return swipeBackLayout; } - protected void handleOnBackPressed() { + protected void onBackPressed() { QMUIFragmentContainerProvider provider = findFragmentContainerProvider(); if(!(provider instanceof FragmentActivity) || provider.getContainerFragmentManager() == null || provider.getContainerFragmentManager().getBackStackEntryCount() > 1){ @@ -1328,6 +1329,14 @@ public boolean isVisibleToUser() { return getUserVisibleHint() && isParentVisibleToUser(); } + public boolean onKeyDown(int keyCode, KeyEvent event) { + return false; + } + + public boolean onKeyUp(int keyCode, KeyEvent event) { + return false; + } + /** * @return true if parentFragments is visible to user */ diff --git a/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragmentActivity.java b/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragmentActivity.java index 7296b2494..67618e1ac 100644 --- a/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragmentActivity.java +++ b/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragmentActivity.java @@ -22,6 +22,7 @@ import android.graphics.Rect; import android.os.Bundle; import android.util.Log; +import android.view.KeyEvent; import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout; @@ -31,6 +32,7 @@ import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentContainerView; import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentTransaction; import androidx.lifecycle.ViewModelStoreOwner; import com.qmuiteam.qmui.QMUILog; @@ -42,6 +44,8 @@ import com.qmuiteam.qmui.util.QMUIWindowInsetHelper; import com.qmuiteam.qmui.widget.QMUIWindowInsetLayout; +import java.lang.reflect.Field; + /** * the container activity for {@link QMUIFragment}. * Created by cgspine on 15/9/14. @@ -202,6 +206,124 @@ private QMUIFragment getCurrentQMUIFragment() { } + /** + * start a new fragment and then destroy current fragment. + * assume there is a fragment stack(A->B->C), and you use this method to start a new + * fragment D and destroy fragment C. Now you are in fragment D, if you want call + * {@link #popBackStack()} to back to B, what the animation should be? Sometimes we hope run + * animation generated by transition B->C, but sometimes we hope run animation generated by + * transition C->D. this why second parameter exists. + * + * @param fragment new fragment to start + * @param useNewTransitionConfigWhenPop if true, use animation generated by transition C->D, + * else, use animation generated by transition B->C + * + * @deprecated use {@link QMUIFragment#startFragmentAndDestroyCurrent(QMUIFragment, boolean)} + */ + @Deprecated + public int startFragmentAndDestroyCurrent(final QMUIFragment fragment, final boolean useNewTransitionConfigWhenPop) { + final QMUIFragment.TransitionConfig transitionConfig = fragment.onFetchTransitionConfig(); + String tagName = fragment.getClass().getSimpleName(); + FragmentManager fragmentManager = getSupportFragmentManager(); + FragmentTransaction transaction = getSupportFragmentManager().beginTransaction() + .setCustomAnimations(transitionConfig.enter, transitionConfig.exit, + transitionConfig.popenter, transitionConfig.popout) + .replace(getContextViewId(), fragment, tagName); + int index = transaction.commit(); + Utils.findAndModifyOpInBackStackRecord(fragmentManager, -1, new Utils.OpHandler() { + @Override + public boolean handle(Object op) { + Field cmdField = null; + try { + cmdField = Utils.getOpCmdField(op); + cmdField.setAccessible(true); + int cmd = (int) cmdField.get(op); + if (cmd == 1) { + if (useNewTransitionConfigWhenPop) { + Field popEnterAnimField = Utils.getOpPopEnterAnimField(op); + popEnterAnimField.setAccessible(true); + popEnterAnimField.set(op, transitionConfig.popenter); + + Field popExitAnimField = Utils.getOpPopExitAnimField(op); + popExitAnimField.setAccessible(true); + popExitAnimField.set(op, transitionConfig.popout); + } + + Field oldFragmentField = Utils.getOpFragmentField(op); + oldFragmentField.setAccessible(true); + Object fragmentObj = oldFragmentField.get(op); + oldFragmentField.set(op, fragment); + Field backStackNestField = Fragment.class.getDeclaredField("mBackStackNesting"); + backStackNestField.setAccessible(true); + int oldFragmentBackStackNest = (int) backStackNestField.get(fragmentObj); + backStackNestField.set(fragment, oldFragmentBackStackNest); + backStackNestField.set(fragmentObj, --oldFragmentBackStackNest); + return true; + } + } catch (NoSuchFieldException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + return false; + } + + @Override + public boolean needReNameTag() { + return true; + } + + @Override + public String newTagName() { + return fragment.getClass().getSimpleName(); + } + }); + return index; + } + + /** + * + * @param fragment target fragment to start + * @return commit id + * + * @deprecated use {@link QMUIFragment#startFragment(QMUIFragment)} + */ + @Deprecated + public int startFragment(QMUIFragment fragment) { + Log.i(TAG, "startFragment"); + QMUIFragment.TransitionConfig transitionConfig = fragment.onFetchTransitionConfig(); + String tagName = fragment.getClass().getSimpleName(); + return getSupportFragmentManager() + .beginTransaction() + .setCustomAnimations(transitionConfig.enter, transitionConfig.exit, transitionConfig.popenter, transitionConfig.popout) + .replace(getContextViewId(), fragment, tagName) + .addToBackStack(tagName) + .commit(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + QMUIFragment fragment = getCurrentQMUIFragment(); + if (fragment != null && !fragment.isInSwipeBack() && fragment.onKeyDown(keyCode, event)) { + return true; + } + return super.onKeyDown(keyCode, event); + } + + @Override + public boolean onKeyUp(int keyCode, KeyEvent event) { + QMUIFragment fragment = getCurrentQMUIFragment(); + if (fragment != null && !fragment.isInSwipeBack() && fragment.onKeyUp(keyCode, event)) { + return true; + } + return super.onKeyUp(keyCode, event); + } + + public void popBackStack() { + getOnBackPressedDispatcher().onBackPressed(); + } + + public static Intent intentOf(@NonNull Context context, @NonNull Class targetActivity, @NonNull Class firstFragment) {