2019-10-11 17:20:20 ywl570717586 阅读数 228
  • 完全征服React Native

    React Native是Facebook于2015年推出的跨平台开发工具,可用于开发Android和iOS App,并且同时具有混合开发的优点(热更新,跨平台)以及本地App的性能。 本课程采用新的ES6开发,主要内容包括ReactNative的基础知识,ReactNative的布局,组件,API,封装本地API和组件,发布ReactNative App,本地与ReactNative深度结合

    58300 人正在学习 去看看 李宁

在使用滚轮插件时,如ScrollView、KeyboardAwareScrollView等待,会出现点击该页面的按钮需要点两次才能触发。

使用keyboardShouldPersistTaps={true}方法即可。

代码如下:

<KeyboardAwareScrollView style={{flex: 1}}>

改为

<KeyboardAwareScrollView style={{flex: 1}} keyboardShouldPersistTaps={true}>

即可。

2018-08-14 09:09:21 qq_26651349 阅读数 422
  • 完全征服React Native

    React Native是Facebook于2015年推出的跨平台开发工具,可用于开发Android和iOS App,并且同时具有混合开发的优点(热更新,跨平台)以及本地App的性能。 本课程采用新的ES6开发,主要内容包括ReactNative的基础知识,ReactNative的布局,组件,API,封装本地API和组件,发布ReactNative App,本地与ReactNative深度结合

    58300 人正在学习 去看看 李宁

React Native StackNavigator Android 物理返回按钮处理(这里只做按两次退出应用的处理)
一、首先引入BackHandler
import { StackNavigator } from ‘react-navigation’;//引入StackNavigator
import { BackHandler,ToastAndroid ,View} from ‘react-native’;//由于这儿用到了Toast提示,便一起引入

    首先列出项目入库文件App.js代码:
    import {BackHandler, ToastAndroid ,View ,Platform} from 'react-native';
    import {StackNavigator} from 'react-navigation';
    import HomeScreen from './js/screen/HomeScreen';
    import MineScreen from "./js/screen/MineScreen";
    var stateIndex, oStateIndex = false, goBack = false;
    var lastBackPressed;
    var current = true;

    type Props = {};
    type State = {};
    export default class App extends PureComponent<Props, State> {
        componentWillUnmount() {//注册返回按钮事件监听
            this.backHandler && this.backHandler.remove();
        }

        componentDidMount() {//移除返回按钮事件监听
            this.backHandler = BackHandler.addEventListener('hardwareBackPress',
            this.backOption);
        }

        backOption = () => {
            if (current == true) {//如果是在首页
                if (lastBackPressed && lastBackPressed + 2000 >= Date.now()) {
                    //最近2秒内按过back键,可以退出应用。
                    BackHandler.exitApp();
                    return false;
                }

                lastBackPressed = Date.now();
                ToastAndroid.show('再按一次退出应用', ToastAndroid.SHORT);
                return true;
             } else {
                if (this.props && this.props.navigation) {
                this.props.navigator.pop();
             }
            }
       }

        render() {
            return (
                <View style={flex:1}
                 <Navigator
                        onNavigationStateChange={(prevState, newState, action) => {//注册路由改变监听事件
                            if (newState && newState.routes[newState.routes.length - 1].routeName == 'HomeScreen') {//如果当前路由是Home页面,则需要处理安卓物理返回按键。
                                current = true;
                            } else {
                                current = false;
                            }
                    }}                 
                ></Navigator>
            </View>
        );
    }
}

    const Navigator = StackNavigator(
    {
        HomeScreen: {screen: HomeScreen},
        MineScreen: {screen: MineScreen},
    },
    {
        initialRouteName: 'HomeScreen',
        navigationOptions: {
            header: null,
            gesturesEnabled: Platform.OS == 'ios' ? true : false,
            headerTintColor: '#333333',
            headerBackTitle: null
        },
    }
)

二、自己根据需求编写Home.js和MineScreen.js文件,这里就不列出代码了。
附录:如果有的童鞋是用的Navigator导航,可以使用如下方式:

    componentWillMount() {
        BackHandler.addEventListener('hardwareBackPress', this.onBackAndroid);
    }

    componentWillUnmount() {
        BackHandler.removeEventListener('hardwareBackPress', this.onBackAndroid);
    }
    onBackAndroid = () => {
        const nav = this.props.navigator;
        const routers = nav.getCurrentRoutes();
        if (routers.length > 1) {
          nav.pop();
          return true;
        }else {
            if (lastBackPressed && lastBackPressed + 2000 >= Date.now()) {
                   return false;
               }
               lastBackPressed = Date.now();
               ToastAndroid.show('再按一次退出应用',1000);
               return true;
            }
    };

留言:本篇博客主要记录自己在第一次处理安卓返回按钮监听和处理上的一些方式和技巧。
**附言:有的Android同鞋存在确实添加了BackHandler监听,在debug apk包下也能正常监听安卓手机的返回按钮,页面能够正常返回。

但是:在release包下按安卓物理返回键却会直接退出app。

针对这种情况,我还没找到更好的解决方法,这里只贴出我个人的处理办法:
第一步:创建一个全局的数据存储类。

DataObject.js
代码如下:
const object = {
    //用来保存App.js所在类对象
    APP:{},

};
export default object;

第二步:在App.js的构造方法中为DataObject类中的App变量赋值。
第三步:在/node_modules/react-native/Libraries/Utilities/BackHandler.android.js
文件中找到该处代码:
首先引入我们定义的DataObject类

    import DataObject from '../../../../js/localData/DataObject'//引入我们定义的DataObject类
    RCTDeviceEventEmitter.addListener(DEVICE_BACK_EVENT, function () {
    let invokeDefault = true;
    const subscriptions = Array.from(_backPressSubscriptions.values()).reverse();
    for (let i = 0; i < subscriptions.length; ++i) {
        if (subscriptions[i]()) {
            invokeDefault = false;
            break;
        }
    }

    if (invokeDefault) {
        //此处删除系统原有代码,添加如下代码
        //TODO
        if(DataObject.APP != undefined && DataObject.APP.backOption != undefined){//判断如果DataObject.APP未定义则不执行。
                DataObject.APP.backOption()//调用APP.js中我们的backOption方法。
            }
        }
    });

App.js类所有代码:

import DataObject from './js/localData/DataObject';
import {BackHandler, ToastAndroid ,View ,Platform} from 'react-native';
import {StackNavigator} from 'react-navigation';
import HomeScreen from './js/screen/HomeScreen';
import MineScreen from "./js/screen/MineScreen";
var stateIndex, oStateIndex = false, goBack = false;
var lastBackPressed;
var current = true;

type Props = {};
type State = {};
export default class App extends PureComponent<Props, State> {
    //构造方法
    constructor(props){
        super(props)
        DataObject.APP = this //为DataObject类中的App变量赋值
    }
    backOption = () => {
        if (current == true) {//如果是在首页
            if (lastBackPressed && lastBackPressed + 2000 >= Date.now()) {
                //最近2秒内按过back键,可以退出应用。
                BackHandler.exitApp();
                return false;
            }

            lastBackPressed = Date.now();
            ToastAndroid.show('再按一次退出应用', ToastAndroid.SHORT);
            return true;
         } else {
            if (this.props && this.props.navigation) {
            this.props.navigator.pop();
         }
        }
   }

    render() {
        return (
            <View style={flex:1}
             <Navigator
                    onNavigationStateChange={(prevState, newState, action) => {//注册路由改变监听事件
                        if (newState && newState.routes[newState.routes.length - 1].routeName == 'HomeScreen') {//如果当前路由是Home页面,则需要处理安卓物理返回按键。
                            current = true;
                        } else {
                            current = false;
                        }
                }}                 
            ></Navigator>
        </View>
    );
}
const Navigator = StackNavigator(
{
    HomeScreen: {screen: HomeScreen},
    MineScreen: {screen: MineScreen},
},
{
    initialRouteName: 'HomeScreen',
    navigationOptions: {
        header: null,
        gesturesEnabled: Platform.OS == 'ios' ? true : false,
        headerTintColor: '#333333',
        headerBackTitle: null
    },
}

)
**

到此为止,解决完Android物理返回键在使用StackNavigator导航器时存在的问题。

2016-10-25 17:15:38 u013751625 阅读数 4189
  • 完全征服React Native

    React Native是Facebook于2015年推出的跨平台开发工具,可用于开发Android和iOS App,并且同时具有混合开发的优点(热更新,跨平台)以及本地App的性能。 本课程采用新的ES6开发,主要内容包括ReactNative的基础知识,ReactNative的布局,组件,API,封装本地API和组件,发布ReactNative App,本地与ReactNative深度结合

    58300 人正在学习 去看看 李宁
<TextInput
  ref={component => this._textInput = component}
  onSubmitEditing={this._onSubmitEditing.bind(this)}
  onEndEditing={this._onPressSearch.bind(this)}
  returnKeyType='search'
  style={styles.inputText}/>

  _onSubmitEditing(){
    this._textInput.blur();
  }
  _onPressSearch(event){
    console.log(event.nativeEvent.text);
  }
参考链接http://stackoverflow.com/questions/38710253/onsubmitediting-is-called-twice-when-keyboard-is-dismissed
2018-03-31 13:38:59 gzp_xiaomaolv 阅读数 1162
  • 完全征服React Native

    React Native是Facebook于2015年推出的跨平台开发工具,可用于开发Android和iOS App,并且同时具有混合开发的优点(热更新,跨平台)以及本地App的性能。 本课程采用新的ES6开发,主要内容包括ReactNative的基础知识,ReactNative的布局,组件,API,封装本地API和组件,发布ReactNative App,本地与ReactNative深度结合

    58300 人正在学习 去看看 李宁
在React native项目开发中,当用户点击按钮navigator执行页面跳转的时候,如果连续按了两下,竟然会push两个相同的页面,造成线程卡顿崩溃的现象。在Android我们通过设置launchMode可以轻松的避免出现这样的问题,但在react native中并没有launchMode这类似的属性方法供我们设置。既然执行页面跳转是navigator负责,那我们就从navigator入手。我的思路是这样的,在执行页面跳转的时候,判断路由栈里面是否已经存在当前页面(判断两个页面是否相同我比较的是name,当然你也可以设置比较Id),如果存在,return不执行跳转页面操作,否则跳转。

从react native 官网中获取到navigator提供的方法有如下几种:

getCurrentRoutes() - 获取当前栈里的路由,也就是push进来,没有pop掉的那些。

jumpBack() - 跳回之前的路由,当然前提是保留现在的,还可以再跳回来,会给你保留原样。

jumpForward() - 上一个方法不是调到之前的路由了么,用这个跳回来就好了。

jumpTo(route) - 跳转到已有的场景并且不卸载。

push(route) - 跳转到新的场景,并且将场景入栈,你可以稍后跳转过去

pop() - 跳转回去并且卸载掉当前场景

replace(route) - 用一个新的路由替换掉当前场景

replaceAtIndex(route, index) - 替换掉指定序列的路由场景

replacePrevious(route) - 替换掉之前的场景

resetTo(route) - 跳转到新的场景,并且重置整个路由栈

immediatelyResetRouteStack(routeStack) - 用新的路由数组来重置路由栈

popToRoute(route) - pop到路由指定的场景,在整个路由栈中,处于指定场景之后的场景将会被卸载。

popToTop() - pop到栈中的第一个场景,卸载掉所有的其他场景。 可以发现getCurrentRoutes()方法能提供给我们当前路由栈所有存在的页面,那这就好办了,首先看下我跳转页面的写法(部分代码片段):

//配置切换页面的动画
 
_configureScene(route) {
 
return Navigator.SceneConfigs.FadeAndroid;
 
}
 
//切换的页面
 
_renderScene(route, navigator) {
 
this._navigator = navigator;
 
let Component = route.component;
 
return
 
}
 
render() {
 
let defaultName = '***';
 
let defaultComponent = ***;
 
return (
 
 
configureScene={(route) => this._configureScene(route)}
 
renderScene={(route, navigator) => this._renderScene(route, navigator)}/>
 
);
 
}

路由(route)是navigator用来识别渲染场景的一个对象,我们可以给他设置相关属性,我设置了两个属性name,component,跳转页面的名字,跳转目标的页面,然后在跳转的时候判断页面是否相同,我单独写了个跳转的方法如下,只需要将跳转的信息传入进来即可实现页面跳转:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
//统一的跳转方法
 
static pushPage(navigator, name, component, params) {
 
const routes = navigator.getCurrentRoutes();
 
for (let i = 0; i < routes.length; i++) {
 
if (name === routes[i].name) {
 
return;
 
}
 
}
 
InteractionManager.runAfterInteractions(() => {
 
navigator.push({
 
name: name,
 
component: component,
 
params: params
 
});
 
});
 
}

这样无论用户快速点击多少次,navigator都只会push一个页面进入路由栈,完美解决了自己的问题。



2017-04-19 10:33:41 SpicyBoiledFish 阅读数 16126
  • 完全征服React Native

    React Native是Facebook于2015年推出的跨平台开发工具,可用于开发Android和iOS App,并且同时具有混合开发的优点(热更新,跨平台)以及本地App的性能。 本课程采用新的ES6开发,主要内容包括ReactNative的基础知识,ReactNative的布局,组件,API,封装本地API和组件,发布ReactNative App,本地与ReactNative深度结合

    58300 人正在学习 去看看 李宁

Bug情况描述:React Native项目中,点击按钮A出现弹框浮层,弹框中需要TextInput输入数字,键盘浮起来;这时候点击 取消按钮L 或者 确定按钮R,只是让键盘收起,但是并没有触发 取消 或 确定 的事件,必须要再点击第二次才可以触发。另外,当输入框有焦点的情况下,点击 屏幕任意位置(除了键盘),可使键盘收起隐藏;

期待效果:当输入框输完数字后,光标焦点仍然存在,键盘也未消失,这时候点击一次取消按钮L即可让弹框层和键盘同时隐藏;点击一次确定按钮R即可跳转到另一个页面;




尝试的解决方案和解决思路:

1. 用ScrollView包裹TextInput,并且使用keyboardShouldPersistTaps属性,无效:




2. 给TextInput加上ref属性,然后在点击事件中加上this.refs.xxx.blur()让其主动失去焦点,因为失去焦点键盘会自动收起。无效。





3.使用TextInput中的onEndEditing结束编辑属性,有效。


<TextInput
   style={styles.input1}
   placeholder="请输入短信验证码"
   placeholderTextColor={Color.CM_InputTextColor}
   maxLength={6}
   keyboardType={'numeric'}
   onChangeText={(code) => {
      if (this.state.jdAuth) {
         Config.JDMobileCode = code;
      }else {
         Config.ChinaMobileCode = code;
      }
      this.setState({
         password: code
      })
   }}
   value={this.state.password}
   onEndEditing={()=>{this.endEdit()}}
/>



由于我这里是有取消和确定两个按钮需要触发事件的,我在初始化的时候定义了一个标志位变量,用来表示点击的是左按钮还是右按钮,然后在其相应的事件中赋值不同标志位。在执行了endEdit()函数中判断标志位的值,进而执行取消事件还是确定事件,即可。

endEdit(){
        if(this.state.isLeft==1){
            this.hideModal();
        }else if(this.state.isLeft==2){
            this.btnOK();
        }
    }


注:目前仍存在一点问题,有更好的解决办法,日后会持续更新。。。也欢迎大佬们留言板分享最佳解决方案



==============================更新======================================

上次说的还有点问题,是第二次进入的时候,第一次点击确定或者取消按钮可以触发。现在bug解决了,添加以下代码:

1.在TextInput组件中加入onSubmitEditing属性,且执行让键盘主动消失的函数;

<TextInput
    ref="inputWR"
    style={styles.input1}
    placeholder="请输入短信验证码"
    placeholderTextColor={Color.CM_InputTextColor}
    maxLength={6}
    keyboardType={'numeric'}
    onChangeText={(code) => {
        if (this.state.jdAuth) {
            Config.JDMobileCode = code;
        }
        else {
            Config.ChinaMobileCode = code;
        }
        this.setState({
            password: code
        })
    }}
    value={this.state.password}
    onEndEditing={()=> {
        this.testWR()
    }}
    onSubmitEditing={()=>{this.testBlur()}}
/>

2.写testBlur函数:

 testBlur(){
        this.refs.inputWR.blur();
}

现在测试完美了~~~~~~


没有更多推荐了,返回首页