简体   繁体   English

我如何做二级<View>使用 PanResponder 进入主视图?

[英]How do I make a secondary <View> enter a main view with the PanResponder?

When the View mounts, I would like the secondary view to be off the screen to the right of the main view.当视图安装时,我希望辅助视图位于主视图右侧的屏幕之外

When the user pan swipes left , the secondary view should follow the pan and eventually cover the main view.当用户平移向左滑动时,辅助视图应该跟随平移并最终覆盖主视图。 (like Instagram camera) (如 Instagram 相机)

I have a basic structure set up, but I'm not sure how to finalize the <Animated.View> part.我已经设置了一个基本结构,但我不确定如何完成<Animated.View>部分。 For example, do I put the pan handler on the main view or on the secondary view?例如,我是将平移处理程序放在主视图上还是放在次要视图上? I don't want the secondary view to cover any interactions on the main view.我不希望辅助视图覆盖主视图上的任何交互。

import React from 'react';
import { PanResponder, Animated, Dimensions, StyleSheet, Text, View } from 'react-native';
const winWidth = Dimensions.get('window').width
const winHeight = Dimensions.get('window').height

class Main extends React.Component {
    constructor(props){
        super(props);
    }
    translateX = new Animated.Value(0);
    panResponder = PanResponder.create({
        onMoveShouldSetPanResponderCapture: (e, gs) => {
            return gs.dx < 0 //allow left only
        },
        onPanResponderMove: (e, gs) => { 
            if(gs.dx < 0) { 
                Animated.event([null, {dx: this.translateX}])(e, gs) 
            }
        },
        onPanResponderRelease: (e, {vx, dx}) => {
            //Secondary View should now cover the main View
        },
        onPanResponderTerminationRequest: (e, gs) => {
            return false 
        },
        onPanResponderTerminate: (e, {vx, dx} ) => {
        },
    })
    render(){
        return(
            <View style={{styles.main}}>
                <View style={{styles.secondary}}></View>
                <View><Text>Other components will be displayed</Text></View>
            </View>
        )
    }
}

const styles = StyleSheet.create({
    main:{
        flex:1,
        flexDirection:'column',
        backgroundColor: '#ffffff'
    },
    secondary:{
        width: winWidth,
        height: winHeight,
        backgroundColor: 'red',
        position: 'absolute',
        top:0,
        left:winWidth, //start off screen
    },
})

I am not sure if this is what you are after but the way I did it was nesting two View inside the Animated.View Component which cover the full screen.我不确定这是否是您所追求的,但我这样做的方式是在 Animated.View 组件中嵌套两个视图,覆盖全屏。

<Animated.View style={[this.position.getLayout(), {display: 'flex', flex: 1, flexDirection: 'row'}]} {...this.panResponder.panHandlers}>
    <View style={{width: '100%', height: '100%', backgroundColor: 'yellow'}}>
        <Text>
            This is the Main view
        </Text>
    </View>

    <View style={{ height: '100%', width: '100%', backgroundColor: 'red'}}>
        <Text>
            This is the invisible View
        </Text>     
    </View>
</Animated.View>
  • The styling in the Views is to make each cover the full width视图中的样式是使每个都覆盖整个宽度

  • inside the Animated.View I used the array notation to apply two styles在 Animated.View 中,我使用数组表示法来应用两种样式

  • this.position.getLayout() is the one that gives the coordinates/position of where the Animated.View component should be this.position.getLayout()是给出 Animated.View 组件所在位置的坐标/位置

  • The other styling object is so we can render the child views next to each other using flexbox particularly setting另一个样式对象是这样我们可以使用 flexbox 特别设置来渲染彼此相邻的子视图

  • Also attach the panHandlers to the Animated.View还将 panHandlers 附加到 Animated.View

     constructor(props){ super(props) position = new Animated.ValueXY() const panResponder = PanResponder.create({ onStartShouldSetPanResponder: ()=> true, onPanResponderMove: (evt, gesture)=>{ //Need to set theshhold and state.isOpen to determine direction here position.setValue({x: gesture.dx, y: 0}) }, onPanResponderGrant: ()=>{ this.position.setOffset({x: this.position.x._value, y: 0}) this.position.setValue({x: 0, y: 0}) }, onPanResponderRelease: ()=>{ this.openOrClose() } }) this.state = {isOpen: false} this.panResponder = panResponder this.position = position }
  • I used state to monitor where the View Should move to this.state = {isOpen: false} depending on which view was visible.我使用状态来监视视图应该移动到this.state = {isOpen: false} 的位置,具体取决于哪个视图可见。

  • The functions to move are mainly position.setValue({x: gesture.dx, y: 0}) which tracks the movement while the touch/pan is still active and this.openOrClose() which is called when the touch/pan is released.移动的函数主要是position.setValue({x:gesture.dx, y: 0}) ,它在触摸/平移仍处于活动状态时跟踪移动,以及this.openOrClose()在释放触摸/平移时调用.

  • The openOrClose function determines how to handle the movement and the main logic should be here. openOrClose 函数决定了如何处理移动,主要逻辑应该在这里。 I just did a simple case and did not include any threshHold in this example.我只是做了一个简单的案例,在这个例子中没有包含任何 threshHold。

  • To understand panHandlers I suggest you read this article as it explains the reasons for onPanResponderGrant best.要了解 panHandlers,我建议您阅读这篇文章,因为它最好地解释了onPanResponderGrant的原因。

Below is the code for the working Component下面是工作组件的代码

 import React, {Component} from 'react' import {View, Text, Animated, PanResponder, Dimensions} from 'react-native' const ScreenWidth = Dimensions.get('window').width //Logic to flattenOffset required export class Swipable extends Component{ constructor(props){ super(props) position = new Animated.ValueXY() const panResponder = PanResponder.create({ onStartShouldSetPanResponder: ()=> true, onPanResponderMove: (evt, gesture)=>{ //Need to set theshhold and state.isOpen to determine direction here position.setValue({x: gesture.dx, y: 0}) }, onPanResponderGrant: ()=>{ this.position.setOffset({x: this.position.x._value, y: 0}) this.position.setValue({x: 0, y: 0}) }, onPanResponderRelease: ()=>{ this.openOrClose() } }) this.state = {isOpen: false} this.panResponder = panResponder this.position = position } openOrClose = ()=>{ this.position.flattenOffset() //determine where to move depending onState direction = this.state.isOpen ? 0 : -ScreenWidth Animated.spring(this.position, { toValue: {x: direction, y: 0} }).start(()=>{ //Callback when animation is complete to show if open or closed this.setState((prevState)=>{ return {isOpen: !prevState.isOpen} }) }) } render(){ return( <Animated.View style={[this.position.getLayout(), {display: 'flex', flex: 1, flexDirection: 'row'}]} {...this.panResponder.panHandlers}> <View style={{width: '100%', height: '100%', backgroundColor: 'yellow'}}> <Text> This is the Main view </Text> </View> <View style={{ height: '100%', width: '100%', backgroundColor: 'red'}}> <Text> This is the invisible View </Text> </View> </Animated.View> ) } }

I ran the above code on an Android emulator, I am sure it will work on ios.我在 Android 模拟器上运行了上面的代码,我相信它可以在 ios 上运行。 If there is anything I need to clarify or improve please do tell me如果有什么我需要澄清或改进的,请告诉我

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何滑动辅助视图以显示主视图 - How to slide a secondary view to reveal a main view 如何在视图控制器之间进行转换并从每个控制器返回到主视图 con.? - How do I make the transition between view controllers and return from each to the main view con.? 当主视图分离时,如何使视图保持在屏幕上? - How do I make a view that stays onscreen when the main view segues? 如何在按下按钮时使按钮弹出警报视图并返回主视图控制器? - How Do I Make A Button Get An Alert View To Pop Up When Pressed And Go Back To The Main View Controller? 如何记录主视图? - How to do recording for main view? TableView in View,如何使其透明 - TableView in View, how do i make it transparent 如何使堆栈视图或容器视图包装内容? - How do I make a stack view or container view wrap contents? SplitViewController:如何替换辅助视图而不是推送新视图? - SplitViewController: How do I replace a the secondary view rather than pushing a new one? 如何使我的backgroundImageView成为可拖动而不是主视图 - How do I get my backgroundImageView to be draggable instead of main view 如何制作带有侧面预览和主视图的 PdfView - how to make PdfView with side preview and main view
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM