整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

如何处理界面细节:iOS14 中「时间控件」的设计

辑导读:前段时间, iOS14 升级了。苹果的每一次升级都会引起人们的广泛关注,毕竟它代表着行业标杆。本文作者在使用的过程中,对iOS14 中「时间控件」的设计产生了疑问,并从三个方面展开分析,提出自己的一点思考,与你分享。

前几天升级 iOS14 后在「日历APP」中遇到个「时间控件」使用体验问题,在朋友圈「吐了个槽」后收到很多类似反馈,后来在使用「提醒事项APP」中发现有个类似「时间控件」,体验下来感觉挺顺溜,于是想做个对比分析看看区别。

防杠说明1:接下来聊的体验纯我的「主观感受」,对比分析也是基于过往的经验来聊,没有数据也没有其他支撑,交流为主,无他意求放过。

防杠说明2:苹果在「日历APP」和「提醒事项APP」这 2 个 APP 设计一定有考虑过,文章纯粹从外部视角去聊体验感受,不聊 APP 的场景&战略&定位。

一、iOS14 的「时间控件」长什么样

iOS14 「日历APP」新建日程&点击展开「时间控件」后的状态

先介绍下「时间控件」长什么样,上图左边是「日历APP」中「新建日程」界面,点击「开始-时间」后就展开了「时间控件」,控件中分别有这5个功能:时钟控件(键盘+触摸)、年月控件、快捷切换月份控件、日历控件、时区功能,「提醒事项APP」的「时间控件」界面基本差不多,具体差异会在在对比中展示。

二、开始做3个角度对比

对比1:日历间距处理

整体来看「时间控件」中的「日历」是问题最大影响体验最大的地方,「日历」中的日期和日期之间的距离是大过日期和左右屏幕的距离,这会导致日历看起来比较散不是一个整体,见下图中黄色标记和蓝色标记。

这类型的问题属于「格式塔理论」中的「Law of Proximity接近法则」,间距没有起到把相关元素粘起来的作用,相反把元素拆散,有种信息量很多密密麻麻的感受。

「日历APP」中日期之间间距和屏幕间距对比

具体「Law of Proximity 接近法则」的意思是:相互接近的事物被认为比相隔较远的事物更加相关。

格式塔理论中的接近法则示意图

这里密密麻麻的感受还有另一个理论基础「米勒定律」,因为人同时处理信息大约是「7±2」条信息,当信息量超出这个数量后出现,本能上一定是先排斥的,大家回想下如果你要填写一个复杂表单时候的场景,就是这样的感觉。

米勒定律的示意图

我们对比下「提醒事项APP」中的日历选择,间距处理保证了日期距离是比外面小的,日历看起来就是一个整体可操作的控件状态,如果拿「格式塔理论」和「米勒定律」来看的话都是在合理范围内,事实感受也是这样

「日历APP」和「提醒事项APP」日历进行对比

对比2:上下层级关系处理

「时间控件」是通过点击展开的,如果这个简单控件,仅展开动效足以让用户理解,只是这「时间控件」中包含5个功能占了 1/2 的屏幕,动效解决不了,加上「对比1」的日历间距问题,信息量巨大且复杂。控件里面除了标题做了「文字加粗」处理去表现层级,在「上下衔接 or 左右递进 or 背景颜色」都没做很多工作。

和上一级样式是在太接近,没有能明显区分开,和上一层级融合到一起后,界面看起来从一行行就变成点击后一下子增加「爆发式」的信息出现,观感复杂+信息量变大。如果处理合适「理想中的层级关系」应该是图片右边这样的,用户一眼看到的是一块块而不是一个个。

日历APP 时间控件展开后感觉是「碎裂」,理想应该右侧这样块状的层级结构展开。

再来对比「提醒事项APP」中的层级关系,整个「时间控件」左右都有缩进,左上和上一级的衔接处分割线也做了处理,加上上一级日期标题前有个「日历ICON」,很自然在视觉上就出现了上下层级关系出现,内容一样看起来清晰简洁很多。

「提醒事项APP」中用缩进和风格线去表现层级关系

对比3:页面布局上的对比

再把视角放到页面布局中,「日历APP」采用的是边到边布局(Edge to Edge)方式,「提醒事项APP」采用的是卡片式布局(Card)方式。

在 iOS 系统中「边到边布局」是从 iOS7 后苹果开始采用的方式,优势是把极大增加了屏幕空间利用率,可显示内容增加,当时主打机型是 4 英寸屏 的iPhone5s,,屏幕空间有限。

iOS6 和 iOS7 设置界面的对比

从图片中里面是不是感觉 iOS6 也有点卡片式布局的意思,其实大家当时对 iOS6 印象还是「拟物化」,这里也就不展开了。

「卡片式布局」是被 Google 推崇起来的,当时有款产品叫「Google Now」(现在已经下线),这个产品可以语音互动&主动提醒(飞机、路况、比赛比分、突发新闻等等)信息内容给到你,包含的信息内容多样且复杂,用了卡片设计去解决了信息多而不乱的问题,信息和信息之间互不受到影响。

GoogleNow 主界面,卡片设计为主

「Google Now」产品已经下线,找了个介绍视频(https://v.qq.com/x/page/f03052ojg4u.html),大家可以注意里面不同场景下的卡片的布局都是不同的,也方便未来的扩展。

回到这两个页面布局对比中,不过不展开「时间控件」这样对比来看两边布局并没有很大的问题,具体看是要更多「包容」还是要「屏效」。

不过这里我们对比的是「时间控件」,这部分看来「卡片式布局」是更合适的,布局能包容不同复杂的信息,块和块&功能和功能之间是更加清楚,不会引起混乱。

现在很多产品也都在考虑「卡片式布局」,像「手机淘宝」这两年基本上已经完全改造成「卡片式布局」,我理解是因为手淘信息流复杂&个性,照片和元素的出现都不是固定的,用卡片作为「容器」去包容「内容」,让界面有秩序。

但这里还是要提一嘴信息流不要「无脑」追「卡片式布局」是最好,比如媒体为场景的APP,显然「边到边布局」显然更合适,比如 Instagram ,要给照片以更多的展示空间,也比如电商中对商品品质有信心的,那也适合「边到边布局」,比如 SNKRS,对球鞋品质表现的更加到位。

先理解再去设计「适合自家产品」的风格是个挺重要的事,毕竟一个产品风格会用很久,改动成本很高。

三、最后总结一下

真的是抱着「心惊胆战」的心情去做的对比,苹果设计一直都是行业标杆,这次是想趁聊对比时「抛砖引玉」聊聊「界面细节是如何决定设计品质」,这些东西非常小,合作上下游也不一定在意,觉得差不多就好。现在产品迭代速度飞快,留给设计师的时间也不多,怎么样能够快速有效地把细节处理好,是一个值得长期讨论的话题。

最后抽取一些文章中的「关键词」做个总结:

  • 间距控制:有些设计师出稿或工程师开发&验收时会忽略「间距」的价值,其实「间距」对设计品质影响非常大,背后设计理论支撑是「格式塔理论」,如果对「间距」不敏感,那要多练习练习去找好的产品设计去观察和感受。
  • 米勒定律:很多人看界面觉得乱,为什么感觉乱背后可以通过「米勒定律」做设计理论支撑,人在同一时间处理信息程度是「7±2」个,数量越多越乱。
  • 层级关系:表单或复杂页面中的界面需要把层级关系表现到位,不然界面会乱七八糟,在 iOS11 时候苹果已经注意到这一点并且已经提倡过,阅读了解「iOS11 设计理念和 3 个设计方向」。
  • 边到边布局:一种屏幕效率利用高的界面布局,在iOS7 开始后被使用
  • 卡片式布局:一种能够把复杂信息有序融合在一起的布局,更多包容和扩展

好了,今天和大家就唠叨到这。

作者:icojump,微信公众号:边设计边管理

本文由 @icojump 原创发布于人人都是产品经理,未经作者许可,禁止转载

题图来自Unsplash,基于CC0协议

项目中前端(angular)开发中需要使用到基于时间线的UI控件,初步调研两种,可以参考下面链接

https://ng.ant.design/components/slider/zh

https://echarts.apache.org/zh/cheat-sheet.html

https://echarts.apache.org/zh/option.html#timeline

echarts的timeline

本文进行了简化和集成进angular中,需求是基于时间线展示北京、天津、河北、南京四地2000年每个月的经济指标。最终效果图:

首先在html中,声明div

<div id="lineChart" style="width:100%;height:500px"></div>

在ts脚本中

import { Component, OnInit } from '@angular/core';
import { EChartOption } from 'echarts';

import * as echarts from 'echarts';
import { title } from 'process';

@Component({
  selector: 'app-echart-time-demo',
  templateUrl: './echart-time-demo.component.html',
  styleUrls: ['./echart-time-demo.component.css']
})
export class EchartTimeDemoComponent implements OnInit {
  initCharts() {
    const ec = echarts as any;
    let lineChart = ec.init(document.getElementById('lineChart'));

    let lineChartOption = {
      baseOption: {
        timeline: {
          axisType: 'category',//time
          // realtime: true,
          // loop: false,
          autoPlay: true,
          // currentIndex: 2,
          playInterval: 1000,   
          //时间线刻度值      
          data: [
            '2000-01', '2000-02', '2000-03',
            '2000-04', '2000-05', '2000-06',
            '2000-07', '2000-08', '2000-09',
            '2000-10', '2000-11', '2000-12'
          ],
          label: {
            formatter: function (s) {
              return s;
            }
          }
        },

        title: {
          subtext: '数据来自国家统计局'
        },
		
        xAxis: [{
          type: 'category',
          data: ['北京', '天津', '河北', '南京'],
        }],
        yAxis: [{
          type: 'value'
        }],
        //第一组数据展示形态
        series: [{
          type: 'bar'
        }],
      },
      options: [
        {
          title: {
            text: '2000年1月四地经济指标'
          },
          series: [
            { data: [4315, 2150.76, 16018.28, 20000] }
          ]
        }, {
          title: {
            text: '2000年2月四地经济指标'
          },
          series: [{
            data: [5007.21, 2578.03, 6921.29, 20000]
          }]
        },
        {
          title: {
            text: '2000年3月四地经济指标'
          },
          series: [{
            data: [6033.21, 3110.97, 8477.63, 20000]
          }]
        }, {
          title: {
            text: '2000年4月四地经济指标'
          },
          series: [{
            data: [6033.21, 3110.97, 8477.63, 20000]
          }]
        }, {
          title: {
            text: '2000年5月四地经济指标'
          },
          series: [{
            data: [6033.21, 3130.97, 8477.63, 17000]
          }]
        }, {
          title: {
            text: '2000年6月四地经济指标'
          },
          series: [{
            data: [6033.21, 3110.97, 8177.63, 25000]
          }]
        }, {
          title: {
            text: '2000年7月四地经济指标'
          },
          series: [{
            data: [6433.21, 3110.97, 8477.63, 10000]
          }]
        }, {
          title: {
            text: '2000年8月四地经济指标'
          },
          series: [{
            data: [6033.21, 4110.97, 8477.63, 11000]
          }]
        }, {
          title: {
            text: '2000年9月四地经济指标'
          },
          series: [{
            data: [6033.21, 5110.97, 8477.63, 20000]
          }]
        },
      ]
    }
    lineChart.setOption(lineChartOption);
  }

  constructor() { }

  ngOnInit() {
    this.initCharts();
  }
}

从上文的图片中,列表中只展示四个地区的一组数据,未能充分利用,所以考虑再增加一组2000每月四地的消费指标,所以series里增加一个维度

 series: [{
          type: 'bar'
        },{
          type: 'bar'
        }],

而数据里也要增加一组数据

  series: [{
            data: [6033.21, 4110.97, 8477.63, 11000]
          },
          {
            data: [6033.21, 4110.97, 8477.63, 11000]
          }]

如图,柱状图中各地指标多了一组

使用 axisType: 'time'

上文中使用的 axisType: 'category',这样会将时间线上的坐标等分,简单来说两个刻度间距离相等,但实际使用中可能存在刻度间不是等分的,如1:00到1:10到2:00到3:00,很明显1:00到1:10只过了10分钟,直观上这两个刻度距离要小点。所以在echarts中提供了axisType为time的配置。

  let lineChartOption = {
      baseOption: {
        timeline: {
          // axisType: 'category',
          axisType: 'time',
....
          data: [
            '2000-01', '2000-03',
            '2000-04', '2000-05', '2000-06',
            '2000-07', '2000-08', '2000-09',
            '2000-10', '2000-11', '2000-12'
          ],
          label: {
            formatter: function (s) {                  
				 return (new Date(s).getMonth()+1)+'月';
            }
          }

上面的刻度数据(注意是时间格式)中是没有2月份的,使用time,要特殊处理如label的formater。最终效果如下,发现由于2不存在,所以1到3自动跨两个刻度。

事件timelinechanged

章目录

一 bootstrap 时间日期日历控件datetimepicker

应用

涉及的样式

图片样式展示

pc

手机

属性及使用示例

可用属性列表

示例1:2017-03-30 上午 09:50

示例2:2017-03-30

示例3:仅选择时间

2.3 weekStart 一周从那一天开始

2.4 startDate 开始时间

2.5 endDate 结束时间

2.6 daysOfWeekDisabled 一周禁用的日期

2.7 autoclose 是否自动关闭日期选择器

2.8 startView 日期时间选择器打开之后首先显示的视图。

2.9 minView 日期时间选择器所能提供的最精确的时间选择视图

2.10 maxView 日期选择器最高能展示的范围视图

2.11 todayBtn 是否显示'today'按钮

2.12 todayHighlight 当天日期高亮

2.13 keyboardNavigation 方向键改变日期

2.14 language 语言

2.15 forceParse 强制解析

2.16 minuteStep 步进值

2.17 pickerPosition 选择框的位置

2.18 showMeridian 是否显示上午/下午

2.19 initialDate 初始化日期时间

3.1绑定输入框,并设置format选项

3.2作为组件使用:

3.3时间范围选择联动

具体属性展示

一 bootstrap 时间日期日历控件datetimepicker

应用

手机

pc

涉及的样式

<link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">

<link href="https://cdn.bootcss.com/bootstrap-datetimepicker/4.17.47/css/bootstrap-datetimepicker.min.css" rel="stylesheet">


<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>

<script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>

<script src="static/js/moment-with-locales.js"></script>

<script src="https://cdn.bootcss.com/bootstrap-datetimepicker/4.17.47/js/bootstrap-datetimepicker.min.js"></script>

1

2

3

4

5

6

7

图片样式展示

pc

<div class="col-sm-4">

<div class="input-group">

<span class="input-group-addon">开始日期</span>

<a class='input-group date' id='datetimepicker3'>

<input type='text' class="form-control" id="startDate" readonly/>

<span class="input-group-addon">

<span class="glyphicon glyphicon-calendar"></span>

</span>

</a>

<span class="input-group-addon">~</span>

<span class="input-group-addon">结束日期</span>

<a class='input-group date' id='datetimepicker4'>

<input type='text' class="form-control" id="endDate" readonly/>

<span class="input-group-addon">

<span class="glyphicon glyphicon-calendar"></span>

</span>

</a>


</div>

</div>


<div class="form-group col-lg-6">

<div class="input-group">

<span class="input-group-addon">活动结束日期</span>

<a class='input-group date' id='datetimepicker2'>

<input type='text' class="form-control" id="activityEnd" name="activityEnd"/>

<span class="input-group-addon">

<span class="glyphicon glyphicon-calendar"></span>

</span>

<span class="input-group-addon" style="color:#F00">*</span>

</a>

</div>

</div>


手机

<div class="form-group">

<div class="input-group date form_date" id="datepicker" data-date="" data-date-format="dd MM yyyy" data-link-field="dtp_input2" data-link-format="yyyy-mm-dd" style="width:92%;">

<input class="form-control" size="16" type="text" value="${initialDate}" name="PARAM9" readonly="readonly" id="PARAM9">

<span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>

</div>

<input type="hidden" id="dtp_input2" value="" />

</div>

1

2

3

4

5

6

7

属性及使用示例

<input type="text" readonly class="date" data-link-field="date" />

<input type="hidden" id="date" />

$('.date').datetimepicker();

1

2

3

选中的日期会被存放在id为date的input里。

//设置日期时间控件

$('#datetimepicker1').datetimepicker({

language: 'zh-CN',//显示中文

format: 'yyyy-mm-dd hh:ii:ss',//显示格式

minView: 0,//设置只显示到月份

initialDate: new Date(),

autoclose: true,//选中自动关闭

todayBtn: true,//显示今日按钮

locale: moment.locale('zh-cn')

});