1.背景
??在文章例子中的RN(以下用RN表示React Native)版本是0.43.3。RN官方和非官方提供了很多左右滑動的控件和組件,作者使用的比較多的就是react-native-scrollable-tab-view和react-native-viewpager(之前作為一個Android開發者,對ViewPager情有獨鐘),它們在單獨使用的時候并沒有什么問題,使用的方法也很簡單。但是在實際的開發中,比如主頁面左右滑動切換Tab,同時子頁面中又有左右切換輪播圖的組件,這個時候就會有左右滑動沖突的問題,如果不加以處理的話,實際的效果體檢就會很差。俗話說站在巨人的肩膀上看得遠(其實是作者比較菜,能力有限),本文就是在這兩個控件的基礎上進行改進來解決這個問題。
2.下載組件
??接下來要用到的兩個組件的Github地址分別為,
https://github.com/skv-headless/react-native-scrollable-tab-view
https://github.com/race604/react-native-viewpager
上面都有它們的介紹,相關Api以及如何使用的例子,在這里就不多加以介紹了,這里主要講如何修改去解決活動沖突的問題
3.問題分析和解決思路
??那么問題來了,該怎么去解決這個滑動沖突的問題呢?
??如果開發過Android項目可能知道,遇到這種問題的解決方式一般是使用ViewPager(父View),和ChildViewPager(子View),一般的做法就是在子View中接管Touch事件,當子Viewr中可以進行左滑和右滑操作時,禁止父View的滑動,而當子View滑動到底的時候,把Touch事件交出來給父View,同時允許父View進行滑動。基本的解決思路就是這樣的。首先在開始之前,對于RN下手勢事件不了解不熟悉的可以看下RN官方中文網站的介紹,地址如下:http://reactnative.cn/docs/0.43/gesture-responder-system.html
4.解決問題
??首先我們找到ViewPager中對于手勢控制的代碼,同時將我們的分析思路用代碼進行實現
onMoveShouldSetPanResponder: (e, gestureState) => {
let needMove=false;
//手指從左往右滑動
if(gestureState.dx>0&&this.state.currentPage>0){
needMove=true;
}
//手指從右往左滑動
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;
}
}
},
??判斷手指是從左往右滑動的時候,并且當處于非第0項的時候,或者手指是從右往左滑動的時候,并且當處于非最后一項時候,那么此時的手勢操作應該交給子View,同時可以看到代碼
this.props.hasTouch && this.props.hasTouch(true);
意思就是告訴父View,此時我接管了手勢操作,并且本次滑動操作成功。那么同理,當不需要滑動操作的時候應該告訴父View,我不需要滑動操作了。果然在ViewPager的release方法中找到了該方法的調用
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之中根據這狀態來進行相關的操作了
<ScrollableTabView
locked={this.state.isLocked}
>
{this._getChildItem()}
</ScrollableTabView>
//true表示內部需要滑動,此時外部需要lock住
_hasTouch = (isTouch) => {
this.setState({isLocked: isTouch})
}
??通過對ScrollableTabView屬性的修改來進行左右滑動的控制。我們來看下分別在ios和android下的效果
??從效果上來看偶爾會有誤觸的情況,但是總體上的效果還可以接受
5.最后
??作者接觸RN還不到一個月的時間,之前一直是Android開發,能力有限,現在更多的是使用一些比較成熟的框架或者組件。當然要根據一些業務的需求進行修改。最后,奉上例子的Github地址:https://github.com/hzl123456/ChildViewPagerDemo
(記得修改ViewPager的代碼)