mirror of
https://github.com/Tencent/QMUI_Android.git
synced 2026-10-29 03:26:44 +08:00
QMUINavFragment
This commit is contained in:
@@ -26,7 +26,6 @@ import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewParent;
|
||||
import android.view.animation.AlphaAnimation;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.AnimationUtils;
|
||||
@@ -47,8 +46,6 @@ import androidx.lifecycle.Lifecycle;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.lifecycle.ViewModelStoreOwner;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
import androidx.viewpager2.widget.ViewPager2;
|
||||
|
||||
import com.qmuiteam.qmui.QMUIConfig;
|
||||
import com.qmuiteam.qmui.QMUILog;
|
||||
@@ -423,6 +420,7 @@ public abstract class QMUIFragment extends Fragment implements
|
||||
String tagName = fragment.getClass().getSimpleName();
|
||||
return provider.getContainerFragmentManager()
|
||||
.beginTransaction()
|
||||
.setPrimaryNavigationFragment(null)
|
||||
.setCustomAnimations(transitionConfig.enter, transitionConfig.exit, transitionConfig.popenter, transitionConfig.popout)
|
||||
.replace(provider.getContextViewId(), fragment, tagName)
|
||||
.addToBackStack(tagName)
|
||||
@@ -476,48 +474,16 @@ public abstract class QMUIFragment extends Fragment implements
|
||||
new SwipeBackLayout.Callback() {
|
||||
@Override
|
||||
public int getDragDirection(SwipeBackLayout swipeBackLayout, SwipeBackLayout.ViewMoveAction viewMoveAction, float downX, float downY, float dx, float dy, float touchSlop) {
|
||||
// 1. can not swipe back if in animation
|
||||
if (mEnterAnimationStatus != ANIMATION_ENTER_STATUS_END) {
|
||||
return SwipeBackLayout.DRAG_DIRECTION_NONE;
|
||||
|
||||
mCalled = false;
|
||||
boolean canHandle = canHandleSwipeBack();
|
||||
if (!mCalled) {
|
||||
throw new RuntimeException(getClass().getSimpleName() + " did not call through to super.shouldPreventSwipeBack()");
|
||||
}
|
||||
|
||||
// 2. can not swipe back if it is not managed by FragmentContainer
|
||||
QMUIFragmentContainerProvider provider = findFragmentContainerProvider();
|
||||
if (provider == null) {
|
||||
return SwipeBackLayout.DRAG_DIRECTION_NONE;
|
||||
if(!canHandle){
|
||||
return DRAG_DIRECTION_NONE;
|
||||
}
|
||||
|
||||
FragmentManager fragmentManager = provider.getContainerFragmentManager();
|
||||
if (fragmentManager == null || fragmentManager != getParentFragmentManager()) {
|
||||
return SwipeBackLayout.DRAG_DIRECTION_NONE;
|
||||
}
|
||||
|
||||
// 3. need be handled by inner FragmentContainer
|
||||
if (fragmentManager.getPrimaryNavigationFragment() != null) {
|
||||
return SwipeBackLayout.DRAG_DIRECTION_NONE;
|
||||
}
|
||||
|
||||
// 4. can not swipe back if the view is null
|
||||
View view = getView();
|
||||
if (view == null) {
|
||||
return SwipeBackLayout.DRAG_DIRECTION_NONE;
|
||||
}
|
||||
|
||||
// 5. can not swipe back if if the Fragment is in ViewPager
|
||||
ViewParent parent = view.getParent();
|
||||
while (parent != null) {
|
||||
if (parent instanceof ViewPager || parent instanceof ViewPager2) {
|
||||
return SwipeBackLayout.DRAG_DIRECTION_NONE;
|
||||
}
|
||||
parent = parent.getParent();
|
||||
}
|
||||
|
||||
// 6. can not swipe back if the backStack entry count is less than 2
|
||||
if (fragmentManager.getBackStackEntryCount() <= 1 &&
|
||||
!QMUISwipeBackActivityManager.getInstance().canSwipeBack()) {
|
||||
return SwipeBackLayout.DRAG_DIRECTION_NONE;
|
||||
}
|
||||
|
||||
return QMUIFragment.this.getDragDirection(
|
||||
swipeBackLayout, viewMoveAction, downX, downY, dx, dy, touchSlop);
|
||||
}
|
||||
@@ -748,6 +714,8 @@ public abstract class QMUIFragment extends Fragment implements
|
||||
if (onRemove != null) {
|
||||
onRemove.apply(view);
|
||||
}
|
||||
view.setTranslationY(0);
|
||||
view.setTranslationX(0);
|
||||
parent.removeView(view);
|
||||
}
|
||||
}
|
||||
@@ -1082,7 +1050,7 @@ public abstract class QMUIFragment extends Fragment implements
|
||||
mCalled = false;
|
||||
onEnterAnimationEnd(animation);
|
||||
if (!mCalled) {
|
||||
throw new RuntimeException("QMUIFragment " + this + " did not call through to super.onEnterAnimationEnd(Animation)");
|
||||
throw new RuntimeException(getClass().getSimpleName() + " did not call through to super.onEnterAnimationEnd(Animation)");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1196,6 +1164,44 @@ public abstract class QMUIFragment extends Fragment implements
|
||||
return SwipeBackLayout.MOVE_VIEW_AUTO;
|
||||
}
|
||||
|
||||
protected boolean canHandleSwipeBack(){
|
||||
mCalled = true;
|
||||
// 1. can not swipe back if enter animation is not finished
|
||||
if (mEnterAnimationStatus != ANIMATION_ENTER_STATUS_END) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QMUIFragmentContainerProvider provider = findFragmentContainerProvider();
|
||||
if (provider == null) {
|
||||
return false;
|
||||
}
|
||||
FragmentManager fragmentManager = provider.getContainerFragmentManager();
|
||||
|
||||
// 3. is not managed by QMUIFragmentContainerProvider
|
||||
if (fragmentManager == null || fragmentManager != getParentFragmentManager()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 4. should handle by child
|
||||
if(provider.isChildHandlePopBackRequested()){
|
||||
return false;
|
||||
}
|
||||
|
||||
// 5. can not swipe back if the view is null
|
||||
View view = getView();
|
||||
if (view == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 6. can not swipe back if the backStack entry count is less than 2
|
||||
if (fragmentManager.getBackStackEntryCount() <= 1 &&
|
||||
!QMUISwipeBackActivityManager.getInstance().canSwipeBack()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected int getDragDirection(@NonNull SwipeBackLayout swipeBackLayout,
|
||||
@NonNull SwipeBackLayout.ViewMoveAction viewMoveAction,
|
||||
float downX, float downY, float dx, float dy, float slopTouch) {
|
||||
|
||||
@@ -54,6 +54,7 @@ public abstract class QMUIFragmentActivity extends InnerBaseActivity implements
|
||||
private static final String TAG = "QMUIFragmentActivity";
|
||||
private RootView mRootView;
|
||||
private boolean mIsFirstFragmentAdded = false;
|
||||
private boolean isChildHandlePopBackRequested = false;
|
||||
|
||||
static {
|
||||
QMUIWindowInsetHelper.addHandleContainer(FragmentContainerView.class);
|
||||
@@ -181,6 +182,16 @@ public abstract class QMUIFragmentActivity extends InnerBaseActivity implements
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestForHandlePopBack(boolean toHandle) {
|
||||
isChildHandlePopBackRequested = toHandle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChildHandlePopBackRequested() {
|
||||
return isChildHandlePopBackRequested;
|
||||
}
|
||||
|
||||
protected RootView onCreateRootView(int fragmentContainerId) {
|
||||
return new DefaultRootView(this, fragmentContainerId);
|
||||
}
|
||||
|
||||
@@ -30,4 +30,8 @@ public interface QMUIFragmentContainerProvider {
|
||||
FragmentContainerView getFragmentContainerView();
|
||||
|
||||
ViewModelStoreOwner getContainerViewModelStoreOwner();
|
||||
|
||||
void requestForHandlePopBack(boolean toHandle);
|
||||
|
||||
boolean isChildHandlePopBackRequested();
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.FragmentContainerView;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
import androidx.lifecycle.ViewModelStoreOwner;
|
||||
|
||||
import com.qmuiteam.qmui.QMUILog;
|
||||
@@ -18,6 +19,7 @@ public class QMUINavFragment extends QMUIFragment implements QMUIFragmentContain
|
||||
private static final String QMUI_ARGUMENT_FRAGMENT_ARG = "qmui_argument_fragment_arg";
|
||||
private FragmentContainerView mContainerView;
|
||||
private boolean mIsFirstFragmentAdded = false;
|
||||
private boolean isChildHandlePopBackRequested = false;
|
||||
|
||||
public static QMUINavFragment getDefaultInstance(Class<? extends QMUIFragment> firstFragmentCls,
|
||||
@Nullable Bundle firstFragmentArgument){
|
||||
@@ -44,18 +46,6 @@ public class QMUINavFragment extends QMUIFragment implements QMUIFragmentContain
|
||||
return arg;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(@NonNull Context context) {
|
||||
super.onAttach(context);
|
||||
getChildFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
|
||||
@Override
|
||||
public void onBackStackChanged() {
|
||||
getParentFragmentManager().beginTransaction()
|
||||
.setPrimaryNavigationFragment(getChildFragmentManager().getBackStackEntryCount() > 1 ? QMUINavFragment.this : null)
|
||||
.commit();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
@@ -139,6 +129,50 @@ public class QMUINavFragment extends QMUIFragment implements QMUIFragmentContain
|
||||
return R.id.qmui_activity_fragment_container_id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestForHandlePopBack(boolean toHandle) {
|
||||
isChildHandlePopBackRequested = toHandle;
|
||||
QMUIFragmentContainerProvider provider = findFragmentContainerProvider();
|
||||
if(provider != null){
|
||||
provider.requestForHandlePopBack(toHandle || getChildFragmentManager().getBackStackEntryCount() > 1);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChildHandlePopBackRequested() {
|
||||
return isChildHandlePopBackRequested;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(@NonNull Context context) {
|
||||
super.onAttach(context);
|
||||
getChildFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
|
||||
@Override
|
||||
public void onBackStackChanged() {
|
||||
boolean enoughBackStackCount = getChildFragmentManager().getBackStackEntryCount() > 1;
|
||||
QMUIFragmentContainerProvider provider = findFragmentContainerProvider();
|
||||
if(provider != null){
|
||||
provider.requestForHandlePopBack(isChildHandlePopBackRequested || enoughBackStackCount);
|
||||
}
|
||||
if(getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.RESUMED)){
|
||||
getParentFragmentManager()
|
||||
.beginTransaction()
|
||||
.setPrimaryNavigationFragment(enoughBackStackCount ? QMUINavFragment.this : null)
|
||||
.commit();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
getParentFragmentManager()
|
||||
.beginTransaction()
|
||||
.setPrimaryNavigationFragment(getChildFragmentManager().getBackStackEntryCount() > 1 ? QMUINavFragment.this : null)
|
||||
.commit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FragmentManager getContainerFragmentManager() {
|
||||
return getChildFragmentManager();
|
||||
|
||||
Reference in New Issue
Block a user