渲染出一个可以跟随手势变化的浮层
- 包含native手势浮层(GestureFloat)和Rn手势浮层两种(RNGestureFloat) GestureFloat支持两页模式,当前浮层支持切换页 RNGestureFloat依赖
qportal
,需要在组件最外层挂在qportal.Provider
npm install @qnpm/q-gesture-float --save --registry=http://npmrepo.corp.qunar.com
显示代码
import { GestureFloat } from '@qnpm/q-gesture-float';
const buildMultiFirstFloat = () => {
return {
key:'page1',
fixedHeader: HeaderView,
fixedHeaderData: {
closeHandler: ()=>{
this.setState({
pageNumber: -1,
pageViewList:[]
});
},
isFixed: true,
type: 'multi'
},
header: HeaderView,
headerData: {
closeHandler: ()=>{
this.setState({
pageNumber: -1,
pageViewList:[]
});
},
isFixed: false,
forbidFullScreen:this.state.forbidFullScreen,
type: 'multi'
},
content: ContentView,
contentData: {
type: 'multi',
goToSecondHandler:()=>{
this.openMultiSecondFloatBox();
}
},
footer :FooterView,
footerData: {
type: 'multi'
}
};
}
const pageViewList= [
buildMultiFirstFloat(),
buildMultiFirstFloat()
]
<GestureFloat
pageViewList={pageViewList}
pageNumber={pageNumber}
stopPercent = {{
init: 0.75,
toInitMin: 0.65,
toInitMax: 0.85,
}}
showDuration = {300}
hideDuration = {200}
stopDuration = {200}
borderTopRadius={12}
forbidSwipeBack = {true}
recoverSwipeBack = {true}
onClose={(index)=>{
this.setState({
pageNumber: -1
});
}}
/>
显示代码
import { RNGestureFloat } from '@qnpm/q-gesture-float';
import { Provider } from '@qnpm/qportal';
<Provider>
<View>
{/*这里是根节点*/}
</View>
</Provider>
// 组件使用
<RNGestureFloat
visible={visible}
needAnimate={false}
header={
<View>
<Text>浮层标题</Text>
<Icon name={'close'} />
</View>
}
footer={
<View>
<Text>浮层底部</Text>
</View>
}
onClose={() => toggleStatus(false)}
>
<View
style={{
flex: 1,
backgroundColor: '#f0f',
justifyContent: 'center',
alignItems: 'center'
}}
>
<Text>这是一个由RN实现的手势浮层</Text>
</View>
</RNGestureFloat>
属性名 | 类型 | 默认值 | 是否必须 | 说明 |
---|---|---|---|---|
borderTopRadius |
number |
0 |
true |
视图内容的圆角弧度 |
contentBgColor |
ContentBgColorData |
undefind |
false |
设置page的背景颜色 |
forbidSwipeBack |
boolean |
undefind |
false |
ios特有,禁止侧滑退出 |
hideDuration |
number |
600 |
false |
隐藏动画持续时长 |
initTabIndex |
boolean |
0 |
false |
header为tab时属性,tab默认定位index |
isTabHeader |
boolean |
false |
false |
header为tab时属性,当前页的header是否是tab |
moveSensitivity |
number |
undefind |
false |
touch move回调的灵敏度 |
onClose |
(pageNumber: number, index: number) => void |
undefind |
false |
关闭动画开始时回调方法 |
onCloseAnimateFinish |
(pageNumber: number) => void |
undefind |
false |
关闭动画结束时回调方法 |
onFloatViewOffsetY |
number |
undefind |
false |
划动offsetY的距离,吸顶头部(pageViewList.fixedHeader), (adr>=60001526;iOS>=80011291) |
onStateChange |
(pageNumber: number, state: string) => void |
undefind |
false |
页面的状态发生变化时(全屏、半屏、隐藏)回调方法 |
onTouchMoveChange |
(pageNumber: number, isTouchMoving: boolean) => void |
undefind |
false |
页面的手势移动发生变化时回调方法 |
onTabSelectedChange |
(pageNumber: number, tabIndex: number) => void |
undefind |
false |
scrollView滚动过程中,tab的选中序号切换回调方法 |
pageNumber |
number |
undefind |
true |
当前浮层展示视图控制,0:显示第一页;1:显示第二页;-1:浮层开始收起;-2:浮层收起结束 |
pageViewList |
PageViewData[] |
undefind |
false |
浮层对应的页面元素数据 |
recoverSwipeBack |
boolean |
undefind |
false |
ios特有,恢复侧滑退出 |
scrollEnabled |
ScrollEnabledData |
undefind |
false |
是否允许滚动 |
setFullScreen |
ShowHeaderTipData |
undefind |
false |
仅安卓,打开是否默认全屏展示 |
showArrowIndicator |
boolean |
undefind |
false |
是否展示手势浮层外部拉起箭头 |
showDuration |
number |
600 |
false |
显示动画持续时长 |
showHeaderTip |
ShowHeaderTipData |
undefind |
false |
Header的顶部提示(箭头)图标(adr>=60001526) |
stopDuration |
number |
100 |
false |
停靠动画持续时长 |
stopPercent |
StopPercentData |
undefind |
false |
停靠的位置 |
PageViewData
说明
属性名 | 类型 | 默认值 | 是否必须 | 说明 |
---|---|---|---|---|
content |
React.ComponentClass<{ data: any }> |
<View/> |
false |
scrollView内容的View |
contentData |
any |
undefined |
false |
传递给scrollView内容的View的props属性 |
fixedHeader |
React.ComponentClass<{ data: any }> |
<View/> |
false |
吸顶的header View |
fixedHeaderData |
any |
undefined |
false |
传递给吸顶的header View的props属性 |
footer |
React.ComponentClass<{ data: any }> |
undefined |
false |
footer View |
footerData |
any |
undefined |
false |
传递给footer View的props属性 |
header |
React.ComponentClass<{ data: any }> |
<View/> |
false |
非吸顶的header,位置在scrollView内容的上侧,跟着浮层一起被手势移动。 |
headerData |
any |
undefined |
false |
传递给非吸顶的header View的props属性 |
tabContents |
React.ComponentClass<{ data: any }>[] |
undefined |
false |
header为tab时,每个tab对应的scrollView内容view。当浮层显示是,该属性和content属性,必须有一个有值 |
tabContentsData |
any |
undefined |
false |
传递给tabContents的props属性 |
key |
string |
'' |
true |
页面唯一标识,没有实际含义 |
ContentBgColorData
说明
属性名 | 类型 | 默认值 | 是否必须 | 说明 |
---|---|---|---|---|
page0 |
string |
'#fff' |
false |
第一个页面的背景色 |
page1 |
string |
'#fff' |
false |
第二个页面的背景色 |
ShowHeaderTipData
说明
属性名 | 类型 | 默认值 | 是否必须 | 说明 |
---|---|---|---|---|
page0 |
boolean |
false |
false |
第一个页面native是否展示header中箭头提示图标,仅ios支持 |
page1 |
boolean |
false |
false |
第二个页面native是否展示header中箭头提示图标,仅ios支持 |
ScrollEnabledData
说明
属性名 | 类型 | 默认值 | 是否必须 | 说明 |
---|---|---|---|---|
page0 |
boolean |
true |
false |
第一个页面是否支持手势move |
page1 |
boolean |
true |
false |
第二个页面是否支持手势move |
StopPercentData
说明
属性名 | 类型 | 默认值 | 是否必须 | 说明 |
---|---|---|---|---|
init |
number |
0.7 |
true |
浮层的初始高度占屏幕高度的百分数 |
toInitMax |
number |
0.8 |
true |
手势移动过程中,松手后停靠到初始位置的最大高度 |
toInitMin |
number |
0.6 |
true |
手势移动过程中,松手后停靠到初始位置的最小高度 |
方法名 | 参数 | 说明 |
---|---|---|
topPageScrollTo |
y: number, animated: boolean |
最上层页面的scrollView滚动到指定位置 |
topPageScrollToEnd |
animated: boolean |
最上层页面的scrollView滚动到最底部 |
resetPageLayout |
isResetHeaderHeight: boolean 是否重新计算header的高度 |
当页面内容高度发生变化时,需要重新计算页面视图的高度,否则页面会错乱,仅adr需要 |
setScrollable |
scrollable: boolean |
设置页面的scrollView能够滚动,仅adr支持 |
setSlidingBoundaryAngle |
angle: number |
设置页面的scrollView能否滚动的角度,仅adr支持 |
topPageScrollByTab |
index: number tab的序号,从0开始, animated: boolean |
通过点击tab,将scrollView滚动到tab对应视图的位置 |
属性名 | 类型 | 默认值 | 是否必须 | 说明 |
---|---|---|---|---|
adaptFooter |
boolean |
true |
false |
是否在iPhone X 系列手机上自动添加底部留白 |
content |
ReactElement |
null |
false |
自定义内容元素 |
footer |
ReactElement |
null |
false |
自定义底部元素 |
hasHeader |
boolean |
true |
false |
是否需要展示头部 |
header |
ReactElement |
null |
false |
自定义头部元素 |
headerHeight |
number |
0 |
false |
自定义头部高度 |
hideDuration |
number |
ios: 300 , adr: 400 |
false |
浮层隐藏动画执行时长 |
injectScrollProps |
boolean |
false |
false |
是否需要为子组件注入方法,详细说明见下面 |
moveDistance |
number |
150 |
false |
手势移动有效距离 |
needAnimate |
boolean |
true |
false |
浮层展示/隐藏是否需要动画 |
onClose |
Function |
() => {} |
false |
浮层关闭时的回调 |
onHideAnimateFinished |
(visible: boolean) => void |
() => {} |
false |
浮层隐藏动画执行完成回调 |
onShowAnimateFinished |
(visible: boolean) => void |
() => {} |
false |
浮层展示动画执行完成回调 |
perHeight |
number or string |
90 |
false |
浮层高度百分比, 'auto'情况下自适应高度(40%-80%) |
showDuration |
number |
300 |
false |
浮层展示动画执行时长 |
swipeBackControl |
boolean |
true |
false |
浮层弹起时,是否禁止左滑返回 |
title |
string |
'' |
false |
头部展示标题 |
visible |
boolean |
false |
true |
浮层是否展示 |
zIndex |
number |
false |
false |
浮层相对层级(absolute) |
customStyle |
StyleProp<ViewStyle> |
false |
false |
浮层面板自定义样式 |
injectScrollProps
说明
当
injectScrollProps
属性设置为true
时,会为子元素注入以下属性:{ getScrollRef: this.getScrollRef, scrollEventThrottle: 16, bounces: false, onScroll: this.onChildViewScroll };
一般只有在子元素是一个可滚动容器(
ScrollView
、FlatList
、SectionList
等)需要将此属性设置为true
,然后在子元素的onScroll
方法中调用props.onScroll
,在ref
中调用props.getScrollRef
来配合浮层容器完成手势操作。 特殊情况如:可滚动容器是嵌套在其他容器内,类似<View><ScrollView></ScrollView></View>
,则注入属性将无效,会导致手势冲突等问题。此时需要自行将上述属性从props取出注入到滚动容器上:const { getScrollRef, scrollEventThrottle, onScroll } = this.props; <View> <ScrollView getScrollRef={getScrollRef} scrollEventThrottle={scrollEventThrottle} onScroll={onScroll} > ... </ScrollView> </View>