持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第13天,点击查看活动详情
前言
flutter_swiper是flutter中最好用的swiper,做循环banner展示的首要选择,样式多,使用简单。下面主要分享下flutter_swiper的几个需要注意的地方/小技巧。
SwiperLayout.STACK 布局
flutter_swiper提供了几个布局供我们使用,不过部分布局相对来说不够自由。
比如STACK,固定的方向是右向左的渐出,无法修改。
那我们要左向右的渐出,怎么做呢?当然不用修改源码这么麻烦的事情,可以想一下,既然有向右的方向的布局,那水平翻转一下,是不是就是向左方向的布局了。
水平翻转的方法
Transform(
transform: Matrix4.diagonal3Values(-1, 1, 1.0),
alignment: Alignment.center,
child: child,
)
翻转后
然后我们会发现,里面的Item也水平翻转了。这时候,我们可以再次对Item水平翻转,这样,Item就翻回来了。
itemBuilder: (context, index) {
return Transform(
transform: Matrix4.diagonal3Values(-1, 1, 1.0),
alignment: Alignment.center,
child: _buildItem(),
);
}
这样左向右方向的STACK布局就完成了,其他类似的问题也可以用这种翻转再翻转的方式解决。
多余的间距如何去除
有些布局会因为动画或者什么的原因,带有一些空白间距。再拿STACK举例,转换成左向右之后,可以看到左边有明显的一大块空白
这种比较麻烦,因为可能设计就是如此。在不改源码的情况下,可以尝试暴力解决
Stack(
alignment: Alignment.centerLeft,
children: [
Positioned(
left: -45,
right: 0,
child: Swiper
Stack 默认使超出可视部分不显示,所以可以偏移负的距离,来抵消多余的间距。
可能需要细调一下,因为不确定具体偏移了多少。比较暴力的方式。
与Hero结合的问题
常见的一种需求是,点击可循环播放的图片列表,进入到对应放大的图片查看器(PhotoView)中,还带有对应的Hero动画。
看起来就是使用Hero将图片和PhotoView中heroTag对应上。但实际操作之后,你会发现,会经常报错:
I/flutter ( 8790): Another exception was thrown: There are multiple heroes that share the same tag within a subtree.
为什么呢?因为循环的方式,一般是前后补位的方式,即比如abc三个元素,第一个的位置的前面,插入复制的最后一个元素 (c),最后一个位置的后面,插入原来的复制的第一个元素 (a),也就是
(c) a b c (a)
当滑动到 (c) 时,无动画切换到元素c;当滑动到 (a) 时,无动画切换到a。
这样就实现了循环。
但这时问题就出现了,(c)和c,(a)和a,实际上返回的index下标都是最终的下标,对我们来说,他们只有两个(c和a),但内部实现的却是有四个不同元素。
也就是说,heroTag 对于(c)和c,(a)和a分别使用的是相同的tag,导致了他的报错。
解决方案
可以考虑将Hero更改到Swiper层,而不是Item层,然后进入PhotoView初始化Swiper时,初始化对应的index下标;然后在页面返回时,设置切换后的index下标。
PhotoView
Hero(
tag: 'photo',
child: Swiper(
index: currentIndex,
...
)
)
Picture
final index = await NrNavigator.push(...);
if (index != null) {
swiperController.move(index, animation: false);
}
这样就可以实现Swiper带Hero动画的效果了。
总结
再完善的组件也不能考虑到所有的问题,可以思考怎么结合一些方法来达到自己想要的效果,不一定要修改源码。