Fix navbar window fitting on Android. (#235)

This change fixes the issue of handling transparent status bar. In such a case the navbar should became slightly bigger in order to fill the status bar space that now belongs to the window. In order for that to happen we use `setFitsSystemWindows` on main screen layout, on app bar layout and on toolbar (the toolbar is the view that gets bigger in the end).

Note that this currently only work if we use Android's native mechanism for changingthe status bar behavior and not using `StatusBar` module from RN. It is because `StausBar` module actually strips top insets from the event that gets delivered to the views. For the time being you can try the following to change status bar:
```
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
```

Note that we are also disabling app bar's scroll behavior. We wasn't utilising this yet, and it cause some weird errors on hot reload because scrolling behavior actually sets `firsSystemWindows` flag on the screen view which ended up consuming insets before appbar would get them.
This commit is contained in:
Krzysztof Magiera
2019-11-27 12:35:26 +01:00
committed by GitHub
parent efaf0cd125
commit 0927e03687
3 changed files with 36 additions and 3 deletions

View File

@@ -1,7 +1,11 @@
package com.swmansion.rnscreens;
import android.content.Context;
import android.view.View;
import android.view.WindowInsets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
@@ -32,6 +36,15 @@ public class ScreenStack extends ScreenContainer<ScreenStackFragment> {
public ScreenStack(Context context) {
super(context);
ViewCompat.setOnApplyWindowInsetsListener(this,
new androidx.core.view.OnApplyWindowInsetsListener() {
@Override
public WindowInsetsCompat onApplyWindowInsets(View v, WindowInsetsCompat insets) {
setWindowInsets(insets);
return insets;
}
});
}
public void dismiss(ScreenStackFragment screenFragment) {
@@ -53,6 +66,24 @@ public class ScreenStack extends ScreenContainer<ScreenStackFragment> {
throw new IllegalStateException("Stack has no root screen set");
}
private void setWindowInsets(WindowInsetsCompat insets) {
// we allow each screen to handle insets separately as they are all attached to the same parent
// and take up full screen. Therefore we make a copy of each inset object before passing it down
// to views.
boolean consumed = false;
for (int i = mScreenFragments.size() - 1; i >= 0; i--) {
ScreenStackFragment screen = mScreenFragments.get(i);
if (!mDismissed.contains(screen) && screen.getView() != null) {
if (ViewCompat.dispatchApplyWindowInsets(screen.getView(), new WindowInsetsCompat(insets)).isConsumed()) {
consumed = true;
}
}
}
if (consumed) {
insets.consumeSystemWindowInsets();
}
}
@Override
protected ScreenStackFragment adapt(Screen screen) {
return new ScreenStackFragment(screen);
@@ -70,7 +101,6 @@ public class ScreenStack extends ScreenContainer<ScreenStackFragment> {
fm.removeOnBackStackChangedListener(mBackStackListener);
fm.popBackStack(BACK_STACK_TAG, FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
}
@Override

View File

@@ -64,20 +64,22 @@ public class ScreenStackFragment extends ScreenFragment {
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
CoordinatorLayout view = new CoordinatorLayout(getContext());
view.setFitsSystemWindows(true);
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());
mAppBarLayout.setFitsSystemWindows(true);
// 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));
AppBarLayout.LayoutParams.MATCH_PARENT,
AppBarLayout.LayoutParams.WRAP_CONTENT));
view.addView(mAppBarLayout);
if (mToolbar != null) {

View File

@@ -47,6 +47,7 @@ public class ScreenStackHeaderConfig extends ViewGroup {
setVisibility(View.GONE);
mToolbar = new Toolbar(context);
mToolbar.setFitsSystemWindows(true);
// set primary color as background by default
TypedValue tv = new TypedValue();