沉浸式弹层越来越多,开发该怎么做好弹层体验?

语言: CN / TW / HK

theme: v-green highlight: atom-one-dark


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

前言

当前 App 的设计趋势越来越希望给用户沉浸式体验,这种设计会让用户尽量停留在当前的界面,而不需要太多的跳转,这就需要引入弹层。比如,抖音引入购物功能后,就实现了在观看视频界面可以通过弹层完成加入购物车、下单操作,无需离开当前的视频界面。本篇我们就来讲讲弹层这块需要注意哪些用户体验。 image.png

弹层的形式选择

弹层从形式上来说有中间弹层、左侧弹层、右侧弹层、底部弹层和顶部弹层,如下图所示。 image.png 移动端经过这么多年的发展,不同的弹层的应用场景相对来说比较固定。因此,在选择的时候,建议遵循现有的习惯来选择合适的弹层。

  • 中间弹层:通常用于询问对话框形式,例如退出登录、删除操作的二次确认。
  • 左侧弹层:通常用于抽屉式的个人中心或设置界面,这种一般是底部栏无法放下个人中心类界面的时候一个不错的选择。
  • 右侧弹层:通常用于做数据筛选,典型的场景是购物类应用的精准筛选。
  • 底部弹层:这种非常常见,如我们提到的目前抖音的商品购买,还有像单选、多选、级联选择、时间选择等等。
  • 顶部弹层:顶部弹层一般也是用于筛选,比较常见的是列表表头的筛选,或者导航栏带类似 PC 端的下拉类的筛选。

这里需要提两个比较通用的原则:

  1. 弹层出现的位置应当尽量靠近触发交互的位置,比如点击导航栏左上角的按钮通常会从左侧弹出。
  2. 蒙层的颜色要根据实际情况来定,一般都是黑色半透明的蒙层,但是主要面对是为了让用户能够看清蒙层底下的内容,比如如果是在视频播放页面叠加蒙层就会影响用户体验了。

接下来我们依次来用 Flutter 实现上述的5类弹层,并讲讲一些体验要点。

中间弹层

中间弹层在 Flutter中可以通过showDialogShowCupertinoDialog(iOS 风格)实现,下面是示例代码。 dart showDialog( context: context, barrierDismissible: false, builder: (_) => AlertDialog( title: const Text('操作提醒'), content: const Text('确认要进行此操作吗?'), actionsAlignment: MainAxisAlignment.end, actions: [ TextButton( onPressed: () { Navigator.of(context).pop(); }, child: const Text('取消'), ), TextButton( onPressed: () { Navigator.of(context).pop(); }, child: const Text( '删除', style: TextStyle(color: Colors.red), ), ), ], ), ); 这里有一个体验要素是是否支持点击底部的黑色蒙层隐藏弹层。通常来说,如果是二次确认类操作,建议不要点击蒙层隐藏。因为用户的操作目的性非常明确,如果不小心误触的话,用户还得再点击一次。这个时候需要设置barrierDismissiblefalse

左右抽屉弹层

在 Flutter 的 Scaffold 中 提供了两个属性来设置左侧抽屉和右侧抽屉弹层,对应的参数分别是 drawerendDrawer。我们来看看具体的代码。 dart Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('左右抽屉弹层'), backgroundColor: Colors.red[800], leading: Builder(builder: (context) { return IconButton( onPressed: () { Scaffold.of(context).openDrawer(); }, icon: const Icon( Icons.menu, ), ); }), actions: [ Builder(builder: (context) { return IconButton( onPressed: () { Scaffold.of(context).openEndDrawer(); }, icon: const Icon( Icons.filter_list_alt, ), ); }), ], ), drawer: Container( width: MediaQuery.of(context).size.width * 3 / 4, color: Colors.white, child: Center( child: TextButton( onPressed: () { Navigator.of(context).pop(); }, child: const Text('收起'), ), ), ), endDrawer: Container( width: MediaQuery.of(context).size.width * 3 / 4, color: Colors.blue, child: Center( child: TextButton( onPressed: () { Navigator.of(context).pop(); }, child: const Text( '收起', style: TextStyle( color: Colors.white, ), ), ), ), ), body: const Center(child: Text('抽屉示例')), ); } 实现的效果如下图所示。实用左侧或右侧弹层需注意三个体验要素:

  1. 宽度:建议设置为屏幕宽度的3/4,这种宽度抽屉的显示内容足够宽,而底下的蒙层点击区域宽度也比较合适点击退出弹层。
  2. 顶部内容区域需要注意留出一定的头部位置(比如左侧通常会放头像+昵称),一个是美观,一个是要避免显示内容碰到了手机屏幕的挖孔位置。
  3. 一般侧边弹层点击蒙层都会支持收起,所以建议保留这个操作习惯,而不是非得点弹层的某个按钮才关闭弹层。

drawer.gif

顶部弹层

顶部弹层在 Flutter 中需要自己去实现,一个比较好的方式是使用 showGeneralDialog来实现。这里有个技巧是实用 Column 组件可以让内容区靠顶部,然后利用动画实现从上往下滑的弹出效果。下面是实现代码,实际通过这种方式可以实现底部,左侧,右侧和中间的弹层。 dart showGeneralDialog( context: context, barrierDismissible: true, transitionDuration: const Duration(milliseconds: 300), barrierLabel: MaterialLocalizations.of(context).dialogLabel, barrierColor: Colors.black.withOpacity(0.5), pageBuilder: (context, _, __) { return Column( mainAxisAlignment: MainAxisAlignment.start, children: <Widget>[ Container( width: MediaQuery.of(context).size.width, color: Colors.white, child: Card( margin: const EdgeInsets.all(0), child: ListView( shrinkWrap: true, children: <Widget>[ ListTile( title: const Text('选项 1'), onTap: () => Navigator.of(context).pop('1'), ), ListTile( title: const Text('选项2'), onTap: () => Navigator.of(context).pop('2'), ), ListTile( title: const Text('选项3'), onTap: () => Navigator.of(context).pop('3'), ), ], ), ), ), ], ); }, transitionBuilder: (context, animation, secondaryAnimation, child) { return SlideTransition( position: CurvedAnimation( parent: animation, curve: Curves.easeOut, ).drive(Tween<Offset>( begin: const Offset(0, -1.0), end: Offset.zero, )), child: child, ); }, ); 效果如下所示,顶部弹层弹出的方向最好是从上到下,如果是从下到上的话移动距离过长,会觉得很突兀。 顶部弹层.gif

底部弹层

底部弹层和顶部弹层其实是类似的,而且更为常见一点。之前在文章底部弹窗ModelBottomSheet详解有过介绍,这里就不再讲具体实现了。说一下底部弹层的几个体验要点:

  1. 弹出方向从底部往上弹出,动画时长建议200-300毫秒;
  2. 如果是多选这种需要二次确认操作的,需要在顶部提供确认和取消按钮;
  3. 适用选项不太多的场景,如果选择的内容很多建议单独跳转到选择页面完成,并且支持模糊搜索匹配选项;
  4. 需要区分选中项,让用户知道之前的选项;
  5. 如果涉及到网络请求,建议是在网络请求完成后再关闭弹层,因为有可能操作失败导致用户需要再次操作。

总结

本篇介绍了各类弹层开发过程的体验注意点,同时给出了示例代码。随着沉浸式体验的推动,弹层会越来越多,因此建议各位开发同学也能够多多思考弹层如何改善用户体验,虽然咱不是产品经理也不是设计师,但是从开发角度给产品和设计一些专业的意见,也是能够“提升话语权”的,嘿嘿!