rn-sliding-view
rn-sliding-view is a small customizable library that allows you to add animated sliding views to your screens.
It supports 4 modes: from top to bottom ("top"), from bottom to top ("bottom"), from left to right ("left") and from right to left ("right").
You can customize the component in the way you want, including styling, setting
animation duration, delays, positioning, allow/disable default drag, make your own drag, etc.
Contents
Installation
yarn add rn-sliding-view
or
npm install rn-sliding-view --save
Usage
The simplest usage.
All you need to do is provide two props: componentVisible and changeVisibilityCallback:
import React Component from 'react';import View Button Text TouchableOpacity from 'react-native';import SlidingView from 'rn-sliding-view'; state = componentVisible: false ; this; { return <> <Button = ="tap to toggle rn-sliding-view" /> /* Your other components... */ <SlidingView = = > /* any nested components */ </SlidingView> </> ; }
Code of examples above.
Default positioning (bottom), default allowed drag, default height and default animation duration. You can explicitly pass position prop, but "bottom" position is default.
Click to see the code.
import React Component from 'react';import Alert StyleSheet Text TouchableOpacity ImageBackground from 'react-native';import SlidingView from 'rn-sliding-view';import wallpaper from './wallpaper.jpeg'; state = sliderVisible: false ; { return <> <ImageBackground = = > <TouchableOpacity = = > <Text =>rn-sliding-view at work</Text> <Text =>Default </Text> <Text =>Default </Text> <Text =>Default </Text> <Text =>Drag is allowed</Text> <Text =>Drag finishing on release is allowed</Text> </TouchableOpacity> </ImageBackground> <SlidingView = = = > <TouchableOpacity = = > <Text => This text is touchable </Text> </TouchableOpacity> <Text =>This one is not</Text> <Text =>You can put here</Text> <Text =>Anything you want</Text> </SlidingView> </> ; } const styles = StyleSheet;
Position "top", custom height, custom animation duration, drag is allowed, disabled auto finishing drag.
Click to see the code.
import React Component from 'react';import StyleSheet Text TouchableOpacity ImageBackground from 'react-native';import widthPercentageToDP as wp heightPercentageToDP as hp from 'react-native-responsive-screen';import SlidingView from 'rn-sliding-view';import wallpaper from './wallpaper.jpeg'; state = sliderVisible: false ; { return <> <ImageBackground = = > <TouchableOpacity = = > <Text =>rn-sliding-view at work</Text> <Text =>Custom </Text> <Text =>Custom </Text> <Text =>Custom </Text> <Text =>Drag is allowed</Text> <Text =>Drag finishing on release is disabled</Text> </TouchableOpacity> </ImageBackground> <SlidingView = = ="top" = = = > <TouchableOpacity = = > <Text => Example with "top" position </Text> </TouchableOpacity> <Text =>This time auto drag finishing is disabled</Text> <Text =>Custom duration of animation</Text> <Text =>And custom height</Text> </SlidingView> </> ; } const styles = StyleSheet;
Position "left", default width, default animation duration, drag is allowed, default auto finishing drag.
Click to see the code.
import React Component from 'react';import StyleSheet Text TouchableOpacity ImageBackground from 'react-native';import widthPercentageToDP as wp heightPercentageToDP as hp from 'react-native-responsive-screen';import SlidingView from 'rn-sliding-view';import wallpaper from './wallpaper.jpeg'; state = sliderVisible: false ; { return <> <ImageBackground = = > <TouchableOpacity = = > <Text =>rn-sliding-view at work</Text> <Text =>Custom </Text> <Text =>Default </Text> <Text =>Default </Text> <Text =>Drag is allowed</Text> <Text =>Default drag finishing on </Text> </TouchableOpacity> </ImageBackground> <SlidingView = = ="left" = > <TouchableOpacity = = > <Text => Example with "left" position touch to close </Text> </TouchableOpacity> <Text =>Default values</Text> <Text =>Except "position property"</Text> <Text =>Default width is 100% of screen</Text> </SlidingView> </> ; } const styles = StyleSheet;
Position "right", disabled drag, custom width, custom animation duration and styles.
Click to see the code.
import React Component from 'react';import Alert StyleSheet Text TouchableOpacity ImageBackground from 'react-native';import widthPercentageToDP as wp from 'react-native-responsive-screen';import SlidingView from 'rn-sliding-view';import wallpaper from './wallpaper.jpeg'; state = sliderVisible: false ; { return <> <ImageBackground = = > <TouchableOpacity = = > <Text =>rn-sliding-view at work</Text> <Text =>Custom </Text> <Text =>Custom </Text> <Text =>Default </Text> <Text =>Drag is disabled</Text> <Text =>Default drag finishing on </Text> </TouchableOpacity> </ImageBackground> <SlidingView = = ="right" = = = > <TouchableOpacity = = > <Text = = > Example with "right" position touch to close </Text> </TouchableOpacity> <Text =>Drag is disabled</Text> <Text =>Custom </Text> <Text =>Custom </Text> </SlidingView> </> ; } const styles = StyleSheet;
Make it draggable
Generally it's up to you what you want to do with the component. By default drag'n'drop is allowed and it has its own behaviour (described below). If you wish you can disable it via disableDrag prop and make your own logic of drag'n'drop or not make it at all. If you're going to make your own logic, make sure you've disabled default behaviour via disableDrag prop.
Default drag'n'drop behaviour.
By default you can drag the component at its any part. Maximum value is component's height (or width, if it has left or right position), minimum is an edge of device's screen. If you don't pass disableAutoDragEnd prop it has the following behaviour: when you release your finger the component evaluates the direction of its move. So on release it either hides the component or returns it to maximum value.
Custom drag'n'drop behaviour.
To make your own logic of drag'n'drop you have to pass disableDrag prop. Generally all you need to do is create your own responder and pass it to your child component.
... { thisresponders = } { return <SlidingView = = = = > /* Your components below */ <View> <View /> <-- This view will be draggable /* Your other not draggable components */ </View> </SlidingView> }...
After you created your responder and passed it to the component, you can handle it in the way you want. The main thing you have to do now - dynamically update currentPositionY (or currentPositionX) prop.
Important: if you want to pass TouchableOpacity (or other touchable) elements, consider making a distinction between drag and single tap. By default, pan responders override single taps of nested views, so TouchableOpacity won't work. As in example below you can set onStartShouldSetResponderCapture to () => false if you use react-native-gesture-responder library. Or use similar method of native PanResponder class.
Click to see example of custom drag'n'drop implementation
import React Component from 'react';import View StyleSheet Text TouchableOpacity ImageBackground Animated from "react-native";import widthPercentageToDP as wp heightPercentageToDP as hp from 'react-native-responsive-screen';import createResponder from 'react-native-gesture-responder';import SlidingView from 'rn-sliding-view';import wallpaper from './wallpaper.jpeg'; <Props> state = sliderVisible: false y: null ; { thisresponders = ; } { const y = thisstate; const maxY = ; const minY = 0; const yDiff = gestureStatemoveY - gestureStatepreviousMoveY; let newY = y - yDiff; if y === null newY = gestureStatemoveY; if newY < minY newY = minY; else if newY > maxY newY = maxY; this; }; { const sliderVisible = thisstate; if gestureStatemoveY > gestureStatepreviousMoveY return this; return this; }; { return <> <View => // ... Your other components </View> <SlidingView = = ="bottom" = > <TouchableOpacity = = > <Text => Example with "left" position touch to close </Text> </TouchableOpacity> <View > // <-- This view will be draggable <Text =>Default values</Text> </View> <Text =>This text is not draggable</Text> </SlidingView> </> ; } const styles = StyleSheet;
Props
Props | Default value | Required | Type | Definition |
---|---|---|---|---|
componentVisible | - | true | Boolean | Represents if the component is visible. |
animationDuration | 300 | false | Number | Sets duration of animation. |
position | "bottom" | false | String | Sets the place where the component appears. |
height | 50% of screen | false | Number | Sets the height of the component. |
width | 100% of screen | false | Number | Sets the width of the component. |
delay | 0 | false | Number | Sets the delay before animation starts. |
disableDrag | false | false | Boolean | Disables default drag behaviour. |
disableAutoDragEnd | false | false | Boolean | Disables default finishing drag behaviour (fires on release of touch). |
changeVisibilityCallback | () => {} | false | Function | Changes visibility of the component. Required, if you use default drag behaviour. Pass the same function you use for changing componentVisible prop. |
currentPositionX | null | false | Number | Represents horizontal position of the component. Required if you use "left" or "right" position prop. |
currentPositionY | null | false | Number | Represents vertical position of the component. Required if you use "bottom" or "top" position prop. |
children | - | false | React.Node | Children components you pass to rn-sliding-view component. |
containerStyle | {} | false | Object | Custom styles of the component's container |
Caveats
-
It's better to make your component a single module with separate logic of drag'n'drop, switching between visibility states, etc.
-
Consider using redux/mobX state if you want to pass rn-sliding-view at the top of your application. So you can toggle visibility via single function throughout your app.
-
The place matters. Bounds where the component will be placed are defined by its place in your code. If you nest the component inside of another nested component (not at the top level), it will be placed at the same level in your views hierarchy.
Contribution
Contributors are welcome! Please, opening PR consider following git flow. If I am afk too long you can message me directly to my linkedIn or to email: egor19942012@gmail.com.
Issues
Please, opening new issue provide the code to reproduce the problem and full description. This is the fastest way to solve it.
License
MIT