Android 带有React Native的Google地图面板
我试图复制谷歌地图滑动面板(“探索伦敦城”)或类似的东西。面板应通过滑动打开和关闭,打开时,内部内容应滚动,即在滚动视图内,然后当滚动视图位于顶部时,滚动被禁用,面板可关闭 目前,我正在使用Android 带有React Native的Google地图面板,android,reactjs,google-maps,react-native,swipe-gesture,Android,Reactjs,Google Maps,React Native,Swipe Gesture,我试图复制谷歌地图滑动面板(“探索伦敦城”)或类似的东西。面板应通过滑动打开和关闭,打开时,内部内容应滚动,即在滚动视图内,然后当滚动视图位于顶部时,滚动被禁用,面板可关闭 目前,我正在使用rn向上滑动面板插件进行面板滑动,子组件为ScrollView。然后我找到ScrollView的位置,如果它在0,并且用户正在向下滑动,我关闭面板 然而,在Android和iOS设备上,这似乎都有相当多的缺陷。有时它会在ScrollView中停留在位置0 有没有人建造过类似的东西?也许我在正确的轨道上,它需
rn向上滑动面板
插件进行面板滑动,子组件为ScrollView。然后我找到ScrollView的位置,如果它在0,并且用户正在向下滑动,我关闭面板
然而,在Android和iOS设备上,这似乎都有相当多的缺陷。有时它会在ScrollView中停留在位置0
有没有人建造过类似的东西?也许我在正确的轨道上,它需要改进?还是有更好的插件
任何建议或示例都将非常有用。类ssss扩展组件{
class ssss extends Component {
constructor(props) {
super(props);
this.state = {
position: new Animated.Value(props.isOpen ? 0 : height),
opacity: new Animated.Value(0),
height: defaultHeight,
expanded: false,
visible: props.isOpen
};
}
// When user starts pulling popup previous height gets stored here
// to help us calculate new height value during and after pulling
_previousHeight = 0;
componentDidMount() {
// Initialize PanResponder to handle move gestures
this._panResponder = PanResponder.create({
onStartShouldSetPanResponder: (evt, gestureState) => true,
onMoveShouldSetPanResponder: (evt, gestureState) => {
const { dx, dy } = gestureState;
// Ignore taps
if (dx !== 0 && dy === 0) {
return true;
}
return false;
},
onPanResponderGrant: (evt, gestureState) => {
// Store previous height before user changed it
this._previousHeight = this.state.height;
},
onPanResponderMove: (evt, gestureState) => {
// Pull delta and velocity values for y axis from gestureState
const { dy, vy } = gestureState;
// Subtract delta y from previous height to get new height
let newHeight = this._previousHeight - dy;
// Animate heigh change so it looks smooth
LayoutAnimation.easeInEaseOut();
// Switch to expanded mode if popup pulled up above 80% mark
if (newHeight > 600 - 600 / 5) {
this.setState({ expanded: true });
} else {
this.setState({ expanded: false });
}
// Expand to full height if pulled up rapidly
if (vy < -0.75) {
this.setState({
expanded: true,
height: height * 0.65
});
}
// Close if pulled down rapidly
else if (vy > 0.75) {
this.props.onClose();
}
// Close if pulled below 95% mark of default height
else if (newHeight < defaultHeight * 0.95) {
this.props.onClose();
}
// Limit max height to screen height
else if (newHeight > 600) {
this.setState({ height: height * 0.65 });
} else {
this.setState({ height: newHeight });
}
},
onPanResponderTerminationRequest: (evt, gestureState) => true,
onPanResponderRelease: (evt, gestureState) => {
const { dy } = gestureState;
const newHeight = this._previousHeight - dy;
// Close if pulled below default height
if (newHeight < defaultHeight) {
this.props.onClose();
}
// Update previous height
this._previousHeight = this.state.height;
},
onShouldBlockNativeResponder: (evt, gestureState) => {
// Returns whether this component should block native components from becoming the JS
// responder. Returns true by default. Is currently only supported on android.
return true;
}
});
}
// Handle isOpen changes to either open or close popup
componentWillReceiveProps(nextProps) {
// isOpen prop changed to true from false
if (!this.props.isOpen && nextProps.isOpen) {
this.animateOpen();
}
// isOpen prop changed to false from true
else if (this.props.isOpen && !nextProps.isOpen) {
this.animateClose();
}
}
// Open popup
animateOpen() {
// Update state first
this.setState({ visible: true }, () => {
Animated.parallel([
// Animate opacity
Animated.timing(
this.state.opacity,
{ toValue: 0.5 } // semi-transparent
),
// And slide up
Animated.timing(
this.state.position,
{ toValue: 0 } // top of the screen
)
]).start();
});
}
// Close popup
animateClose() {
Animated.parallel([
// Animate opacity
Animated.timing(
this.state.opacity,
{ toValue: 0 } // transparent
),
// Slide down
Animated.timing(
this.state.position,
{ toValue: height } // bottom of the screen
)
]).start(() =>
this.setState({
// Reset to default values
height: defaultHeight,
expanded: false,
visible: false
})
);
}
render() {
// Render nothing if not visible
if (!this.state.visible) {
return null;
}
return (
<View style={styles.container}>
{/* Closes popup if user taps on semi-transparent backdrop */}
<TouchableWithoutFeedback onPress={this.props.onClose}>
<Animated.View
style={[styles.backdrop, { opacity: this.state.opacity }]}
/>
</TouchableWithoutFeedback>
<Animated.View
style={[
styles.modal,
{
// Animates height
height: this.state.height,
// Animates position on the screen
transform: [
{ translateY: this.state.position },
{ translateX: 0 }
]
}
]}
>
{/* Content */}
<View style={styles.content}>
<View
style={[styles.topUpContainer]}
{...this._panResponder.panHandlers}
>
<View style={styles.hookerContainer}>
<View style={styles.hooker} />
</View>
{/* Your content comes here */}
</View>
</View>
</Animated.View>
</View>
);
}
}
建造师(道具){
超级(道具);
此.state={
位置:新的动画.Value(props.isOpen?0:高度),
不透明度:新的动画。值(0),
高度:默认高度,
扩展:错,
可见:props.isOpen
};
}
//当用户开始拉弹出窗口时,先前的高度存储在此处
//帮助我们在拉动期间和拉动之后计算新高度值
_以前的高度=0;
componentDidMount(){
//初始化PanResponder以处理移动手势
这是.\u panResponder=panResponder.create({
onStartShouldSetPanResponder:(evt,手势状态)=>真,
onMoveShouldSetPanResponder:(evt,手势状态)=>{
常数{dx,dy}=gestureState;
//忽略水龙头
如果(dx!==0&&dy==0){
返回true;
}
返回false;
},
onPanResponderGrant:(evt,手势状态)=>{
//在用户更改之前存储以前的高度
this.\u previousHeight=this.state.height;
},
onPanResponderMove:(evt,手势状态)=>{
//从gestureState拉出y轴的增量和速度值
常数{dy,vy}=手势状态;
//从以前的高度中减去增量y以获得新高度
设newHeight=this.\u先前的height-dy;
//设置高度变化的动画,使其看起来平滑
LayoutImation.easeInEaseOut();
//如果弹出窗口拉高到80%标记以上,则切换到扩展模式
如果(新高度>600-600/5){
this.setState({expanded:true});
}否则{
this.setState({expanded:false});
}
//如果快速向上拉,则膨胀至全高
如果(vy<-0.75){
这是我的国家({
对,,
高度:高度*0.65
});
}
//如果快速向下拉,则关闭
否则,如果(vy>0.75){
this.props.onClose();
}
//如果拉至默认高度的95%标记以下,则关闭
否则如果(新高度<默认高度*0.95){
this.props.onClose();
}
//将最大高度限制为屏幕高度
否则,如果(新高度>600){
this.setState({height:height*0.65});
}否则{
this.setState({height:newHeight});
}
},
onPanResponderTerminationRequest:(evt,gestureState)=>true,
onPanResponderRelease:(evt,手势状态)=>{
const{dy}=gestureState;
const newHeight=此值。\ u先前的高度-dy;
//如果拉至低于默认高度,则关闭
如果(新高度<默认高度){
this.props.onClose();
}
//更新以前的高度
this.\u previousHeight=this.state.height;
},
onShouldBlockNativeResponder:(evt,手势状态)=>{
//返回此组件是否应阻止本机组件成为JS
//默认情况下返回true。当前仅在android上受支持。
返回true;
}
});
}
//处理打开或关闭弹出窗口的等参线更改
组件将接收道具(下一步){
//isOpen属性从false更改为true
如果(!this.props.isOpen&&nextrops.isOpen){
这个。animateOpen();
}
//isOpen属性从true更改为false
else if(this.props.isOpen&!nextrops.isOpen){
这个。animateClose();
}
}
//打开弹出窗口
animateOpen(){
//首先更新状态
this.setState({visible:true},()=>{
平行动画([
//设置不透明度动画
时间(
这个,状态,不透明度,
{toValue:0.5}//半透明
),
//然后滑上去
时间(
这个州的位置,
{toValue:0}//屏幕顶部
)
]).start();
});
}
//关闭弹出窗口
animateClose(){
平行动画([
//设置不透明度动画
时间(
这个,状态,不透明度,
{toValue:0}//透明
),
//滑落
时间(
这个州的位置,
{toValue:height}//屏幕底部
)
]).start(()=>
这是我的国家({
//重置为默认值
高度:默认高度,
扩展:错,
可见:假
})
);
}
render(){
//如果不可见,则不渲染任何内容
如果(!this.state.visible){
返回null;
}
返回(
{/*如果用户点击半透明背景,则关闭弹出窗口*/}
{/*内容*/}
{/*您的内容出现在这里*/}
);
}
}
这可能对你有帮助