gestureFloat 手势浮层组件

渲染出一个可以跟随手势变化的浮层

特殊说明

  • 包含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>

属性说明GestureFloat

属性名 类型 默认值 是否必须 说明
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对应视图的位置

属性说明RNGestureFloat

属性名 类型 默认值 是否必须 说明
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
};

一般只有在子元素是一个可滚动容器(ScrollViewFlatListSectionList等)需要将此属性设置为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>