1.增加onSlidingPage回調,可以在滑動頁面的時候設定頁面上面的其他元素的狀态
2.增加中文文檔
這個需求在做extended_image的時候就有上帝客戶提過了,一直都沒有時間去考慮實作。最近思考了一下,把效果給實作了。
首先開啟滑動退出頁面效果
ExtendedImage
parameter | description | default |
---|---|---|
enableSlideOutPage | 是否開啟滑動退出頁面效果 | false |
把你的頁面用ExtendedImageSlidePage包一下
注意:onSlidingPage回調,你可以使用它來設定滑動頁面的時候,頁面上其他元素的狀态。但是注意别直接使用setState來重新整理,因為這樣會導緻ExtendedImage的狀态重置掉,你應該隻通知需要重新整理的Widgets進行重新整理
return ExtendedImageSlidePage(
child: result,
slideAxis: SlideAxis.both,
slideType: SlideType.onlyImage,
onSlidingPage: (state) {
///you can change other widgets' state on page as you want
///base on offset/isSliding etc
//var offset= state.offset;
var showSwiper = !state.isSliding;
if (showSwiper != _showSwiper) {
// do not setState directly here, the image state will change,
// you should only notify the widgets which are needed to change
// setState(() {
// _showSwiper = showSwiper;
// });
_showSwiper = showSwiper;
rebuildSwiper.add(_showSwiper);
}
},
);
ExtendedImageGesturePage的參數
parameter | description | default |
---|---|---|
child | 需要包裹的頁面 | - |
slidePageBackgroundHandler | 在滑動頁面的時候根據Offset自定義整個頁面的背景色 | defaultSlidePageBackgroundHandler |
slideScaleHandler | 在滑動頁面的時候根據Offset自定義整個頁面的縮放值 | defaultSlideScaleHandler |
slideEndHandler | 滑動頁面結束的時候計算是否需要pop頁面 | defaultSlideEndHandler |
slideAxis | 滑動頁面的方向(both,horizontal,vertical),掘金是vertical,微信是Both | both |
resetPageDuration | 滑動結束,如果不pop頁面,整個頁面回彈動畫的時間 | milliseconds: 500 |
slideType | 滑動整個頁面還是隻是圖檔(wholePage/onlyImage) | SlideType.onlyImage |
onSlidingPage | 滑動頁面的回調,你可以在這裡改變頁面上其他元素的狀态 | - |
下面是預設實作,你也可以根據你的喜好,來定義屬于自己方式
Color defaultSlidePageBackgroundHandler(
{Offset offset, Size pageSize, Color color, SlideAxis pageGestureAxis}) {
double opacity = 0.0;
if (pageGestureAxis == SlideAxis.both) {
opacity = offset.distance /
(Offset(pageSize.width, pageSize.height).distance / 2.0);
} else if (pageGestureAxis == SlideAxis.horizontal) {
opacity = offset.dx.abs() / (pageSize.width / 2.0);
} else if (pageGestureAxis == SlideAxis.vertical) {
opacity = offset.dy.abs() / (pageSize.height / 2.0);
}
return color.withOpacity(min(1.0, max(1.0 - opacity, 0.0)));
}
bool defaultSlideEndHandler(
{Offset offset, Size pageSize, SlideAxis pageGestureAxis}) {
if (pageGestureAxis == SlideAxis.both) {
return offset.distance >
Offset(pageSize.width, pageSize.height).distance / 3.5;
} else if (pageGestureAxis == SlideAxis.horizontal) {
return offset.dx.abs() > pageSize.width / 3.5;
} else if (pageGestureAxis == SlideAxis.vertical) {
return offset.dy.abs() > pageSize.height / 3.5;
}
return true;
}
double defaultSlideScaleHandler(
{Offset offset, Size pageSize, SlideAxis pageGestureAxis}) {
double scale = 0.0;
if (pageGestureAxis == SlideAxis.both) {
scale = offset.distance / Offset(pageSize.width, pageSize.height).distance;
} else if (pageGestureAxis == SlideAxis.horizontal) {
scale = offset.dx.abs() / (pageSize.width / 2.0);
} else if (pageGestureAxis == SlideAxis.vertical) {
scale = offset.dy.abs() / (pageSize.height / 2.0);
}
return max(1.0 - scale, 0.8);
}
確定你的頁面是透明背景的
如果你設定 slideType =SlideType.onlyImage, 請確定的你頁面是透明的,畢竟沒法操控你頁面上的顔色
Push一個透明的頁面
這裡我把官方的MaterialPageRoute 和CupertinoPageRoute拷貝出來了, 改為TransparentMaterialPageRoute/TransparentCupertinoPageRoute,因為它們的opaque不能設定為false
Navigator.push(
context,
Platform.isAndroid
? TransparentMaterialPageRoute(builder: (_) => page)
: TransparentCupertinoPageRoute(builder: (_) => page),
);
嗯應該還算使用簡單吧?群裡的小夥伴吐槽表情包太多,不讓放,藍瘦香菇。
實作中的一些坑
1.手勢跟縮放拖拽以及PageView之前的關系和沖突
開始我的思路是想在ExtendedImageSlidePage 注冊手勢監聽事件,然後ExtendedImageGesture裡面當條件滿足(達到邊界/無法拖拽)的時候通知 ExtendedImageSlidePage 開始滑動頁面手勢了,可以阻止ExtendedImageSlidePage的child的hittest。
但是在實際中發現,在ExtendedImageGesture手勢未完成之前(手指擡起),ExtendedImageSlidePage 也是擷取不到任何手勢,而且IgnorePointer 也是不會生效的
後面幹脆直接把手勢接收都放ExtendedImageGesture裡面了,直接通知ExtendedImageSlidePage進行translate和scale
2.透明頁面
TransparentMaterialPageRoute/TransparentCupertinoPageRoute 因為需要整個頁面是透明的,是以重寫了官方的。
但是在pop頁面的時候還是有不滿意的地方,比如ios上面有個從左到右Shadow,安卓上面整個頁面也有Shadow。
最後
如果你看到了這裡,覺得文章寫得不錯就給個贊呗!歡迎大家評論讨論!如果你覺得那裡值得改進的,請給我留言。一定會認真查詢,修正不足,定期免費分享技術幹貨。謝謝!