mirror of
https://github.com/zhigang1992/react-navigation.git
synced 2026-02-10 22:47:02 +08:00
A few bugs fixed with android native stack in this commit: - fixed a problem with views not resizing when keyboard appears, the bug was due to onMeasure forwardin getHeight which was the old height of the container instead of the changed one - fixed a problem with back button behavior not being consistent. Now back button is controlled by 'gestureEnabled' to emulate iOS behavior where there is no hw back button but you can swipe back instead. - added compatibility for "contained" modal styles - for now we always render "containted" fragments on Android, plan to add a way to render in dialogs in the future
173 lines
4.9 KiB
Java
173 lines
4.9 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 implements ReactPointerEventsView {
|
|
|
|
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;
|
|
|
|
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 StackAnimation getStackAnimation() {
|
|
return mStackAnimation;
|
|
}
|
|
|
|
public StackPresentation getStackPresentation() {
|
|
return mStackPresentation;
|
|
}
|
|
|
|
@Override
|
|
public PointerEvents getPointerEvents() {
|
|
return mTransitioning ? PointerEvents.NONE : PointerEvents.AUTO;
|
|
}
|
|
|
|
@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;
|
|
}
|
|
}
|