How do I make a secondary enter a main view with the PanResponder?
up vote
1
down vote
favorite
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)
I have a basic structure set up, but I'm not sure how to finalize the <Animated.View>
part. 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
,
)
ios react-native view
add a comment |
up vote
1
down vote
favorite
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)
I have a basic structure set up, but I'm not sure how to finalize the <Animated.View>
part. 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
,
)
ios react-native view
Never had to deal with panhandler myself, I use this awesome library kmagiera.github.io/react-native-gesture-handler/docs/…
– Ziyo
Nov 12 at 0:52
add a comment |
up vote
1
down vote
favorite
up vote
1
down vote
favorite
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)
I have a basic structure set up, but I'm not sure how to finalize the <Animated.View>
part. 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
,
)
ios react-native view
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)
I have a basic structure set up, but I'm not sure how to finalize the <Animated.View>
part. 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
,
)
ios react-native view
ios react-native view
asked Nov 11 at 22:03
TIMEX
67.3k268645947
67.3k268645947
Never had to deal with panhandler myself, I use this awesome library kmagiera.github.io/react-native-gesture-handler/docs/…
– Ziyo
Nov 12 at 0:52
add a comment |
Never had to deal with panhandler myself, I use this awesome library kmagiera.github.io/react-native-gesture-handler/docs/…
– Ziyo
Nov 12 at 0:52
Never had to deal with panhandler myself, I use this awesome library kmagiera.github.io/react-native-gesture-handler/docs/…
– Ziyo
Nov 12 at 0:52
Never had to deal with panhandler myself, I use this awesome library kmagiera.github.io/react-native-gesture-handler/docs/…
– Ziyo
Nov 12 at 0:52
add a comment |
1 Answer
1
active
oldest
votes
up vote
1
down vote
accepted
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 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
this.position.getLayout() is the one that gives the coordinates/position of where the Animated.View component should be
The other styling object is so we can render the child views next to each other using flexbox particularly setting
Also attach the panHandlers to the 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 = positionI used state to monitor where the View Should move to this.state = isOpen: false depending on which view was visible.
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.
The openOrClose function determines how to handle the movement and the main logic should be here. I just did a simple case and did not include any threshHold in this example.
To understand panHandlers I suggest you read this article as it explains the reasons for onPanResponderGrant best.
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. If there is anything I need to clarify or improve please do tell me
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53253709%2fhow-do-i-make-a-secondary-view-enter-a-main-view-with-the-panresponder%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
1
down vote
accepted
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 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
this.position.getLayout() is the one that gives the coordinates/position of where the Animated.View component should be
The other styling object is so we can render the child views next to each other using flexbox particularly setting
Also attach the panHandlers to the 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 = positionI used state to monitor where the View Should move to this.state = isOpen: false depending on which view was visible.
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.
The openOrClose function determines how to handle the movement and the main logic should be here. I just did a simple case and did not include any threshHold in this example.
To understand panHandlers I suggest you read this article as it explains the reasons for onPanResponderGrant best.
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. If there is anything I need to clarify or improve please do tell me
add a comment |
up vote
1
down vote
accepted
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 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
this.position.getLayout() is the one that gives the coordinates/position of where the Animated.View component should be
The other styling object is so we can render the child views next to each other using flexbox particularly setting
Also attach the panHandlers to the 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 = positionI used state to monitor where the View Should move to this.state = isOpen: false depending on which view was visible.
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.
The openOrClose function determines how to handle the movement and the main logic should be here. I just did a simple case and did not include any threshHold in this example.
To understand panHandlers I suggest you read this article as it explains the reasons for onPanResponderGrant best.
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. If there is anything I need to clarify or improve please do tell me
add a comment |
up vote
1
down vote
accepted
up vote
1
down vote
accepted
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 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
this.position.getLayout() is the one that gives the coordinates/position of where the Animated.View component should be
The other styling object is so we can render the child views next to each other using flexbox particularly setting
Also attach the panHandlers to the 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 = positionI used state to monitor where the View Should move to this.state = isOpen: false depending on which view was visible.
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.
The openOrClose function determines how to handle the movement and the main logic should be here. I just did a simple case and did not include any threshHold in this example.
To understand panHandlers I suggest you read this article as it explains the reasons for onPanResponderGrant best.
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. If there is anything I need to clarify or improve please do tell me
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 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
this.position.getLayout() is the one that gives the coordinates/position of where the Animated.View component should be
The other styling object is so we can render the child views next to each other using flexbox particularly setting
Also attach the panHandlers to the 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 = positionI used state to monitor where the View Should move to this.state = isOpen: false depending on which view was visible.
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.
The openOrClose function determines how to handle the movement and the main logic should be here. I just did a simple case and did not include any threshHold in this example.
To understand panHandlers I suggest you read this article as it explains the reasons for onPanResponderGrant best.
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. If there is anything I need to clarify or improve please do tell me
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>
)
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>
)
edited Nov 12 at 1:35
answered Nov 12 at 1:30
Craques
1189
1189
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53253709%2fhow-do-i-make-a-secondary-view-enter-a-main-view-with-the-panresponder%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Never had to deal with panhandler myself, I use this awesome library kmagiera.github.io/react-native-gesture-handler/docs/…
– Ziyo
Nov 12 at 0:52