mirror of
https://github.com/zhigang1992/react-navigation.git
synced 2026-03-01 22:35:12 +08:00
We believe that it might be better to manage the logic of blocking interactions from JS with setNativeProps and pointerEvents. The current logic leads to some issues we're facing within React Navigation. There might be a state when more that one screen can be active. E.g. in modals we want to have two screens visible on the stack and have enabled interaction on the bottom one. New code should not give any issues, because even though we need to handle activation of each screen from JS and this will just introduce an additional native call for enabling / disabling pointer events. On iOS, we're not using React Native Screens in React Navigation for now and we'd like to focus on it later because right now we're not observing that crucial performance issues.
177 lines
5.0 KiB
Java
177 lines
5.0 KiB
Java
package com.swmansion.rnscreens;
|
|
|
|
import android.content.Context;
|
|
import android.graphics.Paint;
|
|
import android.view.View;
|
|
import android.view.ViewGroup;
|
|
import android.view.inputmethod.InputMethodManager;
|
|
import android.widget.TextView;
|
|
|
|
import androidx.annotation.Nullable;
|
|
import androidx.fragment.app.Fragment;
|
|
|
|
import com.facebook.react.bridge.GuardedRunnable;
|
|
import com.facebook.react.bridge.ReactContext;
|
|
import com.facebook.react.uimanager.PointerEvents;
|
|
import com.facebook.react.uimanager.ReactPointerEventsView;
|
|
import com.facebook.react.uimanager.UIManagerModule;
|
|
|
|
public class Screen extends ViewGroup {
|
|
|
|
public enum StackPresentation {
|
|
PUSH,
|
|
MODAL,
|
|
TRANSPARENT_MODAL
|
|
}
|
|
|
|
public enum StackAnimation {
|
|
DEFAULT,
|
|
NONE,
|
|
FADE
|
|
}
|
|
|
|
private static OnAttachStateChangeListener sShowSoftKeyboardOnAttach = new OnAttachStateChangeListener() {
|
|
|
|
@Override
|
|
public void onViewAttachedToWindow(View view) {
|
|
InputMethodManager inputMethodManager =
|
|
(InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
|
|
inputMethodManager.showSoftInput(view, 0);
|
|
view.removeOnAttachStateChangeListener(sShowSoftKeyboardOnAttach);
|
|
}
|
|
|
|
@Override
|
|
public void onViewDetachedFromWindow(View view) {
|
|
|
|
}
|
|
};
|
|
|
|
private @Nullable Fragment mFragment;
|
|
private @Nullable ScreenContainer mContainer;
|
|
private boolean mActive;
|
|
private boolean mTransitioning;
|
|
private StackPresentation mStackPresentation = StackPresentation.PUSH;
|
|
private StackAnimation mStackAnimation = StackAnimation.DEFAULT;
|
|
private boolean mGestureEnabled = true;
|
|
|
|
public Screen(ReactContext context) {
|
|
super(context);
|
|
}
|
|
|
|
@Override
|
|
protected void onLayout(boolean changed, int l, int t, int r, int b) {
|
|
if (changed) {
|
|
final int width = r - l;
|
|
final int height = b - t;
|
|
final ReactContext reactContext = (ReactContext) getContext();
|
|
reactContext.runOnNativeModulesQueueThread(
|
|
new GuardedRunnable(reactContext) {
|
|
@Override
|
|
public void runGuarded() {
|
|
reactContext.getNativeModule(UIManagerModule.class)
|
|
.updateNodeSize(getId(), width, height);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void onDetachedFromWindow() {
|
|
super.onDetachedFromWindow();
|
|
clearDisappearingChildren();
|
|
}
|
|
|
|
@Override
|
|
protected void onAttachedToWindow() {
|
|
super.onAttachedToWindow();
|
|
// This method implements a workaround for RN's autoFocus functionality. Because of the way
|
|
// autoFocus is implemented it sometimes gets triggered before native text view is mounted. As
|
|
// a result Android ignores calls for opening soft keyboard and here we trigger it manually
|
|
// again after the screen is attached.
|
|
View view = getFocusedChild();
|
|
if (view != null) {
|
|
while (view instanceof ViewGroup) {
|
|
view = ((ViewGroup) view).getFocusedChild();
|
|
}
|
|
if (view instanceof TextView) {
|
|
TextView textView = (TextView) view;
|
|
if (textView.getShowSoftInputOnFocus()) {
|
|
textView.addOnAttachStateChangeListener(sShowSoftKeyboardOnAttach);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 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);
|
|
}
|
|
|
|
public void setStackPresentation(StackPresentation stackPresentation) {
|
|
mStackPresentation = stackPresentation;
|
|
}
|
|
|
|
public void setStackAnimation(StackAnimation stackAnimation) {
|
|
mStackAnimation = stackAnimation;
|
|
}
|
|
|
|
public void setGestureEnabled(boolean gestureEnabled) {
|
|
mGestureEnabled = gestureEnabled;
|
|
}
|
|
|
|
public StackAnimation getStackAnimation() {
|
|
return mStackAnimation;
|
|
}
|
|
|
|
public StackPresentation getStackPresentation() {
|
|
return mStackPresentation;
|
|
}
|
|
|
|
@Override
|
|
public void setLayerType(int layerType, @Nullable Paint paint) {
|
|
// ignore - layer type is controlled by `transitioning` prop
|
|
}
|
|
|
|
protected void setContainer(@Nullable ScreenContainer container) {
|
|
mContainer = container;
|
|
}
|
|
|
|
protected void setFragment(Fragment fragment) {
|
|
mFragment = fragment;
|
|
}
|
|
|
|
protected @Nullable Fragment getFragment() {
|
|
return mFragment;
|
|
}
|
|
|
|
protected @Nullable ScreenContainer getContainer() {
|
|
return mContainer;
|
|
}
|
|
|
|
public void setActive(boolean active) {
|
|
if (active == mActive) {
|
|
return;
|
|
}
|
|
mActive = active;
|
|
if (mContainer != null) {
|
|
mContainer.notifyChildUpdate();
|
|
}
|
|
}
|
|
|
|
public boolean isActive() {
|
|
return mActive;
|
|
}
|
|
|
|
public boolean isGestureEnabled() {
|
|
return mGestureEnabled;
|
|
}
|
|
}
|