mirror of
https://github.com/zhigang1992/react-navigation.git
synced 2026-01-29 22:53:52 +08:00
This change fixes a problem with native stack on Android where we'd display a sw back button on screens that are nested stack navigatodespite the fact those screens were the initial screens in the whole container stack. In #306 we introuced a change that would allow for displaying sw back in nested stacks, however that change did not handle the case where screen is a root screen of a container that is nested and placed as an initial screen in another container.
133 lines
4.3 KiB
Java
133 lines
4.3 KiB
Java
package com.swmansion.rnscreens;
|
|
|
|
import android.annotation.SuppressLint;
|
|
import android.graphics.Color;
|
|
import android.os.Bundle;
|
|
import android.view.LayoutInflater;
|
|
import android.view.View;
|
|
import android.view.ViewGroup;
|
|
import android.widget.LinearLayout;
|
|
|
|
import androidx.annotation.Nullable;
|
|
import androidx.appcompat.widget.Toolbar;
|
|
import androidx.coordinatorlayout.widget.CoordinatorLayout;
|
|
import androidx.fragment.app.Fragment;
|
|
|
|
import com.facebook.react.uimanager.PixelUtil;
|
|
import com.google.android.material.appbar.AppBarLayout;
|
|
|
|
public class ScreenStackFragment extends ScreenFragment {
|
|
|
|
private static final float TOOLBAR_ELEVATION = PixelUtil.toPixelFromDIP(4);
|
|
|
|
private AppBarLayout mAppBarLayout;
|
|
private Toolbar mToolbar;
|
|
private boolean mShadowHidden;
|
|
private CoordinatorLayout mScreenRootView;
|
|
|
|
@SuppressLint("ValidFragment")
|
|
public ScreenStackFragment(Screen screenView) {
|
|
super(screenView);
|
|
}
|
|
|
|
public void removeToolbar() {
|
|
if (mAppBarLayout != null) {
|
|
((CoordinatorLayout) getView()).removeView(mAppBarLayout);
|
|
}
|
|
}
|
|
|
|
public void setToolbar(Toolbar toolbar) {
|
|
if (mAppBarLayout != null) {
|
|
mAppBarLayout.addView(toolbar);
|
|
}
|
|
mToolbar = toolbar;
|
|
AppBarLayout.LayoutParams params = new AppBarLayout.LayoutParams(
|
|
AppBarLayout.LayoutParams.MATCH_PARENT, AppBarLayout.LayoutParams.WRAP_CONTENT);
|
|
params.setScrollFlags(0);
|
|
mToolbar.setLayoutParams(params);
|
|
}
|
|
|
|
public void setToolbarShadowHidden(boolean hidden) {
|
|
if (mShadowHidden != hidden) {
|
|
mAppBarLayout.setTargetElevation(hidden ? 0 : TOOLBAR_ELEVATION);
|
|
mShadowHidden = hidden;
|
|
}
|
|
}
|
|
|
|
public void onStackUpdate() {
|
|
View child = mScreenView.getChildAt(0);
|
|
if (child instanceof ScreenStackHeaderConfig) {
|
|
((ScreenStackHeaderConfig) child).onUpdate();
|
|
}
|
|
}
|
|
|
|
private CoordinatorLayout configureView() {
|
|
CoordinatorLayout view = new CoordinatorLayout(getContext());
|
|
CoordinatorLayout.LayoutParams params = new CoordinatorLayout.LayoutParams(
|
|
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);
|
|
params.setBehavior(new AppBarLayout.ScrollingViewBehavior());
|
|
mScreenView.setLayoutParams(params);
|
|
view.addView(mScreenView);
|
|
|
|
mAppBarLayout = new AppBarLayout(getContext());
|
|
// By default AppBarLayout will have a background color set but since we cover the whole layout
|
|
// with toolbar (that can be semi-transparent) the bar layout background color does not pay a
|
|
// role. On top of that it breaks screens animations when alfa offscreen compositing is off
|
|
// (which is the default)
|
|
mAppBarLayout.setBackgroundColor(Color.TRANSPARENT);
|
|
mAppBarLayout.setLayoutParams(new AppBarLayout.LayoutParams(
|
|
AppBarLayout.LayoutParams.MATCH_PARENT, AppBarLayout.LayoutParams.WRAP_CONTENT));
|
|
view.addView(mAppBarLayout);
|
|
|
|
if (mToolbar != null) {
|
|
mAppBarLayout.addView(mToolbar);
|
|
}
|
|
|
|
return view;
|
|
}
|
|
|
|
@Override
|
|
public View onCreateView(LayoutInflater inflater,
|
|
@Nullable ViewGroup container,
|
|
@Nullable Bundle savedInstanceState) {
|
|
if (mScreenRootView == null) {
|
|
mScreenRootView = configureView();
|
|
}
|
|
|
|
return mScreenRootView;
|
|
}
|
|
|
|
public boolean isDismissable() {
|
|
return mScreenView.isGestureEnabled();
|
|
}
|
|
|
|
public boolean canNavigateBack() {
|
|
ScreenContainer container = mScreenView.getContainer();
|
|
if (container instanceof ScreenStack) {
|
|
if (((ScreenStack) container).getRootScreen() == getScreen()) {
|
|
// this screen is the root of the container, if it is nested we can check parent container
|
|
// if it is also a root or not
|
|
Fragment parentFragment = getParentFragment();
|
|
if (parentFragment instanceof ScreenStackFragment) {
|
|
return ((ScreenStackFragment) parentFragment).canNavigateBack();
|
|
} else {
|
|
return false;
|
|
}
|
|
} else {
|
|
return true;
|
|
}
|
|
} else {
|
|
throw new IllegalStateException("ScreenStackFragment added into a non-stack container");
|
|
}
|
|
}
|
|
|
|
public void dismiss() {
|
|
ScreenContainer container = mScreenView.getContainer();
|
|
if (container instanceof ScreenStack) {
|
|
((ScreenStack) container).dismiss(this);
|
|
} else {
|
|
throw new IllegalStateException("ScreenStackFragment added into a non-stack container");
|
|
}
|
|
}
|
|
}
|