首页

上亿人使用的腾讯微视,是如何做品牌体验设计的?

雪涛

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

编者按:微视作为今年腾讯对抗抖音的核心产品,其重要性不言而喻。在短视频App 百花齐放的今天,腾讯微视该如何做品牌设计才能避免同质化,给产品带来价值呢?本文来自腾讯设计师的复盘回顾,你可以看到大厂的完整设计流程是怎样的。

一、项目背景

2017年是整个短视频大爆发的时期,内容产业逐渐成为移动互联网新的生力军。短视频产品同质化,用户体验趋同,团队希望运用品牌体验的全局设计思维,从视觉识别,用户体验,线上线下推广及产品礼品等多个维度来凸显产品核心价值,搭建一套完整统一的产品设计语言。

二、目标

微视目标很清晰,需要在短时间内快速进入短视频第一集团,切入短视频社交领域,挖掘更多机会点,也希望借这个机会能成为像微信这样的腾讯战略级产品。

三、设计挑战

设计的挑战点,短视频无论是产品形态还是设计体验都已成熟,如何避免同质化,在设计上寻求自己的核心竞争力;另外短视频产品强调内容运营,设计如何能够给产品带来价值,也是微视设计在这次的最大挑战。

微视在刚起步阶段,品牌团队曾经给微视做过1.0版本的设计,当时微视的设计思路没有太清晰,最终设计偏向于简洁专注的方向;但随着短视频逐步上升为腾讯的战略方向,微视单一的设计风格已经不能满足本身需求了,微视需要一个更丰富的设计语言,这给微视的新设计重新提供了一次机会。

我们梳理了微视的设计流程,整个微视品牌设计分为三大块内容,策略,设计和体验;设计前期需要明确微视的整体品牌定位以及挖掘产品的核心价值,推导出一套符合产品气质的设计原则,品牌设计上,应该是整个产品的设计语言素材库,其中包括了标志的设计,字体库的建立,色彩系统的搭建,图形延展设计,插画风格的提炼,动效概念等核心设计元素;在最后一环的品牌体验,代表了微视所有的场景媒介,都需要从设计语言素材库内提取设计元素并适配对应的设计,保证所有媒介场景的高度统一。

「做年轻人的潮流分享社区」是整个微视的品牌定位,让年轻人感知玩微视是一种潮流,在微视里能够挖掘更多很酷的事情和有趣内容,成为年轻人分享潮流和趣味的平台;微视的 slogan 是「发现更有趣」,发现更多有趣的人,和事,或者说是一种生活态度;基于整个品牌定位,我们挖掘微视的三大核心价值:保持好奇,寻找生活趣事;微视展现与众不同的自我;打造微视达人的潮流文化。三个核心价值,我们构建出微视的基础设计原则:微视是具备丰富内容和玩法多变的产品;它应该有个性化的标签来彰显自己的态度;微视是一个自带潮流属性的平台,在潮流圈中有很好的认可度,通过它来传播自己的态度和生活方式。

四、微视slogan:发现更有趣

通过整体的品牌策略与其它短视频拉开差异化,当下主要竞品的品牌定位都是强调记录生活,记录美好时刻;微视则强调用户自己,主动去挖掘更多有趣的人,有趣的玩法,生活趣事,探索世界,发现更多精彩。

我们在设计的第一阶段,logo设计,就是围绕「有趣」来展开发散设计。设计方案是否有趣,是我们的第一标准;它可能是一个实际存在的事物,它也有可能是一个抽象的造型,但它必须是有趣值得玩味的,也可能是别的概念会引起你的兴趣点。最终我们决定使用一个特别的播放键来代表微视,播放键的造型能让用户感受它是拥有多个维度的,2D,3D甚至是异度空间等,寓意着用户可以从多个维度来看世界,寻找有趣的内容。

我们针对这个大方向再进行了几轮细化,右边是最终的设计方案,这个 logo 希望它在多数的 app 当中表现的足够抢眼,所以色彩纯度足够高,渐变四色的搭配能让它从众多 app 中跳跃出来。

logo设计确定后,接下来补充 logo 在各使用场景中的基础设计规范,另外会增加一个不带 app底的场景,微视不只是单纯的应用在 app 上,它还需要有很好的扩展性。

四色渐变是微视的品牌色,确定了微视红是它的主品牌色,紫色,蓝色和桃红则是它的子品牌色。

另外在品牌字体的选择上,我们选择了三款原生字体作为微视的标准品牌字体。Fugaz-One 是一款能够广泛用于各种书刊画册的艺术字体,它的大写字体具有强烈的视觉冲击力,选择它作为微视标准英文字体;汉仪雅酷黑也是一款用于艺术设计方面的简体中文字体,字体线条粗壮,字形端正大方,并且字库相对其它艺术字体更完整;汉仪旗黑系列则作为微视信息类字体的补充,汉仪旗黑是汉仪字库推出的一款非常庞大而完整的家族字体,字体的各类粗细度都很齐全,并且能完美的实现各类终端环境的呈现。

微视的 pattern 是从 logo 的造型延展出来的纹理设计,这套 pattern会 应用在许多应用场景上,包括广告,内容模版,周边产品等需要辅助设计的场景中。

△ 微视网站

△ 微视内容模板

△ 品牌视频结束页

Pattern 也会结合激光动效的理念运用到微视的场景中,例如官网设计,内容模版,视频结束页等,Pattern 会作为底层展现品牌形象,在整个过程中会有品牌色激光动效,让整个场景丰富立体起来。

微视logo 具备多维度的特性,将这种特性运用到 UI场景的 loading 和微视水印效果上,增强品牌的独特性和趣味性;另外我们也会将 logo 做成霓虹灯的立体装置在线下活动中展出,让用户感受 logo 的丰富多变。

△ 点击查看完整视频

品牌视频通过多个几何维度来诠释 logo 理念,强调微视品牌趣味性。

结合 logo 的造型特征,我们打造了一套完整的图形系统素材库,里面包含了完整的字母与数字,还有结合短视频特性的图标体系;目前这套素材库仍在不断完善中,所有的图形设计都会运用到后期微视的广告和运营活动当中,霓虹灯的实体效果会结合线下的活动装置中使用,这套图形系统素材库,不但具备很好的品牌识别度,而且强调了微视有趣的设计理念。

品牌体验模块把我们确定的这套设计语言结合到与用户面对面的场景中来。品牌体验主要阐述微视的广告,活动和礼品三大块内容上。

在整体的微视广告设计中,我们把微视达人的个性拆成六大类别,每一类型都会拥有一个抽象的图形来代表这一类人群,向往美好生活和生活趣事的人;作风个性炸裂,酷炫的人;有才华的人;潮流网红;二次元;甚至是闷骚奇葩的人等。

每类个性标签的人群都有与之对应的风格与设计手法匹配,例如美趣标签的设计风格偏向暖色氛围与立体化图形的搭配;炸裂标签的达人,风格酷炫,广告整体运用撞色叠加的手法+霓虹灯的视觉效果;每种标签的设定都会有不一样的定义,让微视的广告语言更丰富和多元化。

微视官方品牌广告采用微视的标准品牌风格,对比其它标签的设计,它需要更加微视的风格。在首波微视推广中都采用了标准风格。我们给每套风格设定一套设计规范,方便后期CP 和其他设计师介入制作广告提供一套标准。

另外在微视的 IP形象微视狗的推广上,也采用微视的品牌风格来宣传。

微视中期的推广投放量非常巨大,所以也是微视广告语言需要多元化的原因,只有一套风格设定,不能满足微视的推广需求,美趣风格也是专门为101打造的微视广告,设定的糖果色氛围和3d设计很符合101女团的风格。

酷炫风强调撞色对比来体现氛围感,搭配品牌霓虹灯的视觉效果来呈现,霓虹灯设计也是运用微视图标素材库里提取出来的元素设计。在 NBA总决赛推广期,微视狗与 nba 合作的广告采用了这套风格设定。

微视广告在后期陆续补充了未来概念,街头时尚等风格,都是围绕大量不同个性的明星设定。

二次元作为近几年影响力逐渐壮大的群体,微视也打造了一套插画风格的设计,风格抽象,色彩纯度高,画质的细节多,适用于年轻搞怪的明星使用。

微视官网也采用插画作为主要设计的风格,这套推广插画偏向潮流感科技感,服装特地设计成 wesee 出品,让用户看到微视和其它竞品不一样的设计定位。

微视设计原则的第二条是微视拥有很强烈的个性标签,代表微视自身的态度。

我们采用了警示带的概念,作为微视品牌的专属元素,警示带能够彰显一个人的态度,同时又有趣味性和潮流感。我们结合了微视达人的特性,提炼出6段个性的词语作为警示带内容(拒绝雷同,发现有趣,忠于态度,潮流支配,躁动时代,极度爆炸)让警示带的设计更多选择和多样化。

在 vans 和微视的联名活动中,微视采用了警示带概念来对整个活动场馆进行铺装。

警示带概念还运用到微视线下潮流商品的设计中,背包,帽子,tee,手机壳等单品。

微视的最后一条设计原则,阐述微视的潮流文化。最主要的场景是在微视的达人商品设计上。

我们不希望只把微视当作是一个短视频的产品来做,设计师希望把它打造成一个新生的潮流生活品牌,无论是在选择产品的类型,到设计,打样,还有拍摄推广,都和普通的公司文化衫,或者纪念品拉开差距。

微视的潮流贴纸,除了作为线下达人活动的礼品,也作为线上APP 贴纸库的内容资源,提供给用户使用。

微视后续会继续生产更多的周边商品,比如拖鞋,背包,卫衣,毛巾等,这些都属于生产周期短,没有复杂工艺,性价比极高,属于潮流圈的基础单品,人手一件。这些单品都拿到能够触达用户的官方线下活动和品牌联名活动中,手递手传播微视的潮流品牌影响力。

总结

微视设计不仅包含了APP的体验设计,还包含了市场营销,运营活动,达人推广,周边商品等多个设计环节,环环相扣,缺一不可,一起构建了整个大微视的设计体系;互联网品牌体验在这几年逐渐显得重要,在如何设计同质化严重的产品上,如何打造竞品差异化的设计上,整体规划清晰的品牌设计能够让产品有更好的唯一性和专属感。

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计  cs界面设计  ipad界面设计  包装设计  图标定制  用户体验 、交互设计、 网站建设 平面设计服务

UI设计中如何配色?

用心设计

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里


颜色跟其他事物一样,使用需要恰到好处。如果您在配色方案中坚持使用最多三种基色,您将获得更好的效果。将颜色应用于设计项目中,要保持色彩平衡,您使用的颜色越多,越难保持平衡。


颜色不会增加设计品质 - 它只是加强了设计的品质感

                                      --皮埃尔·波纳德(Pierre Bonnard)




60–30–10 规则


室内设计规则是一种永恒的装饰技术,可以帮助您轻松地将配色方案放在一起。 60%+ 30%+ 10%的比例是为了保持颜色平衡。这个公式非常有用,因为它创造出一种平衡的感觉,并允许眼睛从一个焦点到另一个焦点舒适地移动。 使用也非常简单。


60%是主色调,30%是副色和10%用于强调色。


e1f458de0ea5a801219c77abf06a.jpg


墙面漆(60%),家具(30%),配饰(10%)


颜色的含义


几个世纪以来,科学家已经研究出某些颜色的生理效应。 除了美学,颜色也是情感交流的创造者。 颜色的含义可能因文化差异而不同。这就是为什么你看到时装店铺的设计是黑白配色。 他们希望看起来优雅而高贵。


a18858de0ebca801219c77eecdb0.jpg


Asos采用纯黑白配色搭配绿色按钮设计,这种配色是有原因的。


  • 红色:激情,爱,危险

  • 蓝色:平静,负责,安全

  • 黑色:神秘,优雅,邪恶

  • 白色:纯净,沉默,清洁

  • 绿色:新生,新鲜,自然


首先考虑单色设计


在项目设计初期,我们通常倾向于尝试不同的颜色进行调整,但这种行为会很快违背你的初衷,当你发现的时候,已经花费了3个小时调整基础色...这确实很诱人,但你应该学会避免这种态度。

相反,你应当专注于元素的间距和整体布局。它会节省你很多时间。 这种约束是非常有成效的。从另一方面讲,它看起来并不乏味。如果你想让整个作品看起来更好,尝试不同的颜色选择。


43da58de08aaa801219c7791a8c3.jpg


我在追波(dribbble)上的作品之一。简约单色处理,专注于元素之间的使用。


避免使用灰色和黑色


我学到的最重要的颜色技巧之一是避免使用灰色等不饱和色彩。 在现实生活中,纯灰色几乎不存在。 黑色也是如此。

b6d358de08d0a801219c7750613e.jpg

这张图片最黑的颜色不是#000,而是#0A0A10


始终记着给你的颜色增加饱和度。潜意识里会显得更自然,为用户所熟悉。


667258de08f5a801219c77147ee4.jpg


相信自然


最好的颜色组合来自大自然。 他们看起来总是很自然。 寻找颜色设计的解决方案,最好的办法是调色板总是发生变化。


为了得到设计灵感,我们只需环顾四周。


975d58de0910a801219c7714bed0.jpg


保持对比


一些颜色相互融合,而其他颜色一起使用会发生冲突。 有一个明确的规则,想要了解不同颜色之间如何融合,最好的办法是观察一个色轮。 你应该知道这个方法,但是没有必要动手操作。


f09d58de095fa801219c77f5485c.jpg


获取灵感


当我们在谈论UI参考时,dribbble是最佳选择。它还具有通过颜色搜索的工具,所以当你想对其他设计师使用特定颜色进行视觉研究时,然后去这里:dribbble.com/colors


5ce458de097ba801219c77aa763e.jpg


视频,平面广告设计,室内设计,时装......有这么多鼓舞人心的地方可供收集。如果说根本就没有配色参考,那一定是懒惰的原因,把那些调色板保存下来,一切看起来都非常有趣。


通常我喜欢从KPOP(韩国流行音乐)视频剪辑中选取颜色,他们看起来很华丽。


配色工具推荐


为了方便起见,我搜集了一些最好的配色工具可供选择,在2017年获取调色板,他们会为您节省大量的时间。



Coolors.co


这个绝对是我最喜欢的取色工具。 您只需锁定所选颜色并按空格即可生成调色板。 Coolors还可让您上传图像并从中调出调色板。 很酷的事情是,你不仅仅是一个结果,而是有一个选择器,允许你修改参考点。


a68a58de0c65a801219c77885e56.jpg



Kuler


这款Adobe旗下的配色工具已经和我们在一起了很长时间。它在浏览器和桌面版本中都可用。 如果您使用的是桌面版本,则可以将配色方案导出到Photoshop中。


296e58de0c83a801219c77fbb98e.jpg


Paletton


它类似于Kuler,但不同的是,您不仅限于5个色调。 当您拥有原色并希望使用其他色调时,您可以使用这款很棒的工具。


92ba58de0c94a801219c77d2592b.jpg




Designspiration.net


试想一下,你有自己的配色的想法,但你要看到几种颜色组合的例子。 Designspiration是一个伟大的工具。 您可以选择最多5种颜色,并搜索符合您的查询的图像。 真的很好,不仅用于找到具有特定调色板的图像,还可以在设计中实现它们。


52a358de09e9a801219c774d8bb5.jpg


ShutterstockLab Spectrum


你可能会问:如果我想用我所选择的颜色搜索照片? 那么,Shutterstock有一个叫做Spectrum的工具,你可以用特定的语气搜索照片。 您甚至不需要订阅,因为具有水印的小预览图像将足以生成调色板。


cc6c58de0a22a801219c77af34c9.jpg


Tineye Multicolr


但是,如果你想搜索照片中的颜色混合,甚至指定每个颜色的数量,那么Tineye会帮助你。 本网站使用了来自Flickr千万张共享图像的数据库。

64dd58de0aa0a801219c77382a00.jpg



最后的想法


掌握配色技巧是一件苦差事,特别是在数字时代。 上面提到的技巧将会减轻工作中寻找正确颜色方案的困难度。 学习创造令人惊叹的配色方案,最佳方法是练习,让自己有所帮助,用玩的心态去使用颜色。


以上是本篇文章全部内容,感谢您的阅读,希望对您设计产生帮助。



蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

调试移动端网页工具Weinre使用整理

seo达人

一、Weinre 说明



Weinre的本意是Web Inspector Remote,它是一种远程调试工具。功能与Firebug、Webkit inspector类似,可以帮助我们即时更改页面元素、样式,调试JS等。



使用Weinre工具,Weinre的本意是Web Inspector Remote,它是一种远程调试工具:



1.它可以将远程的页面经过代理在PC上调试页面元素、样式,JS。



2.可以监听页面内部的Ajax请求等。



3.可以监听页面加载成功时候的Console控制台输出



官网首页:http://people.apache.org/~pmuellr/weinre/docs/latest/



Weinre的原理







三个端的含义:客户端(client):本地的WebInspector,远程调试客户端。服务端(agent):本地的HTTPServer,为目标页面与客户端建立通信。目标页面(target):被调试的页面,页面已嵌入weinre的远程js。



调试过程:



客户端将指令(请求DOM、执行js)post到代理服务端,目标页面定时(大概5s)从服务端get指令,然后将结果post回服务端,最终客户端定时从服务端get结果。



PS:由于Weinre的客户端是基于Web Inspector开发,而Web Inspector只兼容WebKit核心的浏览器,所以只能在Chrome/Safari浏览器打开Weinre客户端进行调试。





二、Weinre安装和使用



1.weinre是基于NodeJs,因此首先要安装NodeJs,然后使用npm命令安装weinre



npm -g install weinre

2.运行,启动weinre服务器,默认端口8080



node.exe node_modules\weinre\weinre --boundHost -all-

node.exe node_modules\weinre\weinre --boundHost  192.168.1.125 

在windows下,系统防火墙可能会弹出是否允许其访问网络的提示,点击充许即可。

3.从浏览器访问,http://localhost:8080,或者,http://192.168.1.125:8080,显示如下表示启动服务器监视成功











三、Weinre需要监听调试的Web页面配置处理



1.在所有页面引入js文件



2.特别说明,当前js文件的域名需要指定为本机的IP地址,因为在手机模拟器中无法访问电脑‘localhost’



















更多:



cordova-plugin-whitelist 协议白名单配置整理 



VS Code插件安装位置



Visual Studio Code插件之Atom One Dark Syntax Theme



相关参考文章:



http://blog.csdn.net/freshlover/article/details/42640253



http://www.cnblogs.com/diva/p/3995674.html

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

豆瓣API实践项目-前言-0

seo达人

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

这是一个 app从获取获取数据 用于显示的经典实践项目,数据来源于 豆瓣官方公开的api接口:https://developers.douban.com/wiki/?title=movie_v2



先上图:

      

   





项目使用了如下第三方library:

下拉刷新:Android-PullToRefresh

网络数据加载:android-async-http

图片加载:universal-image-loader



后面的博客,会把项目的制作流程发出来

豆瓣API实践项目-前言-0(可下载源码): http://blog.csdn.net/mario_faker/article/details/79618210

豆瓣API实践项目-数据api接口-1:http://blog.csdn.net/mario_faker/article/details/79618235

豆瓣API实践项目-搭建项目基本框架-2:http://blog.csdn.net/mario_faker/article/details/79618245

豆瓣API实践项目-导入第三方library-3:http://blog.csdn.net/mario_faker/article/details/79618261

豆瓣API实践项目-单页细讲4: http://blog.csdn.net/mario_faker/article/details/79618272

豆瓣API实践项目-apk打包:http://blog.csdn.net/mario_faker/article/details/79618291





项目源代码下载地址:

http://download.csdn.net/download/mario_faker/10253201

或github:https://github.com/MarioFaker/DBMovie

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

做人就象是一家客栈

蓝蓝

作者:鲁米

做人就象是一家客栈

每个早晨,都是一位新来的客人

喜悦、沮丧、卑鄙

一瞬的觉悟来临

就像一个意外的访客

欢迎和招待每一位客人!

即使他们是一群悲伤之徒

来扫荡你的客房

将家具一扫而光

但你要款待每一位宾客

他或许会为你打扫

并带来新的喜悦

如果是阴暗的思想、 羞耻和怨恨

你也要在门口笑脸相迎

邀请他们进来

无论谁来,都要感激

因为每一位都是

由世外派来

指引你的向导

Android5.0以后,materialDesign风格的加阴影和裁剪效果

seo达人

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

5.0以后,materialDesign风格,出现了立体这种概念,高光,阴影,也就是Z轴,凸显层次;同时,裁剪view也变得方便简单了很多。
1,先说说阴影的实现。
方案1:在xml中设置 
xml中设置有两个方式,android:elevation="2dp" 
android:translationZ="2dp"这两句代码是可以同时并存的,而且是叠加的效果;当然只使用其中一个属性进行z轴的阴影设置也是OK的。

方案2:在代码中设置 
(下面说这个实现方式,其实就是轮廓的实现)

设置阴影,有一个需要注意的地方:
①:view的大小要比它的父布局小,才会有阴影效果,如果相同大小,是看不到阴影效果的; 
②:给图片设置阴影的时候,如果这种图片的background属性是shape,那直接通过xml设置阴影是OK的,但是,如果是一张png或者其他格式的图片,直接通过xml设置android:elevation="2dp" 
android:translationZ="2dp"阴影是看不到效果的,得通过其他代码设置才行。。。**

2,view的轮廓,轮廓其实也是阴影
默认情况下,所有的view都是矩形的,虽然可以给view设置背景圆形的图片,即可以在界面显示出圆形的内容,但是view的大小实际上依然是矩形,并且设置的图片实际上也是矩形的,只是圆形以外的区域是透明色。 
如果根据view大小来生成对应的阴影,就会出现很奇怪的效果,(一个看起来圆形的view展示出的确实一个矩形的阴影)我了解决这个问题,view增加了一个新的描述来指明内容显示的形状,这就是 轮廓

轮廓的实现
①通过shape设置的背景,view会自动根据shape的形状进行轮廓判定,
②通过color设置的背景,view默认其轮廓和view的大小一样。
③但是通过图片进行背景设置,view则无法获知轮廓的形状,这个时候就需要手动进行指定了。
1
2
3
一:在xml中可以通过android:outlineProvider来指定轮廓的判定方式: 
1,none即使设置了Z属性,也不会显示阴影 
2,background会按照背景来设置阴影形状 
3,bounds会按照view的大小来描绘阴影

**对于①和②这种情况,也是可以通过设置`android:outlineProvider`
来改变阴影的形状以及轮廓外观的。**

对于③这种背景是一张png或者其他格式的图片的情况,
`android:outlineProvider=“background”`
是没有效果的,属性设置成`android:outlineProvider=bounds`
虽然也是有效果的,但是阴影轮廓是一个方形的轮廓,
并不是我们想要的效果了。

不设置`android:outlineProvider`属性就更没有效果了。
1
2
3
4
5
6
7
8
9
10
对于这种使用了png图片作为背景的view加阴影轮廓的时候情况解决办法也非常简单,解决办法就是:
就通过Java代码设置,也就是说,一个圆形的png图(我们知道,看起来是圆形的,
但是它其实还是方形的图片,只是圆形之外的区域是透明不可见的),
 通过Java代码设置轮廓,就会显示出圆形的阴影轮廓了。
1
2
3
具体实现,继续看: 
二:在代码中,课通过setOutlineProvider来指定一个view的轮廓。 
对于③这种情况在代码中设置轮廓才会有效果。

TextView textView= findViewById(R.id.tv);
ViewOutlineProvider viewOutlineProvider=new ViewOutlineProvider() {
            @Override
            public void getOutline(View view, Outline outline) {
         //x,y轴表示位置,后两个参数表示长,宽 
               outline.setOval(0,0,textView.getWidth(),textView.getHeight());
            }
        };
textView.setOutlineProvider(viewOutlineProvider);
1
2
3
4
5
6
7
8
9
强调:
如果采用圆形图片作为背景,即使在xml布局中指定android:outlineProvider=“background”,也不会显示阴影,设置为android:outlineProvider=bounds,虽然也有效果,但是效果很差,所以一般都是通过代码来指定轮廓显示。

1,一个shape圆形作为背景,设置阴影,设置android:outlineProvider的4种属性的效果:


2,一个圆形png作为背景,设置阴影,设置android:outlineProvider的4种属性的效果:


3,一个png作为背景,设置阴影,通过代码设置的效果:


3,view的裁剪
裁剪,默认的ImageView是矩形的,很多时候,需要的是圆角的ImageView或者圆形的ImageView,这就需要裁剪view了。

实现,裁剪圆形:

final TextView textView= findViewById(R.id.tv);

ViewOutlineProvider viewOutlineProvider=new ViewOutlineProvider() {
            @Override
            public void getOutline(View view, Outline outline) {
                //设置圆形oval
                outline.setOval(0,0,textView.getWidth(),textView.getHeight());
            }
        };
//设置裁剪
textView.setClipToOutline(true);
1
2
3
4
5
6
7
8
9
10
11
实现,裁剪圆角矩形:

final TextView textView= findViewById(R.id.tv);

ViewOutlineProvider viewOutlineProvider=new ViewOutlineProvider() {
            @Override
            public void getOutline(View view, Outline outline) {
                //设置圆角矩形
               outline.setRoundRect(0,0,view.getWidth(),view.getHeight(),25);
            }
        };
textView.setOutlineProvider(viewOutlineProvider);
//设置裁剪
蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

TabLayout 全面总结

seo达人

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

一、简介

TabLayout提供了一个水平布局用于展示tabs,继承自HorizontalScrollView。一般与Viewpager结合使用实现页面和标签联动的效果,是时下APP中非常常用的一个控件



二、基本用法

  1. 添加design依赖

    compile 'com.android.support:design:25.3.1'

    1
  2. xml引用
  3. xml中添加tab

    <android.support.design.widget.TabLayout

        android:id="@+id/tab_layout"

        android:layout_width="match_parent"

        android:layout_height="wrap_content">

        <android.support.design.widget.TabItem

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:text="Tab1"/>

        <android.support.design.widget.TabItem

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:text="Tab2"/>

        <android.support.design.widget.TabItem

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:text="Tab3"/>

        <android.support.design.widget.TabItem

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:text="Tab4"/>

    </android.support.design.widget.TabLayout>

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21
  4. 代码中添加tab

    <android.support.design.widget.TabLayout

        android:id="@+id/tab_layout"

        android:layout_width="match_parent"

        android:layout_height="wrap_content">

    </android.support.design.widget.TabLayout>

    1

    2

    3

    4

    5

    // tablayout,Tab是TabLayout的内部类,且Tab的构造方法是包访问权限

    TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);

    tabLayout.addTab(tabLayout.newTab().setText("Tab1"));

    tabLayout.addTab(tabLayout.newTab().setText("Tab2"));

    tabLayout.addTab(tabLayout.newTab().setText("Tab3"));

    tabLayout.addTab(tabLayout.newTab().setText("Tab4"));

    1

    2

    3

    4

    5

    6





    三、属性详解

    <declare-styleable name="TabLayout">

        <!--指示器颜色-->

        <attr name="tabIndicatorColor" format="color"/>

        <!--指示器高度-->

        <attr name="tabIndicatorHeight" format="dimension"/>

        <!--tabs距TabLayout开始位置的偏移量,但app:tabMode="scrollable"才生效-->

        <attr name="tabContentStart" format="dimension"/>

        <!--仅是Tab背景,设置TabLayout背景用android:background-->

        <attr name="tabBackground" format="reference"/>

        <!--默认fixed,所有Tab只能在屏幕内显示,超出会被挤压;scrollable,tab数量多会超出屏幕,可滑动-->

        <attr name="tabMode">

            <enum name="scrollable" value="0"/>

            <enum name="fixed" value="1"/>

        </attr>

        <!--默认fill,tab填满TabLayout,但tabMode=“fixed”才生效;center,tabs位于TabLayout的中间-->

        <attr name="tabGravity">

            <enum name="fill" value="0"/>

            <enum name="center" value="1"/>

        </attr>

        <!--Tab的最小宽度-->

        <attr name="tabMinWidth" format="dimension"/>

        <!--Tab的最大宽度-->

        <attr name="tabMaxWidth" format="dimension"/>

        <!--Tab文本设置样式-->

        <attr name="tabTextAppearance" format="reference"/>

        <!--Tab未选中字体颜色-->

        <attr name="tabTextColor" format="color"/>

        <!--Tab选中字体颜色-->

        <attr name="tabSelectedTextColor" format="color"/>

        <!--Tab内填充相关-->

        <attr name="tabPaddingStart" format="dimension"/>

        <attr name="tabPaddingTop" format="dimension"/>

        <attr name="tabPaddingEnd" format="dimension"/>

        <attr name="tabPaddingBottom" format="dimension"/>

        <attr name="tabPadding" format="dimension"/>

    </declare-styleable>

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    使用示例



     <android.support.design.widget.TabLayout

        android:id="@+id/tab_layout"

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        app:tabIndicatorColor="@color/colorPrimaryDark"

        app:tabIndicatorHeight="2dp"

        app:tabContentStart="50dp"

        app:tabBackground="@color/colorAccent"

        app:tabMode="scrollable"

        app:tabGravity="fill"

        app:tabTextAppearance="@style/MyTabTextAppearance"

        app:tabTextColor="@android:color/black"

        app:tabSelectedTextColor="@android:color/white"/>

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    <style name="MyTabTextAppearance" parent="TextAppearance.Design.Tab">

        <item name="textAllCaps">false</item>

        <item name="android:textSize">18sp</item>

    </style>

    1

    2

    3

    4





    四、图文混排,Tab中添加图片
  5. 通过SpannableString设置图片

    @NonNull

    private SpannableString setImageSpan(String string,int drawableId) {

        SpannableString ss = new SpannableString("  "+string);

        Drawable drawable = ContextCompat.getDrawable(this, drawableId);

        drawable.setBounds(0,0,drawable.getIntrinsicWidth(),drawable.getIntrinsicHeight());

        ImageSpan imageSpan = new ImageSpan(drawable);

        ss.setSpan(imageSpan,0,1, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);

        return ss;

    }

    1

    2

    3

    4

    5

    6

    7

    8

    9

    TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);

    tabLayout.addTab(tabLayout.newTab().setText(setImageSpan("Tab1",R.drawable.ic_home)));

    tabLayout.addTab(tabLayout.newTab().setText(setImageSpan("Tab2",R.drawable.ic_info)));

    ……

    1

    2

    3

    4





    我们会发现个问题,通过ImageSpan设置的图片和文字没有对齐,先百度到一个可用方法解决:重写ImageSpan的draw()方法



    package com.strivestay.tablayoutdemo;



    import android.graphics.Bitmap;

    import android.graphics.Canvas;

    import android.graphics.Paint;

    import android.graphics.drawable.Drawable;

    import android.support.annotation.NonNull;

    import android.text.style.ImageSpan;



    public class CenterImageSpan extends ImageSpan {

        public CenterImageSpan(Drawable drawable) {

            super(drawable);



        }



        public CenterImageSpan(Bitmap b) {

            super(b);

        }



        @Override

        public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom,

                         @NonNull Paint paint) {



            Drawable b = getDrawable();

            Paint.FontMetricsInt fm = paint.getFontMetricsInt();

            int transY = (y + fm.descent + y + fm.ascent) / 2 - b.getBounds().bottom / 2;//计算y方向的位移

            canvas.save();

            canvas.translate(x, transY);//绘制图片位移一段距离

            b.draw(canvas);

            canvas.restore();

        }

    }

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    将上面的ImageSpan替换为现在的CenterImageSpan,即可实现图文混排时对齐






  6. 通过Tab.setCustomView()设置图片
  7. 自定义view布局

    <?xml version="1.0" encoding="utf-8"?>

    <LinearLayout

        xmlns:android="http://schemas.android.com/apk/res/android"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:orientation="vertical"

        android:gravity="center">

        <ImageView

            android:id="@+id/iv"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:src="@drawable/ic_home"/>

        <TextView

            android:id="@+id/tv"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:layout_margin="2dp"

            android:textSize="16sp"

            android:text="首页"/>

    </LinearLayout>

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20
  8. 代码设置

     TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);

    tabLayout.addTab(tabLayout.newTab().setCustomView(setCustomView(R.drawable.ic_home,"首页")));

    tabLayout.addTab(tabLayout.newTab().setCustomView(setCustomView(R.drawable.ic_info,"资讯")));

    tabLayout.addTab(tabLayout.newTab().setCustomView(setCustomView(R.drawable.ic_live,"直播")));

    tabLayout.addTab(tabLayout.newTab().setCustomView(setCustomView(R.drawable.ic_me,"我")));

    1

    2

    3

    4

    5

     private View setCustomView(int drawableId,String tabText) {

        View view = View.inflate(this, R.layout.item_tab, null);

        ImageView iv = (ImageView) view.findViewById(R.id.iv);

        TextView tv = (TextView) view.findViewById(R.id.tv);

        iv.setImageResource(drawableId);

        tv.setText(tabText);

        return view;

    }

    1

    2

    3

    4

    5

    6

    7

    8





    五、TabLayout与Viewpager联动
  9. xml设置TabLayout和Viewpager

    第一种:TabLayout放置在Viewpager的上方,放在AppbarLayout中会有阴影效果



    <?xml version="1.0" encoding="utf-8"?>

    <android.support.design.widget.CoordinatorLayout

        xmlns:android="http://schemas.android.com/apk/res/android"

        xmlns:app="http://schemas.android.com/apk/res-auto"

        xmlns:tools="http://schemas.android.com/tools"

        android:id="@+id/main_content"

        android:layout_width="match_parent"

        android:layout_height="match_parent"

        android:fitsSystemWindows="true"

        tools:context="com.strivestay.tablayoutdemo.MainActivity">



        <android.support.design.widget.AppBarLayout

            android:id="@+id/appbar"

            android:layout_width="match_parent"

            android:layout_height="wrap_content"

            android:paddingTop="@dimen/appbar_padding_top"

            android:theme="@style/AppTheme.AppBarOverlay">



            <android.support.v7.widget.Toolbar

                android:id="@+id/toolbar"

                android:layout_width="match_parent"

                android:layout_height="?attr/actionBarSize"

                android:background="?attr/colorPrimary"

                app:layout_scrollFlags="scroll|enterAlways"

                app:popupTheme="@style/AppTheme.PopupOverlay">



            </android.support.v7.widget.Toolbar>



            <android.support.design.widget.TabLayout

                android:id="@+id/tab_layout"

                android:layout_width="match_parent"

                android:layout_height="wrap_content"

                app:tabIndicatorColor="@color/colorAccent"

                app:tabIndicatorHeight="2dp"

                app:tabBackground="@android:color/white"

                app:tabTextAppearance="@style/MyTabTextAppearance"

                app:tabTextColor="@android:color/black"

                app:tabSelectedTextColor="@android:color/holo_blue_light">

            </android.support.design.widget.TabLayout>



        </android.support.design.widget.AppBarLayout>



        <android.support.v4.view.ViewPager

            android:id="@+id/container"

            android:layout_width="match_parent"

            android:layout_height="match_parent"

            app:layout_behavior="@string/appbar_scrolling_view_behavior"/>



        <android.support.design.widget.FloatingActionButton

            android:id="@+id/fab"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:layout_gravity="end|bottom"

            android:layout_margin="@dimen/fab_margin"

            app:srcCompat="@android:drawable/ic_dialog_email"/>



    </android.support.design.widget.CoordinatorLayout>

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    38

    39

    40

    41

    42

    43

    44

    45

    46

    47

    48

    49

    50

    51

    52

    53

    54

    55

    56

    57

    58





    第二种:TabLayout直接放在Viewpager,无阴影



    <android.support.v4.view.ViewPager

        android:id="@+id/container"

        android:layout_width="match_parent"

        android:layout_height="match_parent"

        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <android.support.design.widget.TabLayout

            android:id="@+id/tab_layout"

            android:layout_width="match_parent"

            android:layout_height="wrap_content"

            app:tabIndicatorColor="@color/colorAccent"

            app:tabIndicatorHeight="2dp"

            app:tabBackground="@android:color/white"

            app:tabTextAppearance="@style/MyTabTextAppearance"

            app:tabTextColor="@android:color/black"

            app:tabSelectedTextColor="@android:color/holo_blue_light">

        </android.support.design.widget.TabLayout>

    </android.support.v4.view.ViewPager>

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17




  10. 为Viewpager创建适配器

    /

      fragment

     
    /

    public static class PlaceholderFragment extends Fragment {

        private static final String ARG_SECTION = "section";



        public PlaceholderFragment() {

        }



        public static PlaceholderFragment newInstance(String section) {

            PlaceholderFragment fragment = new PlaceholderFragment();

            Bundle args = new Bundle();

            args.putString(ARG_SECTION, section);

            fragment.setArguments(args);

            return fragment;

        }



        @Override

        public View onCreateView(LayoutInflater inflater, ViewGroup container,

                                 Bundle savedInstanceState) {

            View rootView = inflater.inflate(R.layout.fragment_main, container, false);

            TextView textView = (TextView) rootView.findViewById(R.id.section_label);

            textView.setText(getArguments().getString(ARG_SECTION));

            return rootView;

        }

    }



    /


      pagerAdapter

     
    /

    public class SectionsPagerAdapter extends FragmentPagerAdapter {

        String[] tabs = {"首页","资讯","直播","我"};



        public SectionsPagerAdapter(FragmentManager fm) {

            super(fm);

        }



        @Override

        public Fragment getItem(int position) {

            return PlaceholderFragment.newInstance(tabs[position]);

        }



        @Override

        public int getCount() {

            return tabs.length;

        }



        @Override

        public CharSequence getPageTitle(int position) {

            return tabs[position];

        }

    }

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    38

    39

    40

    41

    42

    43

    44

    45

    46

    47

    48

    49

    50

    51

    52

    主要是重写getPageTitle()方法


  11. 代码设置 TabLayout和Viewpager绑定

     // tablayout

    TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);



    // vp

    mViewPager = (ViewPager) findViewById(R.id.container);

    mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());

    mViewPager.setAdapter(mSectionsPagerAdapter);



    // 绑定,要在viewpager设置完数据后,调用此方法,否则不显示 tabs文本

    tabLayout.setupWithViewPager(mViewPager);

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    调用setupWithViewPager()方法,则使用TabLayout.addtab()方法无效,TabLayout会清除之前添加的所有tabs,并将根据Viewpager的页数添加Tab,Tab标题为对应页通过getPageTitle()返回的文本






  12. 图文混排
  13. 同上,使用SpannableString

    修改Adapter如下:



    /*

     
    pagerAdapter

     */

    public class SectionsPagerAdapter extends FragmentPagerAdapter {



        String[] tabs = {"首页","资讯","直播","我"};

        int[] imgs = {R.drawable.ic_home,R.drawable.ic_info,R.drawable.ic_live,R.drawable.ic_me};



        public SectionsPagerAdapter(FragmentManager fm) {

            super(fm);

        }



        @Override

        public Fragment getItem(int position) {

            return PlaceholderFragment.newInstance(tabs[position]);

        }



        @Override

        public int getCount() {

            return tabs.length;

        }



        @Override

        public CharSequence getPageTitle(int position) {

    //            return tabs[position];

            return setImageSpan(tabs[position],imgs[position]);

        }

    }

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    setImageSpan()方法同上






  14. 同上,使用Tab.setCustomView()

    修改pagerAdapter如下:



    /

      pagerAdapter

     
    /

    public class SectionsPagerAdapter extends FragmentPagerAdapter {



        String[] tabs = {"首页","资讯","直播","我"};

        int[] imgs = {R.drawable.ic_home,R.drawable.ic_info,R.drawable.ic_live,R.drawable.ic_me};



        public SectionsPagerAdapter(FragmentManager fm) {

            super(fm);

        }



        @Override

        public Fragment getItem(int position) {

            return PlaceholderFragment.newInstance(tabs[position]);

        }



        @Override

        public int getCount() {

            return tabs.length;

        }



        @Override

        public CharSequence getPageTitle(int position) {

    //            return tabs[position];

    //            return setImageSpan(tabs[position],imgs[position]);

            return null;

        }



        /


          设置自定义view

         
    @param position

          @return

         
    /

        public View setCustomView(int position) {

            View view = View.inflate(getApplicationContext(), R.layout.item_tab, null);

            ImageView iv = (ImageView) view.findViewById(R.id.iv);

            TextView tv = (TextView) view.findViewById(R.id.tv);

            iv.setImageResource(imgs[position]);

            tv.setText(tabs[position]);

            return view;

        }

    }

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    38

    39

    40

    41

    42

    43

    代码修改如下:



    …………

    // 绑定,要在viewpager设置完数据后,调用此方法,否则不显示 tabs文本

    tabLayout.setupWithViewPager(mViewPager);



    // 为绑定viewpager后的TabLayout的tabs设置自定义view

    for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {

        tabLayout.getTabAt(i).setCustomView(mSectionsPagerAdapter.setCustomView(i));

    }

    1

    2

    3

    4

    5

    6

    7

    8

    发现问题:我使用的仍然是上面的item_tab,但是只显示图片,不显示文字如下







    翻了翻源码,也没发现有对Tab的标题有特别的设置;后来,就感觉是不是颜色问题,给item_tab中的textview加上属性android:textColor="@android:color/black",就显示出来了







    六、FlycoTabLayout

    这是一个不错的TabLayout开源项目,效果挺好,可以了解一下。





    蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

一口吃下 iPhone设计规范

雪涛

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

如果您不熟悉iPhone设计规范,请一口吃下本篇文章。伴随笔记吃下效果更佳:)

Image title

 

iPhone的历史


每次苹果发布会UI设计师可能是最睡不着觉的人啦。每次发布会苹果推出全新iPhone时,我们在iPhone平台上的APP应用程序必须跟随iPhone的尺寸、规范等特性调整设计稿。也就是说,几乎每次苹果发布会都是UI设计师加班的通知书!这不,2018年9月13日凌晨,苹果在Apple Park总部里的乔布斯剧院举行了2018苹果秋季新品发布会。这次苹果发布了全新的iPhone Xs、iPhone Xs Max,iPhone Xr三款手机。噢,不要忘记我们也不能怠慢还在服役的iPhone X、iPhone Plus、iPhone6/7/8、iPhone SE等苹果手机。作为一个移动端UI设计师,您必须对苹果所有生产过和现役的iPhone有所了解。

 

起源

谈到iPhone我们必须谈谈史蒂夫·乔布斯(Steve Jobs)。尽管乔布斯去世多年,但是他的理念仍然是现代智能手机设计的原则。乔布斯不仅重新定义了智能手机,也定义了移动端应用程序。这位被领养的犹太男孩在很早就对个人电脑产生了兴趣。在游历了印度和日本之后,他进入了大学校园。在校园里除了无线电和嬉皮士文化,他认为大学课程多半是无聊的。但他曾跑去特意选修了一门课程:字体设计。他所在大学的字体设计课是全美最著名的,在那个课堂上乔布斯学习到了网格设计、衬线体与无衬线体、字体的气质等设计知识。当然在前面讲过的具有摇滚精神的字体Helvetica也深深吸引了乔布斯。后来乔布斯选择大学肄业并在自家车库创立了苹果公司,自此“车库”也成了创业者最喜爱的地标。苹果公司的第一代个人电脑内置了非常出色的用户图形界面系统(即GUI),并且内置了Helvetica等漂亮的字体。但是这并不是乔布斯事业的终点,在经历了苹果公司的权利斗争后,成熟的乔布斯再次登上发布会的舞台,推出了真正能改变世界的产品 - iPhone。一般产品名都会用名字加上产品的类型命名,比如百事可乐、英雄钢笔等。而iPhone似乎本身就是一个类别。在那次发布会上,乔布斯指责当时的功能手机太“愚蠢”:当时的功能手机性能很差,并且屏幕很小,实体键盘占用了很大的空间。之后,他拿出了一部像外星科技的产品:iPhone。自此,苹果重新发明了手机。乔布斯如此强调用户界面和交互设计的重要性,这种理念改变了当时和现在的设计思维。乔布斯身后,移动端的格局在改变,接任乔布斯指挥棒的蒂姆·库克和首席设计官乔纳森·伊夫(Sir Jonathan Paul Ive)也陆续更新着苹果手机的产品线,延续着这些伟大的产品。

 

 Image title

年轻的乔布斯

 

初代iPhone

相关产品:iPhone(一代)、iPhone3G(二代)、iPhone3GS(三代)。

iPhone初代产品在2007年1月9日由史蒂夫·乔布斯在苹果发布会上正式发布。初代的iPhone产品的共同特点是:玻璃屏、屏幕清晰度普通、3.5英寸屏(注意:我们所说的手机尺寸都是测量屏幕的对角线得出的)。iPhone没有实体键而整体是屏幕的设计,在当时仿佛是外星科技降临一般令人惊艳。为了让大众习惯直接在手机上点图标(在此之前人机互动都是间接输入的:比如实体键盘、鼠标、触控笔等),乔布斯发布了革命性的操作系统iOS,手机的所有图标都是圆角:这样可以避免用户认为会刺到手指。所有图标和界面全部是拟物设计,这样可以更好地让用户理解哪些是可以点击操作的。按钮在手机上呈现的大小都是7mm左右,这是因为人类手指点击区域大概是7mm - 9mm。系统充分地应用了多点触控的功能,你不仅仅可以点手机里的按钮,还可以进行长按、滑动、捏等手势操作。这些用户体验和人性化的设计在当时具有划时代的意义。随后,第二代产品iPhone 3G、第三代产品iPhone3GS先后由乔布斯发布。这种能听歌、能打电话、能上网的手机真是太炸了!而且你可以在应用商店Appstore中下载第三方的应用程序,海量的第三方程序可谓是大千世界了。这块3.5英寸屏的手机截图出来后的实际分辨率是480x320px,所以如果你在当时做UI设计的话,那么做APP界面建图的尺寸就应该是480x320px。

 

Image title

 苹果初代产品 (2007)

 

iPhone 4

相关产品:iPhone 4(四代)、iPhone 4s(五代)。

iPhone 4于2010年6月8日发布。iPhone 4延续了iPhone一代的多点触摸(Multi-touch)屏界面,并首次加入视网膜屏幕、前置摄像头、陀螺仪、后置闪光灯,相机像素提高至500万。对我们设计师最重要的就是加上了视网膜屏Retina。Retina是苹果提出的标准,它的含义就是在应用场景的视距内让人无法看清单个像素。我们都知道如果你贴的够近,一般的屏幕上都会出现一格一格的像素矩阵。屏幕是由这些矩阵组成的。这种屏幕的问题就是稍微近一些我们就能看到那些网格和矩阵。如果我们希望用户得到最好的体验,自然是让用户看不到格子,那怎么办?答案就是:加大屏幕的密度。如果屏幕的密度到达一个指定的水平(当然也要取决于用户的视距,即用户与屏幕通常离多远),那么用户的眼睛就无法分辨出细小的像素颗粒了。这种屏幕就被称为Retina屏,也叫视网膜屏。这是用户体验的巨大进步,但是也是UI设计师的噩梦。原先的设计稿统统需要放大才可以在iPhone4里显示得完美:比如原来我们一个界面的尺寸是480x320px,现在因为屏幕密度增加了一倍,我们就需要设计640x960px才够用。在电脑上看这个尺寸要比手机大两倍!(当然啦,那时的电脑屏幕通常不是Retina屏)。而且3GS并没有完全被淘汰,那么如何让一个APP适配两个不同尺寸的手机呢?于是每个APP内预装了两套切图,一套480x320px尺寸,也就是一倍图(@1x);一套960x640px尺寸,也就是二倍图(@2x)。这两套图像资源的命名完全一样,只是二倍图结尾需要加上@2x标记它是高清尺寸,比如home_icon@2x.png。

Image title

 

 iPhone 4代产品 (2010)

 

逻辑像素和物理像素

逻辑像素(logic point):逻辑像素的单位是PT,它是按照内容的尺寸计算的单位。比如iPhone 4的逻辑像素是480x320pt。但是由于每个逻辑的点因为视网膜屏密度增加了一倍,即1pt=2px,那么其实iPhone 4的物理像素是960x640px。iOS开发工程师和使用Sketch和AdobeXD软件设计界面的设计师使用的单位都是PT。

 

物理像素的单位就是我们常说的pixel,简写成PX。它是我们在Photoshop和切图中使用的单位,屏幕设计中最小的单位就是1px不可再分割。使用Photoshop设计移动端界面和网站的设计师使用的单位是PX。在以下的文章中,如果您使用Photoshop设计界面,那么只需要记住所有px单位的数值和支持Photoshop的工具,如果使用Sketch或Adobe XD设计界面,那么只需要记住所有pt单位的数值和对应的工具即可。

 

 Image title

逻辑像素和实际像素计算方式不同

 

PPI

PPI(pixels per inch)指的是屏幕分辨率的单位,表示的是每英寸显示的像素密度。屏幕的PPI值越高,那么这个屏幕每英寸能容纳的像素颗粒也就越多,那这个产品的画面的细节度也就越丰富。PPI值大于300一般我们就无法用肉眼察觉出屏幕上的“马赛克”格子了。但是如果屏幕很大,那么需要呈现视网膜屏的PPI值也需要更大,所以iPhone Plus系列的PPI值比iPhone6/7/8要大。PPI在我们设计的工作中其实关系不大,但理解它对于帮助我们理解为什么iPhone4比iPhone3GS实际像素大一倍有帮助。

 Image title

PPI的计算公式

 

iPhone 5

相关产品:iPhone 5(六代)、iPhone 5s和iPhone 5c(七代)

iPhone 5于2012年9月13日正式发布。iPhone5在设计上带来了很多争议,因为iPhone5没有采用乔布斯认为人类最合适的手机尺寸3.5英寸屏,而是用了4英寸的屏幕。宽度没变而高度加长了。这样做的原因是市场上越大的手机越受欢迎。当时设计师也几近崩溃,因为又要搞适配了。原来960x640px的尺寸变为了1136x640px,但是这个变化其实不大,就是高了点儿。于是@2x高清图的设计稿就变成了640x1136px。因为iPhone4的手机看着也就是长了点儿,滑动不就完了嘛。除了闪屏这样的界面需要单独做iPhone4、iPhone5、3GS尺寸之外,其他界面仍然维持两套设计稿即可。

 

Image title

iPhone 5 (2012)

 

iPhone 6/7/8 和iPhone Plus

相关产品:iPhone6和iPhone6 Plus(八代)、iPhone 6s和iPhone 6s Plus(九代)、iPhone7和iPhone7 Plus(十代)、iPhone8和iPhone8 Plus(十一代)。

这个产品迭代周期值得大家留意,从iPhone6到iPhone8这段时间苹果新手机的物理像素都是750x1334px。而所有Plus手机的物理像素都是1242x2208px。如果按照逻辑像素来计算,那么iPhone6/7/8的逻辑像素就是375 x 667 pt(就是750x1334除以2);而iPhone Plus的逻辑像素就是414 x 736 pt(就是1242x2208除以3,因为这个屏幕太大了视距不同所以屏幕密度更高)。历史到这个时候,原来的手机全部被淘汰了。也就是说iPhone6/7/8成为了我们的设计标准,它的切图就是@2x,iPhone Plus(1242x2208)使用@3x。从此没有@1x倍图了,只存在一个假想的概念。

 Image title

iPhone 6/7/8  (自2014)

 

Image title

 

iPhone Plus (自2014)

 

 

iPhone X

相关产品:iPhone X(十一代)。

这四款手机全部是苹果的全面屏手机。全面屏并不是新概念了,因为从iPhone初代产品开始,手机业内就在构思如何把手机做成全部都是屏幕区域的技术了。但是这个技术有很多难题,比如前置摄像头和听筒怎么处理。那么苹果采用的方案是“齐刘海”,把四周处理成圆角的方式。IPhone X和后续三款全面屏我们设计师需要注意的就是齐刘海。因为需要规避摄像头和麦克风听筒,所以导航栏比其他iPhone系列产品要高;而底部Tab栏因为最下方有圆角同样比其他iPhone系列要高。而且这两个边界是不应该放置任何操作功能的。也就是说只有看的份儿。

iPhone X的物理像素是1125 x 2436 px,而逻辑像素是375 x 812 pt。也就是说如果你使用Sketch或者Adobe XD等工具设计界面的话,iPhone X的宽度和iPhone 6/7/8是相同的;只是高了一些。那么如果需要出一套iPhone X效果图只需要把头和尾巴替换成新版即可。而如果你用Photoshop设计界面的话,宽度变化还是比较大的。需要做放大处理然后单独调整那些乱了的尺寸。

 Image title

iPhone X(2017)

 

iPhone XS Max

相关产品:iPhone XS、iPhone XS Max、iPhone XR(十二代)。

这三款产品的像素分辨率听上去会比较眼晕:

iPhone XS Max:1242 x 2688 px

iPhone XS:1125 x 2436 px

iPhone XR:828 x 1792 px

但是如果我们用点的单位看就会得到:

iPhone XS Max:414 x 896 pt (iPhone Plus分辨率宽度)

iPhone XS:375x812 pt (iPhone 6/7/8分辨率宽度)

iPhone XR:414 x 896 pt (iPhone Plus分辨率宽度)

 

所以其实今年发布的iPhone都是比较友好的,如果使用矢量界面工具那么只需要调整设计稿头和尾巴即可,如果使用Photoshop的设计师需要放大缩小设计稿然后调整头和尾巴可以得到新版设计稿。而切图其实和之前没有变化,不管用什么工具设计还是得出两套切图:@2x(750x1334px)、@3x(1242x2208px)即可。

 Image title

iPhone XS Max (2018)

 

 

以iPhone6/7/8为基准设计

在开始比赛之前,由于iPhone 6、iPhone 6S、iPhone7、iPhone7S、iPhone8屏幕和分辨率都是一致的750X1334px,所以我们可以称它们为iPhone6/7/8。而iPhone 6 Plus、iPhone7 Plus、iPhone8 Plus、屏幕和分辨率都是一致的1242x2208,所以我们可以称它们为iPhone Plus。而iPhone XS、iPhone X屏幕和分辨率都是一致的1125x2436,所以我们可以称它们为iPhoneX。那这场比赛的赢家毫无疑问是价格美丽的iPhone6/7/8获胜啦。那么我们做界面设计时需要按照iPhone6/7/8为基准设计。如果使用Photoshop就建750x1334px尺寸的画布,如果是使用Sketch或Adobe XD等工具就建立375x667pt。当然如果要设计首页之类的界面,它的界面很长你可以设计一个长的设计稿,比如750x8000px。

 Image title

手机型号与像素对应图

 

Image title

 

HIG设计指南


上文说我们建立界面可以根据750x1334px或375x667pt来建立画布,但是具体状态栏的高度、导航栏的高度、tab栏的高度是多少?那些UIKit组件里的东西去哪里找呢?苹果已经为我们准备好了多个格式的规范了:

资源下载地址:https://developer.apple.com/design/resources/

 

设计方式

在iPhone6/7/8存量仍然很大的情况下,我们做设计稿仍然需要以iPhone6/7/8为尺寸来建图。从苹果官网下载好UIKit,上面有我们需要的一切元素。这些元素有PSD、Sketch以及XD版本,不管用什么设计软件均可找到对应版本。打开之后你会发现苹果已经将我们所需要的规范元素准备好了。如果你需要一些弹窗或者控件,那么就在UI Elements里找。如果需要界面的尺寸模板,就在Design Templates找。所有文件都有两份,结尾带有-iPhoneX的是为iPhone X系列设计的模板。没有标识的是为iPhone6/7/8设计的模板。

 Image title

UI Elements 文件夹中的源文件

 

Image title Design Templates中的源文件

 

状态栏和导航栏

状态栏(Status Bars)就是iPhone最上方用来显示时间、运营商信息、电池电量的那个很窄的区域。导航栏(Navigation Bars)就是状态栏之下的区域,一般来说导航栏中间是页面标题,左右是放置功能图标的区域。

在iPhone6/7/8设计中,状态栏的高度为20pt(40px)。导航栏的高度是44pt(88px)。这两个区域在iOS7代之后就进行了一体化设计。所以它们加起来的高度是64pt(128px)。

在iPhoneX设计中,状态栏的高度为40pt(132px)。导航栏的高度也是44pt(132px)。这两个区域同样要进行一体化设计。所以它们加起来的高度是84pt(264px)。这里注意一下,因为iPhone X的PPI值为458,所以并不是如iPhone6/7/8一样1pt=2px换算。

 

 Image title

iPhone6/7/8和iPhone X导航区域的差别

 

Image title

 部分优秀APP的导航区域设计

 

大标题导航栏

在的苹果设计中导航出现了一种新形式:大标题。出现这种形式就是为了减少视觉噪音,让内容更加突出。很明显大标题的设计很像报纸的版式设计,在第一眼我们就会明白页面的主题。大标题导航栏的高度一般为116pt(232px):这包括了20pt(40px)状态栏的高度,同时也能放得下34pt(68px)的大标题和辅助信息(如返回等图标)。但是注意一下,大标题并不应该像传统导航一样常驻在页面之上,因为它太占空间了。所以在滑动页面时大标题会变成正常导航栏的64pt(128px)的高度。当然如果设计稿为iPhone X那么数值需要另外换算。

 

 Image title

大标题的尺寸

导航栏图标

图标作为文字的补充,在移动端中应用非常广泛。在导航栏区域上的功能诸如搜索、添加、更多、返回等均需要用图标来表达。说明:@2x和@3x在逻辑像素单位是一样的,如果您使用如Sketch、Adobe XD等矢量工具设计,可以参照逻辑像素数值设计即可。但是如果您用Photoshop工具以iPhone6/7/8尺寸进行设计,就需按照@2x下的px单位数值设计。

 Image title

导航栏图标尺寸规范

 

标签栏 (Tab Bars)

Tab就是点击的意思,Tab栏(也叫标签栏)指的是APP底部的区域,如微信底部常驻有聊天、通讯录、发现、我的四个图标。iOS规范中Tab栏一般有五个、四个、三个图标的形式。也就是把宽度平分为五、四、三份。iPhone6/7/8设计中,标签栏的高度为49pt(98px)。Tab栏的操作是最常用的,因为手指最方便点击而且这个栏是常驻在页面之上的。所以Tab栏的图标至关重要,因为很多用户可能因为看不懂图标而找不到重要功能的入口,通常我们会在Tab栏图标之下加上11pt(22px)的注释文字,这个注释文字一般来说都是非常浅的浅灰色。

 

Image title

标签栏的尺寸

标签栏图标

我们在标签栏上的图标一般来说30pt(60px)大小左右,苹果给出了四种不同形状标签栏图标的尺寸参考供大家设计时考虑。其意义是让不同外形的图标看上去是差不多大的,保证图标的平衡。标签栏图标的选中态应该是一个彩色,来区别于非选中状态。

 Image title

真实设计中的标签栏

 

Image title

 

标签栏图标设计规范

Image title

 

标签栏图标应该尽量使用清晰地填充风格

 

 

工具栏 (ToolBars)

我们在苹果自带浏览器底部就能看到工具栏。工具栏提供了和当前任务相关的操作和按钮,在滑动时可以收起。工具栏同Tab栏一样都是位于底部,但是高度略窄,它的高度是44pt(88px)。

 

闪屏资源

由于闪屏是一张完整的静态满屏图片,而不是诸如其他页面一样是由切图和文本拼成的,所以闪屏的适配更简单粗暴:我们需要提供不同尺寸的闪屏效果。闪屏资源就是满尺寸的一张png,上端不需要状态栏里的信息,程序会在开发完毕时自动在闪屏中补上状态栏里的信息。我们需要提供的闪屏尺寸有:

 Image title

我们需要提供的闪屏尺寸 一共6张

 

安全距离

作为iPhone全面屏系列手机,齐刘海无疑是一个特征。但是全面屏给我们带来了使用上的问题:上下左右是圆角、顶部齐刘海使屏幕凹下一块。所以在带有圆角和齐刘海的红色标注区域不应该放置任何功能,仅可在上端放置状态栏,底部圆角区域留白。我们界面竖屏使用时左右临近手机边缘的区域不建议放任何操作,应留出一定的边距(Margin)。这个边距是多少呢?没有明确严格的规定,但是一般的APP会留出16pt-24pt不等的边距防止用户在屏幕边缘不好点击。不过内容展现却可以呈现在边距里。如果我们横屏使用手机时,左右同样不好点对吧?横屏同时还有令人闹心的“齐刘海”,所以同样左右需留出一定的边距来。所以我们就得到一个安全距离的矩形,内容可以完整地呈现在这个安全距离内。

 

 Image title

iPhone X系列由于全面屏上下出现不可操作区域

 

色彩

其实在iPhone上显示的色域要比我们作图时的RGB色域要广。所以在iPhone上设计怎样的颜色都可以。只要符合产品气质并且在色彩心理学理论上思考,用什么颜色是设计师的自由。官方建议的系统色彩如下:

 Image title

iPhone的系统色

 

字体

iOS中英文使用的是San Francisco (SF)字体。(下载地址:https://developer.apple.com/fonts

),中文使用的是苹方黑体。安装好以后你会发现中文苹方的字族有不少可供选择的粗细,那么我们设计界面时需要根据信息的逻辑权重分配粗细:标题应该较粗,而说明字体应该较细并且可以设计成灰色。其实字体的设计最重要的考量就是信息层级。苹果认为APP的字体信息层级有:大标题(Large Title)、标题一(Title 1)、标题二(Title 2)、标题三(Title 3)、头条(Headline)、正文(Body)、标注(Callout)、副标题(Subhead)、注解(Footnote)、注释一(Caption 1)、注释二(Caption 2)这几种。

 Image title

HIG对APP的字体建议(基于@2x)

 

注意一下,以上HIG的建议全部是针对英文SF字体而言的,中文字体需要我们灵活运用,以最终呈现效果为基准调整。在设计具体界面时我们一定要以用户的使用情景来考虑,把设计稿导入手机去思考行高与字体大小是否是可读的。10pt(20px)是手机上显示的最小字体,最大的应该是目前的大标题字体了,达到了34pt(68px)。

 

启动图标

在设计模板还没有如今这么发达时,设计师需要设计启动图标(1024x1024px)之后按照程序员的要求切出几十个不同尺寸的图标。比如,在手机中@3x情况下桌面图标尺寸为180x180px,在@2x情况下为120x120px;在应用商店图标需要使用的尺寸是1024x1024px;这个工作太烦人了,好在现在我们只需要专注在启动图标设计本身上了。在苹果给我们的这套资源中,有Template-AppIcons-iOS这个文件。打开这个文件,用我们自己设计的启动图标替换掉智能对象里的内容,你会发现所有尺寸的图标都变成了我们的图标。然后我们把背景隐藏,切出这些图标即可。图标设计建议使用AI等矢量软件,然后使用规范切出图像资源。

 

 Image title

Template-AppIcons-iOS

 

控件

控件包括:输入框、按钮、滑杆、页卡、开关等,在设计模板中已经全部列出。这里格外说明一下,为了让设计更符合整体产品品牌调性,这些控件都可以做成自定义的设计样式。但是会增加工作量和切图资源,所以一般我们在诸如设置界面这些无需太体现设计感的页面中都使用系统默认控件,而在一些品牌感需要强调的页面或产品(诸如白噪音产品、游戏等)则会使用自定义的样式。如果我们想自己设计控件,那么注意两件事:第一,点击区域基本符合44pt(88px)原则,也就是在手机上大小大概是7mm-9mm,适合手指点击。第二,要设计操作的不同状态,不要只设计一种状态。

 Image title

默认控件

 

Image title

 

自定控件和默认控件

 

控件中无处不在的44pt(88px)

之前我们介绍过,人手指点击区域为7mm - 9mm,在@2x中就是44pt(88px)。苹果的导航条、列表、工具栏都充满了44pt(88px)这个神秘数字。我们在设计时一定也要考虑到手指的点击区域。

 Image title

无处不见的44pt(88px)

 

键盘

在设计模板中您也可以找到键盘的设计。这里需要提醒的是,很多朋友做界面设计时不考虑输入时键盘会遮挡到的空间,如果考虑到键盘弹起遮挡住的内容,那么我们的一些界面中的输入框和信息可能都需要上移了。当然也不是说可能被键盘遮挡的地方不可以防止任何内容,也有一种方式就是当输入一个表单时,页面会垂直定位到当前输入的位置。

 Image title

键盘高度

 

iTunes 上传截图

在程序上传APPSTORE时我们需要提供多张APP截图,供用户了解APP的功能。很多设计师朋友不太清楚这个尺寸,这里我们需要提供1242 x 2688px和1125 x 2436px两套截图。有时我们也会在这个尺寸上做一些设计,让用户在APPSTORE打开APP介绍时获得最好的体验。

 Image title

ITunes上传用截图

 Image title


工作流程


前期调研阶段

在我们设计界面之前,我们必须做用户研究来了解产品的调性,比如用户研究手段中的用户画像、用户调研、用户使用场景分析、设计竞品分析等方法。不管工作再忙也建议大家做这些工作,他们对我们深入了解产品大有裨益。

 

原型图阶段

APP产品设计首先需要构建出原型图,之后再开始视觉设计。这个工作有些公司是由产品经理负责的,也有交互设计师负责的,还有的公司因为人手较少,也会出现由UI设计师来负责的情况。就算有产品经理或其他职能人员来完成原型图,那设计师也需要和产品经理等人员沟通需求和探讨原型图,并不是产品经理向设计师下发需求。设计师要站在视觉和交互的角度提出自己建设性的意见,而不是简单等原型图完成后照着上色而已。关于原型图的工具,我们不仅仅可以用Axure RP设计原型图,也可以使用像墨刀、Adobe XD等新工具来完成原型图。

 

 Image title

构建APP原型图(工具:Adobe XD )

 

视觉稿阶段

视觉稿阶段要根据原型图确定的内容和大体版式完成APP的界面设计。但是这里请大家注意一下:目前业界主要是以Sketch、Adobe XD、Photoshop这三个软件来完成APP的界面设计的。Sketch和Adobe XD都是以逻辑像素的单位(PT)来设计,然后导出图像的时候再进行放大两倍三倍来切图。这样做的好处是不用在设计的时候小心翼翼地使用偶数了。而Photoshop由于主要是处理图像而非矢量图形的软件,所以在设计移动端界面时如果做成一倍的话切图会变得很虚,所以要基于2倍图来进行界面设计。比如如果我们以iPhone6/7/8的界面来进行设计,那么在Sketch和Adobe XD中我们建立的画布就是375x667pt在Photoshop中则是750x1334px。

 

Image title 

视觉稿设计阶段(工具:Adobe XD)

 

Image title

 

视觉稿设计阶段(工具:Adobe Photoshop)

 

 

iPhone6/7/8尺寸

在iPhone6/7/8尺寸下,状态栏高度20pt(40px)、导航栏44pt(88px)、Tab栏49pt(98px)、导航标题字号建议17pt(34px)、导航栏图标建议22pt(44px)、Tab栏图标建议30pt(60px)、Tab栏图标注释文字11pt(22px)、左右安全距离建议12pt(24px)。字号从10pt(20px)到34pt(68px)均可,要视具体情况决定。

 

 Image title

在iPhone6/7/8尺寸下的设计尺寸

 

实时预览你的设计稿

我们在Sketch、Adobe XD、Photoshop等软件中设计界面时有一个问题:电脑上的效果总和手机上呈现的效果不同。这是由于尺寸和观察方式决定的,所以最好的方式是我们实时地查看设计稿在手机上的呈现效果。以下APP通过数据线或wifi链接电脑后,即可及时在手机中看到还没有保存的设计稿呈现在手机中的样子。

 

 Image title

Design Mirror:可实时预览Photoshop、XD等设计稿

 

Image title

 

Adobe XD:可实时预览你的XD画板

 

Image title

 Sketch Mirror:可实时预览你的Sketch画板

 

iPhoneX设计效果图

虽然程序员对于iPhoneX等全面屏手机的适配只需要设计师提供切图即可,但很多设计师比较青睐iPhone X和XR和XSM等的设计效果,也比较愿意把设计稿改成iPhoneX的设计图放到作品集或者在汇报时展示。那么我们应该怎么做呢?如果设计稿需要调整为iPhone X的显示效果,可以下载iOS 12设计源文件,把界面头和尾替换成iPhoneX专用头尾——专用头尾在刘海和圆角处做了留白。Sketch和XD都是用一倍图设计所以不涉及修改尺寸,改头尾即可。而PS比较复杂一点:需要先等比例变大整个设计稿,再把宽度改为1125宽度自适应即可。PS变大会虚还得一个一个调一下,然后再改头尾。

 

Image title

替换导航区域和Tab栏区域,即可得到iPhoneX设计效果

 

视觉规范

如果我们设计完了五六个主要界面,那么现在做什么呢?APP设计一套视觉规范是非常有必要的,有了视觉规范我们就可以把控整体的设计和语言。一般来说,一套APP应该有3-5种主题色和辅助色;5-10种不同变化的字体样式。这些如果没有落实到一套规范中,那么很容易跑偏。一套移动端应用的视觉规范应该包括:

 

主色/辅色/色彩规范: 规定APP所能使用的色彩种类;

文字颜色/大小规范: 规定APP主要使用文字的大小、颜色、应用场景等;

ICON规范: 规定APP的icon设计规范;

应用图标规范: 规定APP的应用图标使用规范;

按钮和交互态规范: 规定APP内所有按钮和交互态的样式;

间距规范: 规定APP内所有间距的尺寸。

 

 

Image title

设计规范的重要性

 

 

Image title

设计规范中的色彩规范

 

设计规范的类型可以是png或者多个页面组成的pdf文件。其他设计师打开我们制定的设计规范,可以清晰地找到当前项目适合使用的元素和字体大小、间距等。这样尽管是多人协同工作也可以保证项目设计风格的一致性。

 

切图

有了大小各异的iPhone尺寸,如果程序只有一套切图,那么一定会造成有的手机显示很差。所以我们要在程序里放置多套切图,然后让程序判断“主人”的手机是什么型号,显示不同的切图。这样才能够完美地呈现给用户最好的体验。切图的方法有很多种。Sketch和Adobe XD可以直接导出。Phtoshop不具备这个功能,但是我们可以使用cutterman、蓝湖等插件导出切图。不管是自带功能还是插件,导出切图都可以导出@2x和@3x图,而设计稿只需要iPhone6/7/8一套即可。

 

 

Image title

某项目中的切图文件

 

Adobe XD切图功能

在Adobe XD中将需要切出的元素在图层面板(Ctrl + Y)点击添加批量导出标记记录;然后点击 菜单 > 导出 > 所选画板 > 用于iOS > 导出所有画板 即可。

 

Image title

Adobe XD自带切图功能

 

使用Cutterman协助Photoshop切图

在Cutterman官网下载PS插件后,点击窗口 > 扩展功能 > Cutterman 调出面板;然后选择iOS 并高亮选中@3X和@2X;在图层面板里选中需要切图的元素,点击“导出选中图层”即可。

 

 

Image title

Photoshop中的Cutterman 插件

 

使用蓝湖切图

在蓝湖平台可以下载Sketch、Adobe XD或Photoshop对应的插件。然后在不同设计软件插件中将设计稿上传到蓝湖(PS需要用插件标记需要切出的元素),然后在蓝湖网页版点击切图按钮,选择视网膜@2x和高清视网膜@3x,再点击“下载该页全部切图”即可。

 

 

Image title

在蓝湖平台导出切图

 

切图命名规范

切图最后需要命名成规范的格式,这样方便程序员查找。切图命名的格式建议全英文,如果大家英文不好需要想办法提升一点简单的词汇量。借由上述工具切图后,需要整理切图命名,或在切图之前对图层命名亦可。以下是切图元素的中英文对照:

 Image title

切图命名对照表

 

然后我们要按照 功能_类型_名称_状态@倍数 来命名每个切图,比如我们导航条上有一个搜索图标,那么它的名称就是:

 

navi_icon_search_default@2x.png

(导航_图标_搜索_正常@2x.png)

 

iOS开发语言

作为iOS开发工程师,最重要的三个工具是:Obiective-C、Swift、UIKit框架。Obiective-C是目前最有效率的语言;而Swift开发非常。一般iOS工程师会在这两个语言中选择一种作为开发工具。UIKit是苹果系统自带的一套框架,这个框架里有设置按钮、滑竿、状态栏、电池电量、键盘等接口可供调用。所以我们看到很多第三方APP的界面中,有许多控件和苹果自带程序是一致的,这就是UIKit的功劳。

 

 

Image title

开发视角 By @alvaroreyes

 

了解开发工程师的语言和工具对我们做设计也格外有帮助,我们会知道哪些效果能做,哪些效果不能做,哪些效果能做不好做等等。我找了大家关注的九个问题请教了iOS资深开发工程师程威:

 

 

Image title

Image title

和iOS工程师沟通

 

沟通完是不是学到了不少?我们明白了iOS工程师工作的机制后再设计界面时就可以做到心中有数了。在平时工作中我们也应该多和开发小哥哥聊聊,学习一下他们实现的方式,以便我们的设计能够更好地落地。

 

标注

切图后程序员得到了什么?一大堆碎片。把这些碎片重新用OC或者Swift构建回我们设计的界面并没有想的那么简单。所以开发工程师可能会总是在思考构架层面的问题,而忽视了视觉还原。并且由于iOS的开发人员不会使用设计软件,所以很容易出现比如14pt或者28px的文字,实现后是16pt或者32px。那就乱了套了不是,那怎么办呢?我们可以通过一些标注软件把图标之间的位置、字体的高度、字体的大小和色彩进行标注,让程序员轻松省力地还原我们的设计稿。

 

蓝湖平台自动标注功能

将Sketch和Adobe XD、Photoshop的设计稿上传至蓝湖后,在蓝湖平台每个页面左侧有一个类似分享的图标,点击会获取一个网址,这个网址就是系统生成的自动标注。它会自动识别设计稿中字体大小和间距等,甚至有代码参考。

 

Image title

蓝湖自动标注工具

 

使用Px像素大厨标注

像素大厨同样提供了自动标注、手动标注两种标注方法。自动标注需要上传设计稿,手动标注需要设计师使用“尺子”来测量距离、“吸管”来吸取色号。在界面上部有单位选择,如果我们给iOS开发做标注,那么单位最好选择PT,与开发环境一致。

 

Image title

像素大厨标注工具

 

“标你妹啊”进行自动标注

国产标注在线神器。只需要登录网站后,上传设计稿可直接生成标注网址,发给程序员就可以啦。同样提供代码参考和自动标注间距尺寸等功能。

 

 

Image title

在线标注工具 - 标你妹啊

 

Markman 手动标注

Markman同样是国产标注神器。而且是我使用的第一个标注工具,选用底部工具可以进行手动标注,标注后导出png标注图即可。

 

 

Image title

Markman标注工具

 

动效

据资深iOS开发程威介绍,目前的iOS主流的动效实现方式有以下四种:第一种,设计师给到开发动效视频或gif,开发人员照着效果编写代码调用静态切图重新做一遍,这样的还原度可能会有问题,需要开发和设计师多沟通。第二种,可以使用序列帧的方式实现动画,原理是给到开发按顺序命名的png,比如1.png、2.png等,然后用代码将它们快速替换实现动画。第三种,我们也可以给到程序员avi等视频文件直接插入视频。第四种,使用Airbnb开源的Lottie(https://airbnb.design/lottie/)。具体来说是通过after effects来完成动效,然后通过BodyMovin插件导出json文件,里面记录的就是动画的细节,然后在安卓,iOS,React Native上都有一套对应的SDK,来解析这个json文件来还原成动画。这个方式的还原度很高,除了部分AE不支持外堪称完美。其实还有QuartzCode、CoreAnimator等工具,有兴趣的大家可以去尝试一下。但我认为不管使用什么方式,最优秀的动效还是要靠设计师和开发人员“真诚地交流”。


项目走查

当我们最终完成了界面设计,需要和我们的设计稿进行对照还原。除了用肉眼辨别之外,我们也可以把还原后的程序截图下来放到PS中对照,寻找问题。那么我们给程序员的反馈就是一个有截图对照和标注的文档,这个文档可以成为Buglist。

 

Image title

截图后可在软件中对比寻找问题

 

项目走查除了判断视觉还原程度,也要兼顾动效、点击状态等动态效果是否符合设计预期。如果有问题需要及时和技术反馈,反馈的方式建议是文档类型,保证有据可查。

 

 Image title


总结


我们一起来小结一下:当我们设计iOS平台的APP时,我们可以选择使用Sketch、Adobe XD、Photoshop等工具。为了切图和适配方便,设计时我们以iPhone6/7/8尺寸(750x1334px或375x667pt)为基准设计。设计过程中我们需要通过诸如Adobe XD或Mirror等工具随时在手机上预览设计效果。之后我们需要把图像资源输出成@2x视网膜屏幕和@3x高清视网膜屏幕两套图像资源,这时可以使用Cutterman或Sketch和XD自带的切图功能切图。为了保证开发工程师能够完美地还原我们的设计稿,我们需要提供标注。通过蓝湖或像素大厨、Markman、标你妹啊等工具我们可以把设计稿完美标注给到程序员,这时程序员就清晰地明白每个元素的大小和间距了。最后,我们要对完成的程序进行验收。本篇文章写于二零一八年,按照惯例,每年苹果都会举办两场发布会发布新产品。如果后面发布了新的手机,也希望大家能够理清脉络,透过现象看到本质,找出合适的设计适配方法。



参考资料

苹果开发者中心网址:

https://developer.apple.com/

苹果人机交互规范:

https://developer.apple.com/design/human-interface-guidelines/

iOS设计资源下载:

https://developer.apple.com/design/resources/

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计  cs界面设计  ipad界面设计  包装设计  图标定制  用户体验 、交互设计、 网站建设 平面设计服务

jQuery中的Ajax操作

seo达人

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

jQuery对Ajax操作进行了封装,常用的方法包括 $.get(),$.post(),$.ajax()。 
分别对其进行介绍

$.get()
$.get()方法使用GET方式来进行异步请求。
$.get()结构
$.get(url,[. data][. callback][. type])
1
$.get()方法参数解释
参数名称 类型 说明
url String 请求的HTML页的url地址
data(可选) Object 发送至服务器的key/value数据会作为QueryString附加到请求的url中
callback(可选) Function 载入成功时回调函数(只有当Response的返回状态是success才调用该方法)自动将请求结果和状态传递给该方法
type(可选) String 服务器端返回内容的格式,包括xml、html、script、json、text和_default
示例 
json数据:data.json(后面的$.post()和$.ajax()方法都用这个数据)
{
    "name":"龙猫",
    "hobby":"睡觉",
    "friend":"加菲猫"
}

jq_get.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>

</head>
<body>
    <input type="button" value="$.get方法" id="jQget">
    <div id="content"></div>
</body>
</html>
<!-- 导入jquery.js文件 -->
<script type="text/javascript" src="js/jquery.min.js"></script>
<script type="text/javascript">
    $(function(){
        $('#jQget').on('click',function(){

            /*

            参数1:url
                参数2:发送的数据 支持 直接写js对象的方式
                参数3:回调函数
                参数4:从服务端获取的 数据类型 可以不写
                注意
                    如果type 为json 
                        并且服务端返回的就是 json格式字符串
                        jq内部 会帮助我们自动转化
                        在回调函数中 获取的 实参 就是转化完成的 js对象 直接使用即可

                参数的 顺序 是更换的
                    但是 如果 把data 放到后面 会出现 无法传递数据的问题,
                    所以 不要擅自更换 严格按照 jq文档中的 顺序 进行使用
            */
            $.get('jq_get.php',{name:"jack",age:18},function(data){
                    console.log(data);

                    $('#content').html('name:'+data.name+'<br>'+'hobby:'+data.hobby+'<br>'+'friend:'+data.friend); 

            },'json');
        });

    });
</script>

jq_get.php (后面的$.post()和$.ajax()方法都用这个页面的内容,只是在html请求时分别对应的php页面)

<?php
    header('content-type:text/html;charset=utf-8');
    echo file_get_contents('datas/data.json');
?>

结果展示: 


$.post()方法
  它与$.get()方法的结构和使用方式都相同,不过它们之间仍然有以下区别:

GET请求会将参数跟在URL后进行传递,而POST请求则是作为HTTP消息的实体内容发送个Web服务器,当然,在Ajax中,这种区别对用户是不可见的。
GET方式对传输的数据有大小限制(通常不能大于2KB),而使用POST方式传递的数据量要比GET方式大得多(理论上不受限制,但是可以在服务端进行限制)。
GET方式请求的数据会被浏览器缓存起来,因此其他人就可以从浏览器的历史记录中读取这些数据,例如账号和密码等。在某种情况下,GET方式会带来严重的安全性问题,而POST方式相对来说就可以避免这些问题。(但是也是不安全的,所以密码之类的还是要加密的)
GET方式和POST方式传递的数据在服务器的获取方式也不相同。在PHP中,GET方式数据可以用$_GET[]获取,而POST可以用$_POST[]获取、两种方式都可以用$_REQUEST[]来获取。 
其实这完全是对这篇文章中post()和get()方法不同的总结啊!(点击查看) 
$.post()演示
<script type="text/javascript" src="js/jquery.min.js"></script>
<script type="text/javascript">
    $(function(){
        $('#jQpost').on('click',function(){
            // 跟$.get用法及其类似
            /*
                参数1:url
                参数2:发送的数据 支持 直接写js对象的方式
                参数3:回调函数
                参数4:从服务端获取的 数据类型 可以不写,如果写为json jq内部 会帮我们进行一个 JSON.parse()的转化 
            */
             $.post('jq_post.php',{name:"kong",age:18},function(data){
                    console.log(data);
             },'json');
        });
    });
</script>

$.ajax()
$.ajax()方法是jQuery最底层的Ajax实现
其结构为
$.ajax(options)
1
该方法只有1个参数,但在这个对象里包含了$.ajax()方法所需要的请求设置以及回调函数等信息,参数以key/value的形式存在,所有参数都是可选的,只写几个常用的参数,如下:

参数名称 类型 说明
url String 请求的HTML页的url地址
type String 请求方式,默认GET。注意其他的HTTP请求方法,例如PUT和DELETE也可以使用,但仅部分浏览器支持
data Object或String 发送到服务器的数据,如果已经不是字符串,将自动转换为字符串格式。
dataType String 服务器端返回内容的格式,包括xml、html、script、json、jsonp 、jQuery
beforeSend Function 发送请求前可以修改XMLHttpRequest对象的函数,例如添加自定义HTTP头。在beforeSend中如果返回false可以取消本次Ajax请求。XMLHttpRequest对象的唯一参数。
success Function 请求成功后嗲用的回调函数,有两个参数。
(1)由服务器返回,并根据dataType参数进行处理后的数据。
(2)描述状态的字符串。
function(data,textStatus){
        //data可能是xmlDoc、jsonObj、html、text等等。
        this//调用本次Ajax请求时传递的options参数
  }
error Function 请求失败时被调用的函数,该函数有3个参数,即
XMLHttpRequest对象、错误信息、捕获的错误对象(可选)。
Ajax事件函数如下。
function(XMLHttpRequest,textStatus,errorThrown){//通常情况下textStatus和errorThown只有其中一个包含信息
this;//调用本次Ajax请求时传递的options参数
}
示例
<script type="text/javascript" src="js/jquery.min.js"></script>
<script type="text/javascript">
    $(function(){
        $('#jqAjax').on('click',function(){
    /*
                常见参数:
                    url:请求的地址
                    success:请求成功的回调函数
                    type:不写是get 可以指定 get,post
                    dataType:数据的类型
                    data:发数据 可以写js对象
                    beforeSend:发送之前调用的匿名函数
                        可以return false 阻止该次请求
                        验证用户的数据 是否填了
                    error:请求失败以后 会调用
            */
            $.ajax({
                url:'jq_ajax.php',
                success:function(data){
                    console.log(data);
                    $('#box').append(data.name+'<br>'+data.hobby);
                },
                type:'post',
                dataType:'json',
                data:{"name":"张信哲","skill":"情歌王子"},
                beforeSend:function(){
                    console.log('发送之前调用');
                },
                error:function(){
                    console.log('请求失败了');
                }
            });
        });

    });
</script>
--------------------- 
作者:diligentkong 
来源:CSDN 
原文:https://blog.csdn.net/diligentkong/article/details/72851443 
版权声明:本文为博主原创文章,转载请附上博文链接!
蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

日历

链接

blogger

蓝蓝 http://www.lanlanwork.com

存档