1.背景
??在文章例子中的RN(以下用RN表示React Native)版本是0.43.3。RN官方和非官方提供了很多左右滑動(dòng)的控件和組件,作者使用的比較多的就是react-native-scrollable-tab-view和react-native-viewpager(之前作為一個(gè)Android開發(fā)者,對(duì)ViewPager情有獨(dú)鐘),它們?cè)趩为?dú)使用的時(shí)候并沒有什么問題,使用的方法也很簡(jiǎn)單。但是在實(shí)際的開發(fā)中,比如主頁面左右滑動(dòng)切換Tab,同時(shí)子頁面中又有左右切換輪播圖的組件,這個(gè)時(shí)候就會(huì)有左右滑動(dòng)沖突的問題,如果不加以處理的話,實(shí)際的效果體檢就會(huì)很差。俗話說站在巨人的肩膀上看得遠(yuǎn)(其實(shí)是作者比較菜,能力有限),本文就是在這兩個(gè)控件的基礎(chǔ)上進(jìn)行改進(jìn)來解決這個(gè)問題。
2.下載組件
??接下來要用到的兩個(gè)組件的Github地址分別為,
https://github.com/skv-headless/react-native-scrollable-tab-view
https://github.com/race604/react-native-viewpager
上面都有它們的介紹,相關(guān)Api以及如何使用的例子,在這里就不多加以介紹了,這里主要講如何修改去解決活動(dòng)沖突的問題
3.問題分析和解決思路
??那么問題來了,該怎么去解決這個(gè)滑動(dòng)沖突的問題呢?
??如果開發(fā)過Android項(xiàng)目可能知道,遇到這種問題的解決方式一般是使用ViewPager(父View),和ChildViewPager(子View),一般的做法就是在子View中接管Touch事件,當(dāng)子Viewr中可以進(jìn)行左滑和右滑操作時(shí),禁止父View的滑動(dòng),而當(dāng)子View滑動(dòng)到底的時(shí)候,把Touch事件交出來給父View,同時(shí)允許父View進(jìn)行滑動(dòng)?;镜慕鉀Q思路就是這樣的。首先在開始之前,對(duì)于RN下手勢(shì)事件不了解不熟悉的可以看下RN官方中文網(wǎng)站的介紹,地址如下:http://reactnative.cn/docs/0.43/gesture-responder-system.html
4.解決問題
??首先我們找到ViewPager中對(duì)于手勢(shì)控制的代碼,同時(shí)將我們的分析思路用代碼進(jìn)行實(shí)現(xiàn)
onMoveShouldSetPanResponder: (e, gestureState) => {
let needMove=false;
//手指從左往右滑動(dòng)
if(gestureState.dx>0&&this.state.currentPage>0){
needMove=true;
}
//手指從右往左滑動(dòng)
if(gestureState.dx<0&&this.state.currentPage<this.props.dataSource.getPageCount()-1){
needMove=true;
}
if (Math.abs(gestureState.dx) > Math.abs(gestureState.dy)&&needMove) {
if (this.props.locked !== true && !this.fling) {
this.props.hasTouch && this.props.hasTouch(true);
return true;
}
}
},
??判斷手指是從左往右滑動(dòng)的時(shí)候,并且當(dāng)處于非第0項(xiàng)的時(shí)候,或者手指是從右往左滑動(dòng)的時(shí)候,并且當(dāng)處于非最后一項(xiàng)時(shí)候,那么此時(shí)的手勢(shì)操作應(yīng)該交給子View,同時(shí)可以看到代碼
this.props.hasTouch && this.props.hasTouch(true); 意思就是告訴父View,此時(shí)我接管了手勢(shì)操作,并且本次滑動(dòng)操作成功。那么同理,當(dāng)不需要滑動(dòng)操作的時(shí)候應(yīng)該告訴父View,我不需要滑動(dòng)操作了。果然在ViewPager的release方法中找到了該方法的調(diào)用
var release = (e, gestureState) => {
var relativeGestureDistance = gestureState.dx / deviceWidth,
//lastPageIndex = this.props.children.length - 1,
vx = gestureState.vx;
var step = 0;
if (relativeGestureDistance < -0.5 || (relativeGestureDistance < 0 && vx <= -1e-6)) {
step = 1;
} else if (relativeGestureDistance > 0.5 || (relativeGestureDistance > 0 && vx >= 1e-6)) {
step = -1;
}
this.props.hasTouch && this.props.hasTouch(false);
this.movePage(step, gestureState);
}
??有了這些之后,我們就可以在父View之中根據(jù)這狀態(tài)來進(jìn)行相關(guān)的操作了
<ScrollableTabView
locked={this.state.isLocked}
>
{this._getChildItem()}
</ScrollableTabView>
//true表示內(nèi)部需要滑動(dòng),此時(shí)外部需要lock住
_hasTouch = (isTouch) => {
this.setState({isLocked: isTouch})
}
??通過對(duì)ScrollableTabView屬性的修改來進(jìn)行左右滑動(dòng)的控制。我們來看下分別在ios和android下的效果


??從效果上來看偶爾會(huì)有誤觸的情況,但是總體上的效果還可以接受
5.最后
??作者接觸RN還不到一個(gè)月的時(shí)間,之前一直是Android開發(fā),能力有限,現(xiàn)在更多的是使用一些比較成熟的框架或者組件。當(dāng)然要根據(jù)一些業(yè)務(wù)的需求進(jìn)行修改。最后,奉上例子的Github地址:https://github.com/hzl123456/ChildViewPagerDemo
(記得修改ViewPager的代碼)