Flutter 仿掘金微信图片滑动退出页面效果

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的参数

parameterdescriptiondefault
child需要包裹的页面-
slidePageBackgroundHandler在滑动页面的时候根据Offset自定义整个页面的背景色defaultSlidePageBackgroundHandler
slideScaleHandler在滑动页面的时候根据Offset自定义整个页面的缩放值defaultSlideScaleHandler
slideEndHandler滑动页面结束的时候计算是否需要pop页面defaultSlideEndHandler
slideAxis滑动页面的方向(both,horizontal,vertical),掘金是vertical,微信是Bothboth
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 也是不会生效的

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助

因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
资料的朋友可以戳我获取!!**](https://bbs.csdn.net/topics/618165277)

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

  • 17
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
你可以使用 `GestureDetector` 组件来监听长按事件,并在长按时显示一个底部的菜单栏,用于选择多个消息。下面是一个简单的示例代码: ```dart class ChatMessage { final String content; bool selected; ChatMessage(this.content, {this.selected = false}); } class ChatScreen extends StatefulWidget { @override _ChatScreenState createState() => _ChatScreenState(); } class _ChatScreenState extends State<ChatScreen> { final List<ChatMessage> messages = [ ChatMessage("Hello!"), ChatMessage("How are you?"), ChatMessage("I'm fine, thanks."), ChatMessage("What about you?"), ChatMessage("I'm good."), ]; List<ChatMessage> selectedMessages = []; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("Chat"), ), body: ListView.builder( itemCount: messages.length, itemBuilder: (context, index) { final message = messages[index]; return GestureDetector( onLongPress: () { setState(() { message.selected = true; selectedMessages.add(message); }); }, child: Container( padding: EdgeInsets.all(16.0), color: message.selected ? Colors.grey[300] : null, child: Text(message.content), ), ); }, ), bottomNavigationBar: selectedMessages.isNotEmpty ? BottomAppBar( child: Row( children: [ IconButton( icon: Icon(Icons.delete), onPressed: () { setState(() { messages.removeWhere((message) => selectedMessages.contains(message)); selectedMessages.clear(); }); }, ), Text("${selectedMessages.length} selected"), ], ), ) : null, ); } } ``` 在这个示例中,我们创建了一个 `ChatMessage` 类来表示聊天消息。`selected` 属性表示该消息是否被选中。在 `ChatScreen` 中,我们创建了一个 `messages` 列表来存储所有的消息,以及一个 `selectedMessages` 列表来存储被选中的消息。在 `ListView.builder` 中,我们使用 `GestureDetector` 来监听长按事件,并在长按时将消息标记为选中状态,并将其添加到 `selectedMessages` 列表中。在底部菜单栏中,我们显示了一个删除按钮和一个文本框,用于显示选中的消息数量。当用户点击删除按钮时,我们从 `messages` 列表中删除所有被选中的消息,并清空 `selectedMessages` 列表。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值