flutter offset_用Flutter实现58App的首页

背景

Flutter作为全新跨平台应用框架,在页面渲染和MD开发上优势明显,可谓是业界一枝独秀。正好最近有这样的一个机会学习Flutter开发,我们便尝试用它开发一个MD风格的较复杂页面,来比较跟原生应用开发的优势。也是想通过对新框架的学习探索,找到适合自身应用的框架。

页面展示

首页是整个应用里边交互最为复杂的一个页面了,它集合了各种滑动方式,包括:纵向滑动、横向滑动、嵌套滑动;同时,也集合了各种动效,包括:下拉刷新、上拉加载、头图视差、二级吸顶、回到顶部、横向Banner和纵向News轮播等。

d3231bf038f1b249aab122420ee32bb4.png

开发历程

  • 搭建了开发环境,新建flutter module并学习dart语法

  • 调研用Flutter实现CoordinatorLayout的方案

  • 实现了首页主框架的demo搭建,目前同样遇到了滑动冲突的问题,在调研解决方案

  • 解决了滑动冲突的问题,并集成了下拉刷新能力

  • 完成了各区块和feed流的静态UI内容,目前剩余feed流加载更多和负二楼动效

  • 实现首页feed流的加载更多功能

技术难点

两级吸顶

在Flutter中实现吸顶功能比较容易,使用SliverPersistentHeader控件或者间接使用该控件都可以满足吸顶的功能;更重要的是,它支持滑动过程中任意组件的吸顶,即多级吸顶功能。

既然多级吸顶都支持,那么两级吸顶就很轻松了,首页头部和feed流tab的两级吸顶是这样实现的:第一级,使用SliverAppBar(它内部就是一个SliverPersistentHeader控件),不仅可以吸顶,还带有折叠属性,折叠属性能更好的满足头部滑动时的动效处理;第二级,使用SliverPersistentHeader并自定义它的delegate,通过pinned属性灵活选择当前模块吸顶与否,这样可以实现任意组件的吸顶功能。

SliverAppBar(
pinned: true,
...,
bottom: PreferredSize(
child: Header(...),
preferredSize: Size(screenWidth, 15),
),
),
SliverPersistentHeader(
pinned: false,
delegate: _SliverColumnDelegate(
Column(...),
)
),
SliverPersistentHeader(
pinned: true,
delegate: _SliverTabBarDelegate(
TabBar(...)
),
),

pinned的原理很简单,将它设置为true内容到达顶部后不会再跟随外层的ScrollView继续滚动;反之,内容则会滚动出容器外。

而native端实现这个二级吸顶却很费力,通常你可能需要事先隐藏一个跟吸顶内容一样的驻顶view在那里,然后在页面滚动时计算吸顶内容是否已经划至顶部,维护驻顶view的可见属性达到吸顶效果。

上面粗犷的两级吸顶完成了,但想要充分满足首页的折叠效果和准确的二级吸顶需求,还得深挖一下AppBar内部的折叠计算方法。

SliverAppBar折叠计算

SliverAppBar通常作为页面头部使用,是会随内容一起滑动的一个组件;它的构造方法中有四个Widget类型的参数。分析Widget类型的参数,是因为我们需要一个容器来满足自定义首页头部——它既能实现吸顶,又可以接入自定义组件。

  • leading // 左侧按钮

  • title // 标题

  • flexibleSpace // 可以展开区域

  • bottom // 底部内容区域

回顾一下首页的折叠展示效果,首先排除了leading,因为它的位置大小只是一个按钮的位置,显示比较局限;然后title受leading占位影响宽度有限制也无法满足需要;之后,就剩下两个参数可选了,从命名上看,感觉flexibleSpace更符合折叠效果的实现思路,然后一直在尝试使用其实现头部折叠的需求,但开发过程中发现折叠后的高度是无法达到预期的,最大高度也满足不了设计图给的高度。本来想直接排除法使用起bottom的,但是想到一遇到问题就绕过还是有点SUI。那么想知道为什么flexibleSpace会有高度限制,必然得看一下SliverAppBar的实现源码了。

class _SliverAppBarState extends State<SliverAppBar> with TickerProviderStateMixin {
    
...
@override
Widget build(BuildContext context) {
assert(!widget.primary || debugCheckHasMediaQuery(context));
final double topPadding = widget.primary ? MediaQuery.of(context).padding.top : 0.0;
final double collapsedHeight = (widget.pinned && widget.floating && widget.bottom != null)
? widget.bottom.preferredSize.height + topPadding : null;

return MediaQuery.removePadding(
context: context,
removeBottom: true,
child: SliverPersistentHeader(
floating: widget.floating,
pinned: widget.pinned,
delegate: _SliverAppBarDelegate(
...
collapsedHeight: collapsedHeight,
topPadding: topPadding,
),
),
);
}
}

final double collapsedHeight = (widget.pinned && widget.floating && widget.bottom != null)
? widget.bottom.preferredSize.height + topPadding : null;

变量collapsedHeight代表了折叠后头部的高度,从它的计算表达式可看出:当widget.bottom == null的时候,collapsedHeight的值为null。换言之,如果不使用bottom,那么折叠高度是没有的。如果没有折叠后的高度会发生什么?这个需要进一步验证。

const double kToolbarHeight = 56.0;

class _SliverAppBarDelegate extends Sl
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Flutter Zoomable Image 是一个用于 Flutter 应用程序的库,它提供了一个可缩放和拖动的图像小部件。使用 Flutter Zoomable Image,您可以轻松地实现图像的缩放、拖动和捏放手势操作。这对于创建具有可交互性的图像查看器和画廊等应用程序非常有用。 要使用 Flutter Zoomable Image,您需要在项目的 `pubspec.yaml` 文件中添加依赖项,并运行 `flutter packages get` 命令来获取库。 以下是一个简单的示例代码,演示了如何在 Flutter 中使用 Zoomable Image: ```dart import 'package:flutter/material.dart'; import 'package:flutter_zoomable_image/flutter_zoomable_image.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Zoomable Image Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: MyHomePage(), ); } } class MyHomePage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Zoomable Image Demo'), ), body: Center( child: ZoomableImage( AssetImage('path/to/your/image.jpg'), placeholder: Center(child: CircularProgressIndicator()), backgroundColor: Colors.black, ), ), ); } } ``` 在上面的示例中,我们创建了一个简单的 Flutter 应用程序,其中包含一个使用 ZoomableImage 小部件的页面。ZoomableImage 接受一个 AssetImage 对象作为图像源,并提供了一些可选参数,例如 placeholder(用于在图像加载期间显示的小部件)和 backgroundColor(用于设置图像背景色)。 您可以根据自己的需求定制 Zoomable Image 的样式和行为。要了解更多关于 Flutter Zoomable Image 的信息和用法,请参考官方文档或库的 GitHub 页面。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值