Question:
對于這樣一個segementScrollView(Android的稱法),圖片/視頻是作為一個flutterView被集成到原生中,當用戶在屏幕進行拖拽或輕掃動作時(pan or swipe gesture),flutterView本身listView的上下滑動屬性完全失效,此時操作的就像是在操作一個segementScrollView??梢宰笥一瑒?,但圖片/視頻listView本身不滑動,這明顯不符合我們的期望。

segementView.png
Solution:
步驟1. 禁止segementScrollView上的滑動屬性
當我禁止segementScrollView.scrollEnabbled = No后,左右不可滑動,上下滑動正常。因為上下滑動其實用的是flutterView的listView的滑動屬性??瓷先ギ斀箂egementScrollView的滑動屬性后,flutterView就可以接受到用戶的觸摸事件了。
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView {
NSInteger index = scrollView.contentOffset.x/ScreenWidth;
if (self.segmentControl.selectedSegmentIndex != index) {
self.segmentControl.selectedSegmentIndex = index;
}
//戶型信息和圖片/視頻都是flutterView,因此我們需要將其scrollEnabled置為NO
if(self.segmentControl.selectedSegmentIndex == 1 || self.segmentControl.selectedSegmentIndex == 2){
self.segmentScrollView.scrollEnabled = NO;
}else{
self.segmentScrollView.scrollEnabled = YES;
}
}

drawingBoard.gif
步驟2:利用flutterView的pan手勢得到左右偏移量
這時候我們發(fā)現(xiàn)雖然上下滑動flutterView的listView就正常了,但現(xiàn)在左右不可以滑動了。在網上找了很多資料,自己也做了很多嘗試,發(fā)現(xiàn)我們可以這樣做:
既然現(xiàn)在flutterView的手勢是可以工作的,那我們可以利用flutterview的pan手勢進行左右偏移的時候,實時記錄其偏移位置,并將這偏移位置告訴iOS原生,這里就涉及到了flutterView與原生的交互部分了。
//flutter部分代碼
Widget buildBuildingInfoContainer() {
return GestureDetector(
//手勢滾動過程中
onPanUpdate: (d) {
print(
"onPanUpdate----direction=${d.delta.direction},dx=${d.delta.dx},dy=${d.delta.dy},distance=${d.localPosition.distance}");
movedX += d.delta.dx;
movedY += d.delta.dy;
//調用原生的方法,傳遞offsetX值以及狀態(tài)ID
MethodChannelUtil.flutterInvokeNative(
MethodName.houseTypeCellScrolled, {
"status": 6,
"statusDesc": "移動",
"offsetX": movedX - originalX,
"offsetY": movedY - originalY
});
},
//手勢開始拖拽
onPanStart: (d) {
print(
"onPanStart----dx=${d.localPosition.dx},dy=${d.localPosition.dy},distance=${d.localPosition.distance}");
//調用原生的方法,傳遞offsetX值以及狀態(tài)ID
MethodChannelUtil.flutterInvokeNative(
MethodName.houseTypeCellScrolled, {
"status": 5,
"statusDesc": "開始",
"startX": originalX,
"startY": originalY
});
},
//手勢拖動結束
onPanEnd: (DragEndDetails details) {
print("onPanEnd");
double offsetX = movedX - originalX;
double offsetY = movedY - originalY;
print("offsetX=$offsetX offsetY=$offsetY");
//調用原生的方法,傳遞offsetX值以及狀態(tài)ID
MethodChannelUtil.flutterInvokeNative(
MethodName.houseTypeCellScrolled, {
"status": 7,
"statusDesc": "結束",
"offsetX": offsetX,
"offsetY": offsetY
});
},
child: Container(
),
}
步驟3:原生接受到flutter模塊的callBack,作出相應處理
原生模塊可以接受到flutter模塊的callBack,并得到偏移量的值,以及相應的status值。得到偏移量就很簡單了,跟我們在iOS模塊里設置scrollView偏移量沒有兩樣。
self.videoPhotoFlutterViewController.callBack = ^(NSString * _Nonnull jsonStr) {
NSLog(@"OC----%@---",jsonStr);
NSDictionary *dict = jsonStr.mj_JSONObject;
NSInteger value = [[dict objectForKey:@"status"] integerValue];
CGFloat offsetX = [[dict objectForKey:@"offsetX"] doubleValue];
CGFloat offsetY = [[dict objectForKey:@"offsetY"] doubleValue];
//移動中
if(value == 6){
startX = weakself.segmentScrollView.contentOffset.x;
CGFloat startY = weakself.segmentScrollView.contentOffset.y;
startX += -offsetX;
[weakself.segmentScrollView setContentOffset:CGPointMake(startX, 0)];
NSLog(@"startX=%f",startX);
}
//停止移動
if(value == 7){
if(startX>ScreenWidth*1.5 && startX< ScreenWidth*2 + ScreenWidth*0.5){
[weakself.segmentScrollView setContentOffset:CGPointMake(ScreenWidth*2,0) animated:true];
}
if (startX >= ScreenWidth*2 + ScreenWidth*0.5) {
[weakself.segmentScrollView setContentOffset:CGPointMake(UIScreen.mainScreen.bounds.size.width*3,0) animated:true];
}
if (startX <= ScreenWidth*1.5){
[weakself.segmentScrollView setContentOffset:CGPointMake(ScreenWidth,0) animated:true];
}
}
};
最終效果與總結

drawingBoard2.gif
現(xiàn)在從效果上來,可以總結以下幾點:
- 在iOS系統(tǒng)的segmentViewController中,上方是一個自定義的segmentTitleView,下方是一個左右滑動的scrollView。這個segmentItem每一個item都是獨立的ViewController,其中當然也包括我們的flutterViewController。
- 一開始的時候,左右滑動是沒有問題的,但就是flutterView里的listView不能正常滑動,因為我們現(xiàn)在所有的手勢都在iOS層處理了,并不會傳遞給flutterView,flutterView的手勢不起作用。因此我們需要設置segmentScrollView.scrollEnabled = NO去disable掉原生層面的手勢,這樣flutterView層面上的手勢自動生效。
- segmentScrollView的滑動屬性被disable掉之后,左右滑動不能work了。現(xiàn)在我們需要在flutterView的pan手勢去計算得出其手勢偏移量,將此偏移量傳遞給原生,然后由原生去設置segmentScrollView的contentOffset做偏移。
這就是設計的基本思路。有更好的方案,歡迎提出討論????