完整代码(不可完全复制,仅供参考逻辑)
/**
* Created by apple on 2016/11/7.
*/
import React,{ Component } from 'react';
import {
View,
Navigator,
StyleSheet,
Image,
TouchableOpacity,
Alert,
Text,
TouchableHighlight,
PanResponder,
Animated,
Easing
} from 'react-native';
import Language from '../../common/language';
import Nav from '../../common/MineNav';
import Util from '../../common/common';
import Gsoap from '../../common/gsoap';
import * as TYPES from '../../common/types';
var TouchRemote = React.createClass({
debugMsg: true,
_panResponder: null,
movePos: [],
bounceValue: new Animated.Value(0),
getDefaultProps: function () {
return ({
controlType: "keyBoardType",
connectSTBToken: {}
});
},
getInitialState: function () {
return {
powerState: false,
homeState: false,
keyBoard: false,//up down left right ok
menuState: false,
backState: false,
volumeUpState: false,
volumeDownState: false
};
},
componentWillMount: function () {
this.console("componentWillMount===controlType:" + this.props.controlType + ";connectSTBToken:" + JSON.stringify(this.props.connectSTBToken));
this._panResponder = PanResponder.create({
// 要求成为响应者:
onStartShouldSetPanResponder: (evt, gestureState) => true,
onStartShouldSetPanResponderCapture: (evt, gestureState) => true,
onMoveShouldSetPanResponder: (evt, gestureState) => true,
onMoveShouldSetPanResponderCapture: (evt, gestureState) => true,
onPanResponderGrant: (evt, gestureState) => {
// 开始手势操作。给用户一些视觉反馈,让他们知道发生了什么事情!
// gestureState.{x,y}0 现在会被设置为0
this.movePos = [];
this.console("touch start===X:" + gestureState.x0 + "===Y:" + gestureState.y0);
this.movePos.push(Math.floor(gestureState.x0), Math.floor(gestureState.y0));
},
onPanResponderMove: (evt, gestureState) => {
// 最近一次的移动距离为gestureState.move{X,Y}
// 从成为响应者开始时的累计手势移动距离为gestureState.d{x,y}
},
onPanResponderTerminationRequest: (evt, gestureState) => true,
onPanResponderRelease: (evt, gestureState) => {
// 用户放开了所有的触摸点,且此时视图已经成为了响应者。
// 一般来说这意味着一个手势操作已经成功完成。
this.console("touch end===moveX:" + gestureState.moveX + "===moveY:" + gestureState.moveY);
this.movePos.push(Math.floor(gestureState.moveX), Math.floor(gestureState.moveY));
this.moveActionEnd(this.movePos);
},
onPanResponderTerminate: (evt, gestureState) => {
// 另一个组件已经成为了新的响应者,所以当前手势将被取消。
this.console("what???");
},
onShouldBlockNativeResponder: (evt, gestureState) => {
// 返回一个布尔值,决定当前组件是否应该阻止原生组件成为JS响应者
// 默认返回true。目前暂时只支持android。
return true;
}
});
},
actAnimationStart: function () {
this.console("actAnimationStart");
// 可选的基本动画类型: spring, decay, timing
this.bounceValue.setValue(0);
Animated.timing(
/**
* 将`bounceValue`值动画化的意思是,在以Animated为前缀名的组件中,比如此例中的Animated.Image,
* 将`bounceValue`值所赋予的样式就是会跟随`bounceValue`值的变化而改变样式的,
* `bounceValue`值的改变在Animated.timing()函数中改变,此例中`bounceValue`值将从0变化至1,变化的时间为200ms
* 也就是说,以Animated为前缀名的组件Image(Animated.Image),将在200ms的时间内,透明度从0变化至1
* */
this.bounceValue,// 将`bounceValue`值动画化
{
toValue: 1,// 将其值以动画的形式改到一个较小值
duration: 180,
easing: Easing.ease
}
).start(() => {
this.actAnimationEnd()
});
},
actAnimationEnd: function () {
this.console("actAnimationEnd");
// 可选的基本动画类型: spring, decay, timing
this.bounceValue.setValue(1);
Animated.timing(
this.bounceValue,// 将`bounceValue`值动画化
{
toValue: 0,// 将其值以动画的形式改到一个较小值
duration: 300,
easing: Easing.ease
}
).start();
},
moveActionEnd: function (movePos) {
this.console("movePos" + JSON.stringify(movePos));
let [sX, sY, eX, eY] = movePos;
let x = eX - sX, y = eY - sY, direction;
let z = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
if ((eX == 0 && eY == 0) || z < 20) {//移动距离小于20像素视为点击
direction = -1;
} else {
direction = Math.round(( ( ( Math.atan2(y, x) * ( 180 / Math.PI ) ) + 180 ) / 90) + 3) % 4;
}
this.console("角度:" + direction);// 点击(-1) 上(0) 右(1) 下(2) 左(3)
switch (direction) {
case -1:
this.keyPressIn(6);
break;
case 0:
this.keyPressIn(2);
break;
case 1:
this.keyPressIn(5);
break;
case 2:
this.keyPressIn(3);
break;
case 3:
this.keyPressIn(4);
break;
default :
break;
}
},
keyPressIn: function (keyCode) {
let _keyString = '';
switch (keyCode) {
case 0://POWER
this.setState({powerState: true});
_keyString = 'POWER';
break;
case 1://HOME
this.setState({homeState: true});
_keyString = 'HOME';
break;
case 2://UP
this.setState({keyBoard: 'up'});
this.actAnimationStart();
_keyString = 'UP';
break;
case 3://DOWN
this.setState({keyBoard: 'down'});
this.actAnimationStart();
_keyString = 'DOWN';
break;
case 4://LEFT
this.setState({keyBoard: 'left'});
this.actAnimationStart();
_keyString = 'LEFT';
break;
case 5://RIGHT
this.setState({keyBoard: 'right'});
this.actAnimationStart();
_keyString = 'RIGHT';
break;
case 6://CENTER
this.setState({keyBoard: 'center'});
this.actAnimationStart();
_keyString = 'CENTER';
break;
case 7://RED
break;
case 8://MENU
this.setState({menuState: true});
_keyString = 'MENU';
break;
case 9://BACK
this.setState({backState: true});
_keyString = 'BACK';
break;
case 10://VOLUME_UP
this.setState({volumeUpState: true});
_keyString = 'VOLUME_UP';
break;
case 11://VOLUME_DOWN
this.setState({volumeDownState: true});
_keyString = 'VOLUME_DOWN';
break;
default:
break;
}
this.console("userID:" + this.props.connectSTBToken.userId + ";stbToken:" + this.props.connectSTBToken.userToken + ";keyCode:" + keyCode+ ";keyString:" + _keyString);
if (this.props.connectSTBToken.userId && this.props.connectSTBToken.userToken) {
let {userId, userToken} = this.props.connectSTBToken;
let that = this;
Gsoap.sendRemoteControlKeyOnSTBDevice(userId, userToken, _keyString, (statusCode, statusMessage) => {
that.console("keyPressIn===statusCode:" + statusCode + ";statusMessage:" + statusMessage);
switch (statusCode) {
case 2000:
//success
break;
default:
break;
}
});
}
},
keyBoardImg: function () {
let keyBoardImg = ' ';
switch (this.state.keyBoard) {
case 'up':
keyBoardImg = TYPES.REMOTE_TOUCH_UP;
break;
case 'down':
keyBoardImg = TYPES.REMOTE_TOUCH_DOWN;
break;
case 'left':
keyBoardImg = TYPES.REMOTE_TOUCH_LEFT;
break;
case 'right':
keyBoardImg = TYPES.REMOTE_TOUCH_RIGHT;
break;
case 'center':
keyBoardImg = TYPES.REMOTE_TOUCH_OK;
break;
}
return keyBoardImg;
},
render: function () {
let keyBoardImg = this.keyBoardImg();
return (
<View style={styles.wrap}>
{/*顶上停止按键以及主页按键*/}
<View style={styles.topContainer}>
{/*STOP*/}
<TouchableOpacity activeOpacity={1}
onPressIn={()=>{this.keyPressIn(0)}}
onPressOut={()=>{this.setState({powerState:false})}}>
<Image style={styles.StopHomeIcon}
source={{uri: this.state.powerState ? TYPES.REMOTE_STOP_FOCUS : TYPES.REMOTE_STOP}}></Image>
</TouchableOpacity>
{/*HOME*/}
<TouchableOpacity activeOpacity={1}
onPressIn={()=>{this.keyPressIn(1)}}
onPressOut={()=>{this.setState({homeState:false})}}>
<Image style={styles.StopHomeIcon}
source={{uri: this.state.homeState ? TYPES.REMOTE_HOME_FOCUS : TYPES.REMOTE_HOME}}/>
</TouchableOpacity>
</View>
{/*中间上下左右键盘,申请权限等功能键*/}
<View style={[styles.touchContainer, {backgroundColor: '#e2eaea'}]}
{...this._panResponder.panHandlers}>
<Animated.Image
style={[styles.middleContainer_BG, {opacity: this.bounceValue}]}
source={{uri: keyBoardImg}}/>
</View>
{/*底下音量加减,返回菜单等功能按键*/}
<View style={styles.bottomContainer}>
<View style={styles.bottomToolWrap}>
<TouchableOpacity style={[styles.bottomIconStyle, {marginVertical: 5}]}
activeOpacity={1}
onPressIn={()=>{this.keyPressIn(9)}}
onPressOut={()=>{this.setState({backState:false})}}>
<Image style={styles.bottomIconStyle}
source={{uri: this.state.backState ? TYPES.REMOTE_BACK_FOCUS : TYPES.REMOTE_BACK}}/>
</TouchableOpacity>
<TouchableOpacity style={[styles.bottomIconStyle, {marginVertical: 5}]}
activeOpacity={1}
onPressIn={()=>{this.keyPressIn(10)}}
onPressOut={()=>{this.setState({volumeUpState:false})}}>
<Image style={styles.bottomIconStyle}
source={{uri: this.state.volumeUpState ? TYPES.REMOTE_VOLUMEA_FOCUS : TYPES.REMOTE_VOLUMEA}}/>
</TouchableOpacity>
<TouchableOpacity style={[styles.bottomIconStyle, {marginVertical: 5}]}
activeOpacity={1}
onPressIn={()=>{this.keyPressIn(8)}}
onPressOut={()=>{this.setState({menuState:false})}}>
<Image style={styles.bottomIconStyle}
source={{uri: this.state.menuState ? TYPES.REMOTE_MENU_FOCUS : TYPES.REMOTE_MENU}}/>
</TouchableOpacity>
</View>
<TouchableOpacity style={[styles.bottomIconStyle, {marginVertical: 5}]}
activeOpacity={1}
onPressIn={()=>{this.keyPressIn(11)}}
onPressOut={()=>{this.setState({volumeDownState:false})}}>
<Image style={styles.bottomIconStyle}
source={{uri: this.state.volumeDownState ? TYPES.REMOTE_VOLUMEP_FOCUS : TYPES.REMOTE_VOLUMEP}}/>
</TouchableOpacity>
</View>
</View>
);
},
console: function (msg) {
this.debugMsg ? console.log("+++xq debug+++touchRemote===" + msg + "===") : null;
}
});
const styles = StyleSheet.create({
wrap: {
flex: 1,
flexDirection: 'column',
justifyContent: 'flex-start',
alignItems: 'center',
paddingHorizontal: Util.screenWidth / 10,
paddingVertical: Util.screenHeight / 25,
backgroundColor: "#eaeff0"
},
topContainer: {
flexDirection: 'row',
justifyContent: 'space-between',
width: Util.screenWidth / 10 * 8,
paddingHorizontal: 15
},
StopHomeIcon: {
//13 : 7
width: Util.screenWidth / 7 * 1.6,
height: Util.screenWidth / 13 * 1.6
},
touchContainer: {
width: Util.screenWidth,
height: Util.screenWidth / 8 * 5 + Util.screenWidth / 11 * 1.2,
paddingHorizontal: 15,
marginTop: 15,
marginBottom: 15,
alignItems: 'center',
justifyContent: 'center'
},
middleContainer: {
flexDirection: 'row',
justifyContent: 'center',
width: Util.screenWidth / 10 * 8,
paddingHorizontal: 15,
marginVertical: 10
},
middleContainer_BG: {
width: Util.screenWidth / 8 * 5,
height: Util.screenWidth / 8 * 5,
flexDirection: 'column',
justifyContent: 'flex-start',
alignItems: 'center'
},
upIcon: {
flex: 1,
width: Util.screenWidth / 8 * 5 / 4 * 1.5
},
middleToolWrap: {
flex: 1,
flexDirection: 'row'
},
middleTool: {
flex: 1
},
dowIcon: {
flex: 1,
width: Util.screenWidth / 8 * 5 / 4 * 1.5
},
bottomContainer: {
width: Util.screenWidth / 8 * 5,
height: Util.screenWidth / 8 * 3.5,
flexDirection: 'column',
justifyContent: 'flex-start',
alignItems: 'center'
},
bottomIconStyle: {
//11 : 7
width: Util.screenWidth / 7 * 1.2,
height: Util.screenWidth / 11 * 1.2
},
bottomToolWrap: {
width: Util.screenWidth / 8 * 5,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between'
}
});
module.exports = TouchRemote;