本文为社区首发签约文章,14天内制止转载,14天后未获授权制止转载,侵权必究!

前语

如果要说哪些元素是 App 最常见的,列表必定位列其中。资讯、商品、联系人、消息……等等都是以列表的方式呈现在咱们的手机屏幕上。能够说,咱们每天打交道最多的便是列表,在手指滑动之间,时间真的在指缝中消逝。列表中,最为要害的体会是加载进程的处理,有必要做好体会。

进入列表

首次进入列表时,这个时分通常会是一个空白页面,而人天然生成对不知道的事物感到不安。因而,进入列表等候的进程一直坚持空白的体会是很糟糕的。咱们来看看常见的三种进入列表的页面加载情形。 第一种,最普通,便是在加载进程中给一个转圈指示,这是许多开发者接触最多的完成方法,因为最简略!比方拿 Flutter 来说,三元操作符就搞定了。当然,我还见过最偷闲的,便是连个转圈都没有,直接白屏让用户干巴巴地等,碰到网络不好,用户等到花都谢了 —— 当然,App 也被卸了

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: const Text('加载'),
    ),
    body: _isLoading
        ? const Center(child: CircularProgressIndicator())
        : ListView(),
  );
}

列表的加载过程很重要的!
第二种,其实仍是loading 动效,仅仅增强趣味性来进步用户等候的体会,下面是从 Dribble 找到的一个风趣的 loading 动效。说实话,我碰到这种风趣的运动 loading,总是会试图找出其中的运动规律,所以等候一会有时分完全感受不到等候的进程。
列表的加载过程很重要的!
这种动效自己写的话还挺费时间的,不过有相应的东西来制造,比方Airbnb推出的 Lottie,适用于 Android、iOS 和 React Native,能够将 AE (Adode Effect)制造的动效直接渲染成动画。对于 Flutter,有人将 Lottie 移植到了 Flutter,也是大受欢迎,包地址为:Flutter版 Lottie。Lottie 运用十分简略,从本地加载 AE 导出的json 文件即可,也支撑从压缩包或网络加载动画文件。咱们来看一个示例,这是一个运送货车的动画。所以,以后设计师出 loading 动效让你完成的时分,你能够让他放马过来了!

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: const Text('加载'),
    ),
    body: _isLoading
        ? Center(
            child: Lottie.asset(
              'assets/delivery_van.json',
              repeat: true,
            ),
          )
        : ListView(),
  );
}

列表的加载过程很重要的!
第三种是骨架屏,这种现在在许多信息流类的 App 上已经很常见了。说实话,前期出来的时分感觉还挺冷艳的,现在已经见怪不怪了。骨架屏在之前的图片体会篇有介绍过了,这儿就不再赘述。

下拉改写

下拉改写已经十分遍及了,能够说经过下拉和上滑加载更多是手机端列表交互十分大的创新。在此之前,还有模仿 PC 端做分页的处理,那种体会远不如下拉改写和上滑加载更多。与空白页加载类似,改善体会的要害点在于优化等候进程,比方加载进程中给一个风趣的动画作用。这儿推荐 Flutter 一个不错的组件:custom_refresh_indicator。下面是结合了之前的一篇自定义 loading 动效的示例代码:

@override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('加载'),
      ),
      body: CustomRefreshIndicator(
        onRefresh: refresh,
        builder: (context, child, controller) {
          return Stack(alignment: Alignment.topCenter, children: [
            AnimatedBuilder(
              builder: (context, _) {
                return Transform.translate(
                  offset: Offset(0.0, controller.value * _loadingHeaderSize),
                  child: child,
                );
              },
              animation: controller,
            ),
            controller.state.isLoading
                ? LoadingAnimations(
                    foregroundColor: Colors.blue,
                    bgColor: Colors.transparent,
                    size: _loadingHeaderSize,
                  )
                : const SizedBox(height: 0.0)
          ]);
        },
        child: ListView.builder(
          itemBuilder: (context, index) {
            return const ListItem();
          },
          itemCount: 10,
        ),
      ),
    );
  }
}

完成作用如下所示,经过风趣的下拉改写动画能够相当大程度缓解用户等候进程中的焦虑。

列表的加载过程很重要的!

上滑加载更多

上滑加载更多和下拉改写其实是相同的,仅仅也需要在等候进程给予风趣的提示。这儿提出来主要是顺带讲一下 custom_refresh_indicator的上滑加载更多。CustomRefreshIndicator有两个要害的特点:

  • trigger:决议触发改写的方向,是下拉(leadingEdge)仍是上滑(trailingEdge),或者一起触发(bothEdges)。因而,如果要一起支撑下拉改写和上滑加载更多就需要设置为bothEdges
  • controller:整个CustomRefreshIndicator的状况信息都由controller存储,因而能够获取滑动进程中的状况,比方滑动方向,开释后滑动进程的比例等等。咱们能够依据这个来控制等候动画显现的方位。这能够让咱们经过一个 AnimationBuilder 来构建松开手开释后的动画进程。

比方下面的代码便是在下拉改写的基础上增加了上滑加载更多的作用。这儿一个是经过滑动方向设置 offsetRatio的符号来控制开释后列表是往上移动(下拉改写)仍是往下移动(上滑加载)。另一个便是依据滑动的方向决议 Stack 组件里的加载动画组件是顶部对齐仍是底部对齐,从而控制加载动画组件出现是在顶部(下拉改写)仍是底部(上滑加载)。

CustomRefreshIndicator(
    onRefresh: refresh,
    builder: (context, child, controller) {
      double offsetRatio =
          controller.scrollingDirection == ScrollDirection.forward
              ? 1.0
              : -1.0;
      return Stack(
        alignment: controller.scrollingDirection == ScrollDirection.forward
            ? Alignment.topCenter
            : Alignment.bottomCenter,
        children: [
          AnimatedBuilder(
            builder: (context, _) {
              return Transform.translate(
                offset: Offset(0.0,
                    offsetRatio * controller.value * _loadingHeaderSize),
                child: child,
              );
            },
            animation: controller,
          ),
          controller.state.isLoading
              ? LoadingAnimations(
                  foregroundColor: Colors.blue,
                  bgColor: Colors.transparent,
                  size: _loadingHeaderSize,
                )
              : const SizedBox(height: 0.0)
        ],
      );
    },
    trigger: IndicatorTrigger.bothEdges,
    child: ListView.builder(
      itemBuilder: (context, index) {
        return const ListItem();
      },
      itemCount: 10,
    ),
  ),

运转的作用如下面的动图所示。

列表的加载过程很重要的!

总结

列表作为 App 中最为常用的组件之一,用户运用列表时,会面对进入列表、下拉改写和上滑加载三个加载等候进程。请记住进步列表等候进程体会的三个原则:

  1. 尽量不要让用户等候太久,比方进步加载速度;
  2. 尽量经过风趣的动画进步等候进程中的趣味性。
  3. 切忌,不要让用户没有任何预期地等。像那种进入后直接白屏,没有任何反应的等候方式是体会最糟糕的!