mirror of
https://github.com/zhigang1992/react-navigation.git
synced 2026-03-06 17:34:59 +08:00
Android alpha compositing (#50)
This change adds an ability for screen container on Android to apply the correct mechanism for transparent layer blending. This is specifically important as screens are usually a complex views that may displays many layers and while transitioning often opacity is used to animate these. When we detect screen transitioning we (a) turn on offscreen alpha compositing (which makes the opacity being applied for the whole screen layer at once instead of making all the children semi-transparent) and also (b) turn on hardware layer that makes offscreen compositing render to GPU (which is both faster and consumes only GPU memory). In addition to that change we also need to disable wrapping Screen's children with View, as in such a case opacity is applied on the underlying View instead of a Screen. That workaround has been added because of a bug in Animated library and fixed in RN 0.57+
This commit is contained in:
committed by
GitHub
parent
4dd751811a
commit
68a02d58d7
@@ -2,6 +2,7 @@ package com.swmansion.rnscreens;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.graphics.Paint;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.Fragment;
|
||||
@@ -36,6 +37,7 @@ public class Screen extends ViewGroup {
|
||||
private final Fragment mFragment;
|
||||
private @Nullable ScreenContainer mContainer;
|
||||
private boolean mActive;
|
||||
private boolean mTransitioning;
|
||||
|
||||
public Screen(Context context) {
|
||||
super(context);
|
||||
@@ -47,6 +49,33 @@ public class Screen extends ViewGroup {
|
||||
// no-op
|
||||
}
|
||||
|
||||
/**
|
||||
* While transitioning this property allows to optimize rendering behavior on Android and provide
|
||||
* a correct blending options for the animated screen. It is turned on automatically by the container
|
||||
* when transitioning is detected and turned off immediately after
|
||||
*/
|
||||
public void setTransitioning(boolean transitioning) {
|
||||
if (mTransitioning == transitioning) {
|
||||
return;
|
||||
}
|
||||
mTransitioning = transitioning;
|
||||
super.setLayerType(transitioning ? View.LAYER_TYPE_HARDWARE : View.LAYER_TYPE_NONE, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasOverlappingRendering() {
|
||||
return mTransitioning;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLayerType(int layerType, @Nullable Paint paint) {
|
||||
// ignore – layer type is controlled by `transitioning` prop
|
||||
}
|
||||
|
||||
public void setNeedsOffscreenAlphaCompositing(boolean needsOffscreenAlphaCompositing) {
|
||||
// ignore - offscreen alpha is controlled by `transitioning` prop
|
||||
}
|
||||
|
||||
protected void setContainer(@Nullable ScreenContainer mContainer) {
|
||||
this.mContainer = mContainer;
|
||||
}
|
||||
|
||||
@@ -158,6 +158,15 @@ public class ScreenContainer extends ViewGroup {
|
||||
}
|
||||
}
|
||||
|
||||
// detect if we are "transitioning" based on the number of active screens
|
||||
int activeScreens = 0;
|
||||
for (int i = 0, size = mScreens.size(); i < size; i++) {
|
||||
if (isScreenActive(mScreens.get(i), mScreens)) {
|
||||
activeScreens += 1;
|
||||
}
|
||||
}
|
||||
boolean transitioning = activeScreens > 1;
|
||||
|
||||
// attach newly activated screens
|
||||
boolean addedBefore = false;
|
||||
for (int i = 0, size = mScreens.size(); i < size; i++) {
|
||||
@@ -169,6 +178,7 @@ public class ScreenContainer extends ViewGroup {
|
||||
} else if (isActive && addedBefore) {
|
||||
moveToFront(screen);
|
||||
}
|
||||
screen.setTransitioning(transitioning);
|
||||
}
|
||||
tryCommitTransaction();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user