react-navigation相关bug的解决

让安卓实现push动画

之前我群里的讨论怎么让安卓实现类似iOS的push动画,后来翻看官方issues的时候,真的发现了实现push动画的代码,在这里共享下

// 先引入这个方法
import CardStackStyleInterpolator from 'react-navigation/src/views/CardStackStyleInterpolator';

// 在StackNavigator配置headerMode的地方,使用transitionConfig添加
{
    headerMode: 'screen',
    transitionConfig:()=>({
        screenInterpolator:CardStackStyleInterpolator.forHorizontal,
    })
}

修改页面的跳转动画

如何将安卓的跳转动画改成iOS那样,react-navigation一共提供了4种跳转动画:
1、从右向左: forHorizontal;
2、从下向上: forVertical;
3、安卓那种的从下向上: forFadeFromBottomAndroid;
4、无动画: forInitial。

但因为库的限制,想实现某些页面使用某种动画还是很难的,只能通过Demo中提供的笨方法来实现。

首先还是导入react-navigation中的方法

import CardStackStyleInterpolator from 'react-navigation/src/views/CardStack/CardStackStyleInterpolator';

如果要改变跳转动画只能在StackNavigator中实现transitionConfig方法

const MainStack = StackNavigator({
    Main:{
        screen:Main,
    },
},{
    // mode:'modal',
    headerMode: 'screen',
    transitionConfig:()=>({
     // 只要修改最后的forVertical就可以实现不同的动画了。
      screenInterpolator:CardStackStyleInterpolator.forVertical,
    })
});

goBack返回指定页面

react-navigation目录下src/routers/StackRouter.js

iif (action.type === NavigationActions.BACK) {
    let backRouteIndex = null;
    if (action.key) {

      const backRoute = state.routes.find(
        /* $FlowFixMe */
        /* 修改源码 */
        route => route.routeName === action.key
        /* (route: *) => route.key === action.key */
      );
      /* $FlowFixMe */
      console.log('backRoute =====',backRoute);
      backRouteIndex = state.routes.indexOf(backRoute);
      console.log('backRoute =====',backRouteIndex);
    }
    if (backRouteIndex == null) {
      return StateUtils.pop(state);
    }
    if (backRouteIndex >= 0) {
      return {
        ...state,
        routes: state.routes.slice(0, backRouteIndex+1),
        index: backRouteIndex - 1 + 1,
      };
    }
  }

注意:这样的修改源码之后,如果项目中使用Redux,并且启用了滑动返回,很会很大几率导致app卡死,所以并不太推荐这种方式,最好使用下面的方式

关于快速点击重复跳转的解决办法

如果想解决快速点击跳转的问题,需要修改部分源码。

修改react-navigation目录下,scr文件夹中的addNavigationHelpers.js文件,可以直接替换成下面的文本

 export default function(navigation: NavigationProp) {
  // 添加点击判断
  let debounce = true;
  return {
      ...navigation,
      goBack: (key?: ?string): boolean =>
          navigation.dispatch(
              NavigationActions.back({
                  key: key === undefined ? navigation.state.key : key,
              }),
          ),
      navigate: (routeName: string,
                 params?: NavigationParams,
                 action?: NavigationAction,): boolean => {
          if (debounce) {
              debounce = false;
              navigation.dispatch(
                  NavigationActions.navigate({
                      routeName,
                      params,
                      action,
                  }),
              );
              setTimeout(
                  () => {
                      debounce = true;
                  },
              500,
              );
              return true;
          }
          return false;
      },
    /**
     * For updating current route params. For example the nav bar title and
     * buttons are based on the route params.
     * This means `setParams` can be used to update nav bar for example.
     */
    setParams: (params: NavigationParams): boolean =>
      navigation.dispatch(
        NavigationActions.setParams({
          params,
          key: navigation.state.key,
        }),
      ),
  };
}

安卓上,使用TextInput的时候会让TabBar顶起来的解决办法

最简单的解决办法就是在android目录中,添加一句话

目录:android/app/src/main/AndroidManifest.xml中,添加

android:windowSoftInputMode="stateAlwaysHidden|adjustPan|adjustResize"

安卓返回键在react-navigation中的正常监听

之前使用Navigator的时候,可以通过下面的方法实现监听安卓的返回键,但使用了react-navigation后,会很迷茫,不知该怎么监听了。

Navigator的方法

componentWillMount() {
    if (Platform.OS === 'android') {
      BackAndroid.addEventListener('hardwareBackPress', this.onBackAndroid);
    }
  }
componentWillUnmount() {
    if (Platform.OS === 'android') {
      BackAndroid.removeEventListener('hardwareBackPress', this.onBackAndroid);
    }
  }
onBackAndroid = () => {
    const nav = this.navigator;
    const routers = nav.getCurrentRoutes();
    if (routers.length > 1) {
      nav.pop();
      return true;
    }
    return false;
  };
  ……
}

react-navigation的方式

componentWillMount() {
    if (Platform.OS === 'android') {
        BackHandler.addEventListener('handwareBackPress',this.onBackAndroid)
    }
  }
componentWillUnmount() {
    if (Platform.OS === 'android') {
        BackHandler.addEventListener('handwareBackPress',this.onBackAndroid)
    }
  }
onBackAndroid = () => {
    const routers = nav.getCurrentRoutes();
    if (routers.length > 1) {
      return true;
    }
    return false;
  };
  ……
}

// 在跳转之后的页面中
onBackAndroid = ()=> {

    const {routes} = this.props;
    console.log(routes);
    // alert(routes)
    if (routes.length > 1) {
        // 因为其他页面获得不到this.props,所以只能每个页面都写这个方法。
        this.props.navigation.goBack();
        return true;
    }
}

你可能感兴趣的:(react-navigation相关bug的解决)