因为第一次使用react-native开发电视应用,也是个新手,所以在这方面比较菜,看了很久官网,官网简简单单一串代码,对于初次接触的我表示很头大,可能是使用RN开发电视应用的,网上找了很久没有合适的例子,也没有相关教程视频。最后在GitHub上面找了一个demo研究了一番(附上地址:https://github.com/dev-seb/react-native-tv-demo),可以直接下载这个例子打包安装到TV上。另外一个小例子:https://github.com/avkan1087/react-native-android-tv/blob/master/App.js

之后自己根据demo做的时候,输入账号密码登录到首页,发现焦点是很乱的,因为Android TV每个页面有每个页面的焦点事件,所以我在首页点击的时候,发现弹出了输入框,我的首页里面并没有任何输入框,说明焦点跑到了之前的登录页,可是我在componentWillUnmount() 钩子函数里面已经卸载了,为什么焦点还是跑到了这里,这个问题困扰了我很久。

后来才发现,我在登录页跳转到首页的时候是使用navigation.push跳到首页,而使用push的话这个页面的componentWillUnmount() 是不会执行的,这就是造成了跳到了首页但是登录页面焦点并没有卸载,所以在首页的时候我的焦点会跳到登录页。

于是我最后采用了replace替换了push,replace会替换当前路由,push是添加路由,所以replace就可以卸载了登录页面的焦点事件,在跳到首页的时候就可以找到焦点了。

图片.png

按照这个思路,在使用焦点事件的时候,要注意自己的焦点是否符合当前页面的焦点,是否还存在其他页面的焦点,如果存在则想办法卸载其他页面的焦点,也可以通过DeviceEventEmitter来判断卸载焦点

附上登录页代码:

/*
*登录
* */
import React, {Component} from 'react';
import Console from "../common/Console";
import {
View,
Text,
StyleSheet,
TextInput,
Image,
TouchableOpacity,
NativeModules,
TVEventHandler
} from 'react-native'
import Util from '../common/util'
import request from '../constant/request'
import * as URLconstant from '../constant/URLconstant'
import Toast from '../common/ToastUtil'
import MyStroage from '../common/myStroage';
import Loading from 'react-native-easy-loading-view';
export default class login extends Component {
static EVENT_LINES = 3;
constructor(props) {
super(props);
this.tvEventHandler = null;
this.inputTextRef1 = React.createRef();
this.inputTextRef2 = React.createRef();
this.state = {
handlerStatus: 'disabled',
tvEventStack: [],
componentEventStack: [],
username:'',
password:'',
textInputFocused1: false,
textInputFocused2: false,
textInputFocused3: false,
};
}
componentDidMount() {
this.setState({
handlerStatus: 'enabled'
});
this.tvEventHandler = new TVEventHandler();
this.tvEventHandler.enable(
this, this.tvEventListener.bind(this)
);
}
tvEventListener(component, event) {
console.log("tvEventListener:", event.eventType);
// Get event stack
let tvEventStack = this.state.tvEventStack;
if(tvEventStack.length >= login.EVENT_LINES) {
tvEventStack.shift();
}
tvEventStack.push(JSON.stringify(event));
this.setState({
tvEventStack: tvEventStack
});
}
//启用第一个Input的遥控
componentEventListener(event) {
console.warn("componentEventListener:", event);
// Get event stack
if(event==='input1'){
this.inputTextRef1.focus()
}else if(event==='input2'){
this.inputTextRef2.focus()
}
let componentEventStack = this.state.componentEventStack;
if(componentEventStack.length >= login.EVENT_LINES) {
componentEventStack.shift();
}
componentEventStack.push(JSON.stringify(event));
this.setState({
componentEventStack: componentEventStack
});
}
//禁用这个页面的遥控
// _disableTVEventHandler() {
// if (this.tvEventHandler) {
// this.tvEventHandler.disable();
// delete this.tvEventHandler;
// }
// this.setState({
// handlerStatus: 'disabled',
// tvEventStack: [],
// componentEventStack: [],
// });
// }
onChangeUserNameText(txt){
// Console.log('usertxt===',txt)
this.setState({
username:txt
})
}
onChangePwdText(txt){
// Console.log('pwd===',txt)
this.setState({
password:txt
})
}
login(event){
let componentEventStack = this.state.componentEventStack;
if(componentEventStack.length >= login.EVENT_LINES) {
componentEventStack.shift();
}
componentEventStack.push(event);
this.setState({
componentEventStack: componentEventStack
});
Loading.showHud('正在登录...',)
// this.props.navigation.push('Home',{navigation:this.props.navigation})
// Console.log(this.state.username)
// Console.log(this.state.password)
let username = this.state.username
let password =this.state.password
if(!username){
Toast.show('请输入用户名')
return false
}
if(!password){
Toast.show('请输入密码')
return false
}
let datakey={
user_name:username,
pwd:password,
newSas:1
}
// let datakey = [];
// datakey['user_name'] = username;
// datakey['pwd'] = password;
// datakey['newSas'] = 1;
let url = URLconstant.USER_LOGIN_URL
// Console.log('登录请求路径与参数===',url,'params===',datakey)
// Console.log('params=====',datakey)
request.post(url,datakey,this.loginSuc.bind(this),this.errorCallback.bind(this))
}
loginSuc(datas){
// Console.log('登录返回数据====',JSON.stringify(datas))
// LOG('datas=='+JSON.stringify(datas))
if(datas.status==0){
MyStroage.saveStorage('userinfo', JSON.stringify(datas));
this.props.navigation.replace('Home',{navigation:this.props.navigation})
this.props.loginSuc()
}else{
Toast.show(datas.msg)
}
}
errorCallback(err){
}
render() {
return(
ref={(view)=>{Loading.loadingDidCreate(view)}} // 必须调用
// top={-400}
// offsetY={-150}
hudStyle={{position:'absolute',top:'4%',left:'4%'}}
hudTextStyle={{ fontSize : 16, color: 'red' }}
hudBackgroundColor={'transparent'} // hud全局背景色
/>
门店账号登录
商户id
onFocus={this.componentEventListener.bind(this,'input1')}
>
styles.cell_input_view,
this.state.textInputFocused1 && styles.textInputContainerFocused]}>
ref={ref => this.inputTextRef1 = ref}
onFocus={()=>this.setState({textInputFocused1: true})}
onBlur={()=>this.setState({textInputFocused1: false})}
onChangeText={(txt)=>{this.onChangeUserNameText(txt)}}
autoFocus={true}
clearButtonMode={'always'}
placeholder='请输入账号'
placeholderTextColor={'#696969'}
style={styles.input_view}
/>
登录密码
onFocus={this.componentEventListener.bind(this,'input2')}
>
styles.cell_input_view,
this.state.textInputFocused2 && styles.textInputContainerFocused]}>
ref={ref => this.inputTextRef2 = ref}
onFocus={()=>this.setState({textInputFocused2: true})}
onBlur={()=>this.setState({textInputFocused2: false})}
onChangeText={(txt)=>{this.onChangePwdText(txt)}}
// autoFocus={true}
clearButtonMode={'always'}
placeholder='请输入账号'
placeholderTextColor={'#696969'}
style={styles.input_view}
/>
onPress={this.login.bind(this)}
onFocus={()=>this.setState({textInputFocused3: true})}
onBlur={()=>this.setState({textInputFocused3: false})}
>
styles.btn,
this.state.textInputFocused3 && styles.textInputContainerFocused]}>
前往登录>>
)
}
componentWillUnmount() {
// this._disableTVEventHandler();
if (this.tvEventHandler) {
this.tvEventHandler.disable();
delete this.tvEventHandler;
}
this.setState({
handlerStatus: 'disabled',
tvEventStack: [],
componentEventStack: [],
});
if(this.inputTextRef1) {
this.inputTextRef1.clear();
}
if(this.inputTextRef2) {
this.inputTextRef2.clear();
}
}
}
var styles = StyleSheet.create({
container:{
alignItems:'center',
justifyContent:'center',
height:'100%',
},
logo:{
height:150,
width:150,
// width: Util.size.width - 30,
borderRadius:75,
borderWidth: 1,
borderColor: '#000',
overflow:'hidden',
position:'relative'
},
logoTitle:{
marginTop:20,
fontSize: 24
},
cell:{
// backgroundColor:'red',
flexDirection:'row',
width: Util.size.width-150,
alignItems: 'center',
justifyContent: 'flex-end',
marginTop:20
},
cellTitle:{
fontSize:18,
marginRight:15
},
cell_input_view: {
borderWidth: 1,
borderColor: "#ccc",
width: Util.size.width - 250,
height: 40,
},
input_view: {
flex: 1,
padding: 0,
textAlign: 'left',
marginLeft:10,
fontSize: 16,
color: "#333",
},
btn:{
width: Util.size.width - 200,
height:40,
backgroundColor:'#ccc',
justifyContent:'center',
alignItems:'center',
marginTop:20
},
//焦点聚焦时输入框的颜色
textInputContainerFocused: {
borderColor: '#61dafb'
},
})