Flutter 仿掘金微信圖片滑動退出頁面效果

extended_image 相關文章ios

2019/06/16 更新:git

1.增長onSlidingPage回調,能夠在滑動頁面的時候設置頁面上面的其餘元素的狀態github

2.增長中文文檔微信

pub package

這個需求在作extended_image的時候就有上帝客戶提過了,一直都沒有時間去考慮實現。最近思考了一下,把效果給實現了。markdown

首先開啓滑動退出頁面效果

ExtendedImage編輯器

parameter description default
enableSlideOutPage 是否開啓滑動退出頁面效果 false

把你的頁面用ExtendedImageSlidePage包一下

注意:onSlidingPage回調,你可使用它來設置滑動頁面的時候,頁面上其餘元素的狀態。可是注意別直接使用setState來刷新,由於這樣會致使ExtendedImage的狀態重置掉,你應該只通知須要刷新的Widgets進行刷新ide

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的參數svg

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 滑動頁面的回調,你能夠在這裏改變頁面上其餘元素的狀態 -

下面是默認實現,你也能夠根據你的喜愛,來定義屬於本身方式post

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。

經過修改官方源碼,去掉了這些效果,感興趣的小夥伴能夠查看extended_image_slide_page_route.dart(最近拉麪批評代碼上太多,差評,那個啥代碼就不貼了 )

關於extended_image的readme

最近從新整理了一下readme,由於你們總是吐槽不容易看,但願新的readme能幫助你們更好地使用這個組件,感謝財經龍大佬百忙當中幫忙格式readme,懶惰的程序猿,readme都要大佬幫忙弄,羞愧。。。

最後放上 extended_image,若是你有什麼不明白或者對這個方案有什麼改進的地方,請告訴我,歡迎加入Flutter Candies,一塊兒生產可愛的Flutter 小糖果(QQ羣:181398081)

最最後放上Flutter Candies全家桶,真香。

相關文章
相關標籤/搜索