This commit is contained in:
ammarahm-ed
2020-01-11 23:05:39 +05:00
parent ea94048294
commit 9e24f2b40e
2 changed files with 233 additions and 144 deletions

View File

@@ -1,13 +1,16 @@
import React, {useState} from 'react';
import React, {Component} from 'react';
import {
View,
TouchableOpacity,
Dimensions,
ScrollView,
Modal,
KeyboardAvoidingView,
Platform,
} from 'react-native';
import PropTypes from 'prop-types';
import {styles} from './styles';
let scrollViewRef;
const deviceHeight = Dimensions.get('window').height;
const getElevation = elevation => {
@@ -20,173 +23,213 @@ const getElevation = elevation => {
};
};
const ActionSheet = ({
ref,
children = <View />,
animated = true,
animationType = 'fade',
closeOnPressBack = true,
gestureEnabled = true,
bounceOnOpen = true,
bounceOffset = 20,
springOffset = 50,
elevation = 5,
initialOffsetFromBottom = 0.6,
indicatorColor = 'gray',
customStyles = {backgroundColor: 'white'},
overlayColor = 'rgba(0,0,0,0.3)',
onClose = () => {},
onOpen = () => {},
}) => {
const [modalVisible, setModalVisible] = useState(false);
const [scrollable, setScrollable] = useState(false);
const [layoutHasCalled, setLayoutHasCalled] = useState(false);
ActionSheet.customComponentHeight;
ActionSheet.prevScroll;
ActionSheet.scrollAnimationEndValue;
ActionSheet.hasBounced;
const _setModalVisible = () => {
if (!modalVisible) {
setModalVisible(true);
if (gestureEnabled) {
setScrollable(true);
export default class ActionSheet extends Component {
constructor(props) {
super(props);
this.state = {
modalVisible: false,
scrollable: false,
layoutHasCalled: false,
};
this.customComponentHeight;
this.prevScroll;
this.scrollAnimationEndValue;
this.hasBounced;
this.scrollViewRef;
}
_setModalVisible = () => {
if (!this.state.modalVisible) {
this.setState({
modalVisible: true,
scrollable: this.props.gestureEnabled,
});
} else {
_hideModal();
this._hideModal();
}
};
const _hideModal = () => {
_scrollTo(0);
_hideModal = () => {
this._scrollTo(0);
setTimeout(() => {
setLayoutHasCalled(false);
setModalVisible(false);
ActionSheet.customComponentHeight = null;
ActionSheet.prevScroll = null;
ActionSheet.scrollAnimationEndValue = null;
ActionSheet.hasBounced = null;
if (typeof onClose === 'function') onClose();
this.setState(
{
modalVisible: false,
layoutHasCalled: false,
},
() => {
if (typeof this.props.onClose === 'function') this.props.onClose();
},
);
}, 150);
};
const _showModal = event => {
if (layoutHasCalled) {
_showModal = event => {
let {gestureEnabled, bounceOffset, initialOffsetFromBottom} = this.props;
let addFactor = deviceHeight * 0.1;
let height = event.nativeEvent.layout.height;
console.log('layout called again');
if (this.state.layoutHasCalled) {
let diff;
if (height > this.customComponentHeight) {
diff = height - this.customComponentHeight;
this._scrollTo(this.prevScroll + diff);
console.log(this.prevScroll);
this.customComponentHeight = height;
} else {
diff = this.customComponentHeight - height;
this._scrollTo(this.prevScroll - diff);
this.customComponentHeight = height;
}
return;
} else {
ActionSheet.customComponentHeight = event.nativeEvent.layout.height;
let addFactor = deviceHeight * 0.1;
_scrollTo(
this.customComponentHeight = height;
this._scrollTo(
gestureEnabled
? ActionSheet.customComponentHeight * initialOffsetFromBottom +
? this.customComponentHeight * initialOffsetFromBottom +
addFactor +
bounceOffset
: ActionSheet.customComponentHeight + bounceOffset,
: this.customComponentHeight + bounceOffset,
);
setLayoutHasCalled(true);
this.setState({
layoutHasCalled: true,
});
}
};
const _onScrollBeginDrag = event => {
_onScrollBeginDrag = event => {
let verticalOffset = event.nativeEvent.contentOffset.y;
ActionSheet.prevScroll = verticalOffset;
this.prevScroll = verticalOffset;
};
const _onScrollEndDrag = event => {
_onScrollEndDrag = event => {
let {springOffset} = this.props;
let verticalOffset = event.nativeEvent.contentOffset.y;
if (ActionSheet.prevScroll < verticalOffset) {
if (verticalOffset - ActionSheet.prevScroll > springOffset * 0.75) {
if (this.prevScroll < verticalOffset) {
if (verticalOffset - this.prevScroll > springOffset * 0.75) {
let addFactor = deviceHeight * 0.1;
_scrollTo(ActionSheet.customComponentHeight + addFactor);
this._scrollTo(this.customComponentHeight + addFactor);
} else {
_scrollTo(ActionSheet.prevScroll);
this._scrollTo(this.prevScroll);
}
} else {
if (ActionSheet.prevScroll - verticalOffset > springOffset) {
_hideModal();
if (this.prevScroll - verticalOffset > springOffset) {
this._hideModal();
} else {
_scrollTo(ActionSheet.prevScroll);
this._scrollTo(this.prevScroll);
}
}
};
const _scrollTo = (y, bouncing) => {
_scrollTo = (y, bouncing) => {
let {bounceOffset, bounceOnOpen} = this.props;
this.hasBounced = false;
if (!bouncing && bounceOnOpen) {
ActionSheet.scrollAnimationEndValue = y + bounceOffset;
this.scrollAnimationEndValue = y + bounceOffset;
} else {
ActionSheet.scrollAnimationEndValue = y;
this.scrollAnimationEndValue = y;
}
ActionSheet.hasBounced = false;
scrollViewRef.scrollTo({
this.scrollViewRef.scrollTo({
x: 0,
y: ActionSheet.scrollAnimationEndValue,
y: this.scrollAnimationEndValue,
animated: true,
});
};
const _onTouchMove = () => {
setScrollable(false);
_onTouchMove = () => {
this._hideModal();
this.setState({
scrollable: false,
});
};
const _onTouchStart = () => {
setScrollable(false);
_onTouchStart = () => {
this._hideModal();
this.setState({
scrollable: false,
});
};
const _onTouchEnd = () => {
if (gestureEnabled) {
setScrollable(true);
_onTouchEnd = () => {
if (this.props.gestureEnabled) {
this.setState({
scrollable: true,
});
}
};
const _onScrollEndAnimation = () => {
if (!ActionSheet.hasBounced) {
_scrollTo(ActionSheet.scrollAnimationEndValue - bounceOffset, true);
ActionSheet.hasBounced = true;
_onScrollEndAnimation = event => {
this.prevScroll = event.nativeEvent.contentOffset.y;
let {bounceOffset, bounceOnOpen} = this.props;
if (!this.hasBounced && bounceOnOpen) {
this._scrollTo(this.scrollAnimationEndValue - bounceOffset, true);
this.hasBounced = true;
}
};
render() {
let {scrollable, modalVisible} = this.state;
let {
animationType,
animated,
onOpen,
closeOnPressBack,
overlayColor,
bounceOnOpen,
gestureEnabled,
elevation,
indicatorColor,
children,
customStyles,
} = this.props;
return (
<Modal
ref={ref}
visible={modalVisible}
animationType={animationType}
animated={animated}
onShow={() => onOpen}
onRequestClose={() => {
if (closeOnPressBack) _hideModal();
if (closeOnPressBack) this._hideModal();
}}
transparent={true}>
<View style={[styles.parentContainer, {backgroundColor: overlayColor}]}>
<KeyboardAvoidingView
style={{
width: '100%',
}}
enabled={Platform.OS === 'ios' ? true : false}
behavior="position">
<ScrollView
bounces={false}
ref={ref => (scrollViewRef = ref)}
ref={ref => (this.scrollViewRef = ref)}
showsVerticalScrollIndicator={false}
scrollEnabled={scrollable}
onScrollBeginDrag={_onScrollBeginDrag}
onScrollEndDrag={_onScrollEndDrag}
onMomentumScrollEnd={() => {
if (bounceOnOpen) {
_onScrollEndAnimation();
}
}}
onScrollAnimationEnd={_onScrollEndAnimation}
onTouchEnd={_onTouchEnd}
onScrollBeginDrag={this._onScrollBeginDrag}
onScrollEndDrag={this._onScrollEndDrag}
onMomentumScrollEnd={this._onScrollEndAnimation}
onScrollAnimationEnd={this._onScrollEndAnimation}
onTouchEnd={this._onTouchEnd}
overScrollMode="always"
style={[styles.scrollview]}>
<View
onTouchMove={_onTouchMove}
onTouchStart={_onTouchStart}
onTouchEnd={_onTouchEnd}
onTouchMove={this._onTouchMove}
onTouchStart={this._onTouchStart}
onTouchEnd={this._onTouchEnd}
style={{
height: deviceHeight * 1.1,
width: '100%',
}}>
<TouchableOpacity
onPress={_hideModal}
onLongPress={_hideModal}
onPress={this._hideModal}
onLongPress={this._hideModal}
style={{
height: deviceHeight,
width: '100%',
@@ -194,7 +237,7 @@ const ActionSheet = ({
/>
</View>
<View
onLayout={_showModal}
onLayout={this._showModal}
style={[
styles.container,
customStyles,
@@ -202,16 +245,54 @@ const ActionSheet = ({
]}>
{gestureEnabled ? (
<View
style={[styles.indicator, {backgroundColor: indicatorColor}]}
style={[
styles.indicator,
{backgroundColor: indicatorColor},
]}
/>
) : null}
{children}
</View>
</ScrollView>
</KeyboardAvoidingView>
</View>
</Modal>
);
};
}
}
export default ActionSheet;
ActionSheet.defaultProps = {
children: <View />,
animated: true,
animationType: 'fade',
closeOnPressBack: true,
gestureEnabled: true,
bounceOnOpen: true,
bounceOffset: 20,
springOffset: 50,
elevation: 5,
initialOffsetFromBottom: 0.6,
indicatorColor: 'gray',
customStyles: {},
overlayColor: 'rgba(0,0,0,0.3)',
onClose: () => {},
onOpen: () => {},
};
ActionSheet.propTypes = {
children: PropTypes.node,
animated: PropTypes.bool,
animationType: PropTypes.oneOf(['none', 'slide', 'fade']),
closeOnPressBack: PropTypes.bool,
gestureEnabled: PropTypes.bool,
bounceOnOpen: PropTypes.bool,
bounceOffset: PropTypes.number,
springOffset: PropTypes.number,
elevation: PropTypes.number,
initialOffsetFromBottom: PropTypes.number,
indicatorColor: PropTypes.string,
customStyles: PropTypes.object,
overlayColor: PropTypes.string,
onClose: PropTypes.func,
onOpen: PropTypes.func,
};

View File

@@ -1,4 +1,4 @@
import React, {useState} from 'react';
import React, {useState, useEffect} from 'react';
import {
View,
Text,
@@ -28,7 +28,7 @@ const h = Dimensions.get('window').height;
let tagsInputRef;
export const ActionSheetComponent = ({
close = () => {},
item = {},
item,
setWillRefresh = value => {},
hasColors = false,
hasTags = false,
@@ -39,6 +39,10 @@ export const ActionSheetComponent = ({
const [focused, setFocused] = useState(false);
const [note, setNote] = useState(item ? item : {});
useEffect(() => {
setNote({...item});
}, [item]);
let tagToAdd = null;
let backPressCount = 0;
@@ -257,6 +261,10 @@ export const ActionSheetComponent = ({
return (
<View
onLayout={() => {
console.log(item);
setNote({...item});
}}
style={{
paddingBottom: 15,
backgroundColor: colors.bg,