大致思路:
- 使用 PanResponder api实现拖拽
- 使用Dimensions 获取屏幕宽度 判断拖拽边界处理
import { Dimensions, View, Text, TouchableHighlight, PanResponder, Animated, StyleSheet } from 'react-native'
const ScreenWidth = Dimensions.get('window').width
const ScreenHeight = Dimensions.get('window').height
const onlineIconHeight = 40 // 盒子自身高度
const onlineIconWidth = 40 // 盒子自身宽度
class AppWithNavigationState extends React.Component {
constructor (props) {
super(props)
this.state = {
pan: new Animated.ValueXY(),
panResponder: null,
left: ScreenWidth - onlineIconWidth,
bottom: 100
}
}
componentDidMount () {
this.onlineDrag()
}
onlineDrag = () => {
this._panResponder = PanResponder.create({
onStartShouldSetPanResponder: () => true,
onMoveShouldSetResponderCapture: () => true,
onMoveShouldSetPanResponderCapture: () => true,
// 用户开始触摸点
onPanResponderGrant: (e, gestureState) => {
this.startX = this.state.left // 起始位置
this.startY = this.state.bottom
},
// 用户开始移动
onPanResponderMove: (e, g) => {
let left = this.startX + g.dx // 距离左侧距离
let bottom = this.startY - g.dy // 距离底部距离
// 边界处理
if (left <= 0) {
left = 0
}
if(left >= ScreenWidth - onlineIconWidth) {
left = ScreenWidth - onlineIconWidth
}
if(bottom <= 0) {
bottom = 0
}
if(bottom >= ScreenHeight - 100) {
bottom = ScreenHeight - 100
}
this.setState({
left: left,
bottom: bottom
})
},
// 用户放开了所有的触摸点
onPanResponderRelease: (e, g) => {
this.startX = this.state.left
this.startY = this.state.bottom
}
})
}
render () {
return (
<Animated.View
style={{
transform: [ { translateX: this.state.pan.x }, { translateY: this.state.pan.y } ], position: 'absolute', left: this.state.left, bottom: this.state.bottom, backgroundColor: 'rgb(179, 127, 235)', width: onlineIconWidth, height: onlineIconHeight, borderRadius: 30
}}
{...this._panResponder?.panHandlers }
>
<TouchableHighlight
onPress={() => {
// 自定义自己的点击事件逻辑
}}
>
<Text>拖拽的盒子</Text>
</TouchableHighlight>
</Animated.View>
)
}
}
export default AppWithNavigationState;