使用安卓支持库,Material design 无处不在
FranciscaHt
8年前
<p>Material Design 的引入是近年来安卓开发世界里非常令人激动的事情。那些标准描述了一个美丽的 UI,但是对于开发者来说是非常具有挑战性的,特别是它们必须具备向后兼容性。现在使用 ‘Android Design Support Library’ (之前叫做 ‘AppCompat Library’) 来支持 "Material" 将是件不难的事情。开发者们现在可以使用这个工具来很容易地构建 Material 兼容的应用,这些应用可能在所有的设备上工作,并且看起来很棒 (甚至运行在 Eclair 或者 Froyo 上)。在这篇演讲中,Mike Wolfson 重点提到了这些库中间的一些重要的组件,还演示了高效使用它们的方法。这仅仅是 Material design 的开始 - 来学学这些重要的工具吧,这会使事情变得容易而且是变革的一部分!</p> <p>我是 Mike Wolfson (看 <a href="/misc/goto?guid=4959674164612066062" rel="nofollow,noindex">我的书</a> )。我是一名谷歌安卓开发专家,我知道些 Play store 是如何挑选特征应用的内部原则 ( <em>他们非常严格</em> )。如果你的应用不是符合 Material Design 标准的话,它是不会被 Play store 推荐的。至少你的应用需要是 Material Design 兼容的,然后他们会挑选出能让你的应用看起来出彩的地方,但是如果你不是用的 Material Design,他们都不会关注你的应用。</p> <p>延迟开发是最好的开发。Material Design 中所有的一切都要做好是很难的。但是采用 Material Design 支持库却可以让我们偷一点懒,可以多花点时间上上网。最后,可能是你需要采用 Material Design 的最关键的原因是什么?你的应用需要在安卓上看起来不违和。</p> <p>Material Design 标准的创建是为了提供一个给所有手机统一的设计语言。你的应用需要符合它:你的应用需要看起来像或者应该看起来像安卓的原生风格。</p> <p>Material Design 是一套设计语言的标准。它定义了布局、字体、颜色、运动交互模式的标准。它是一个标准,它是只定义元素应该看起来是什么样子的设计语言。它不包括你应该如何实现它的任何信息。在谷歌, <a href="/misc/goto?guid=4959674164742103113" rel="nofollow,noindex">他们创建了一个顶层的范围</a> ,这里你能找到 Material Design 标准,也包括比你希望了解到的更多的设计语言。</p> <p>如果你去那个网站,你会看到这些信息:颜色、风格、指标、交互模式、导航的工作方式、不同的元素相互如何作用;以及你打算使用的各种元素的定义,比如:功能按钮,导航视图,和其他 Material Design 的主要控制组件。</p> <p>一个好的例子是颜色。如果你去看 Material Design 标准,它们创建了许多的不同颜色的调色板。主要颜色 (靛青或者粉色) 是定义好了的,然后有一个调色板允许你定制不同的色调。我写了 <a href="/misc/goto?guid=4958968614795310401" rel="nofollow,noindex">这个项目</a> 来支持这个应用。在这个项目里,我抽象了每一个颜色然后创建了一个调色板能够直接引用这些颜色 (比如:靛青_600)。</p> <p>我们知道他们定义了这些颜色,但是我们不知道这些颜色用来做什么。如果你去看 Material Design 标准,它定义了这个 Material Design 颜色调色板是怎么给一个应用定制的。它有一个 primary ,一个 primaryDark 和一个 accent 颜色。 如果你想使用这些调色板,你需要用你的风格来定义这些调色板。然后系统在这个基础上自动为你的应用着色。我们现在有统一的颜色来标识我们的应用了,它也在某种程度上也标识着系统的颜色。以前,我们需要给每一个视图独立着色,每一个视图都有风格。现在它通过系统统一风格了。</p> <p>如果我想有一个主要的蓝色调色板,这就是我如何着色的方法。我使用蓝色 500,蓝色 700,和一个 accent 的黄色。它就自动地为我着色了。如果我想为我的整个应用改变调色板的话,我可以在我的风格里面改变这些颜色的标准。我们现在给我们的应用统一地打上标识了。( <em>就是这些繁琐的东西让我们没法偷懒</em> )。</p> <h3>活版印刷 - Material 定义的风格</h3> <p>取代手工为应用的每个不同的用例定义字体标准的方法,我们现在可以使用统一的字体风格了 (在整个应用中统一)。如果应用 A 使用了 title ,假设我们知道那会是一个中型的 20sp 字体。为了引用这些新字体风格里面的一个,你需要给你的文字加上一个风格属性。</p> <p>支持库:安卓有多个操作系统版本可以开发而且已经公开发布。但是,因为一些原因 (比如:生产商或者运营商拒绝),想得到这些更新的手机是非常困难的。我们知道想在你的手机上运行最新的安卓是不容易的。这对于谷歌来说是个问题,因为他们不能推送它们最新的热点和新功能代码给这些老的手机。为了解决这个问题,它们创建了一个库 ( <em>因为他们是谷歌,所以不是第三方库</em> )这是一个隔离层:它允许我们在这些老的手机版本上使用这些新功能。如果我们可以在我们的包里发布 jar 的话,而且如果我们使用的功能本地不支持的话,我们就需要这个库来支持这些功能。总而言之,这是一个隔离层,运行谷歌在它很老的操作系统版本上向后兼容这些新功能。</p> <p>如果你想开始使用 AppCompat ,加上这两个依赖 (基础水平)。一旦你增加了这些依赖,你就在不同的产品和你需要的不同的功能上增加了其他的依赖。你增加了两个基础的库,如果你打算使用 CardView 或者 RecyclerView (类似的东西),你把那些依赖作为二级依赖。</p> <p>一旦你增加了这些依赖,你需要在你的 XML 里面增加命名空间。这使得在 XML 里面可以有不同的属性。</p> <p>你还需要扩展 AppCompatActivity 。这是新的:我们以前是扩展 Action Bar activity,它们把它改成了 AppCompatActivity 。你需要做这些改变:给你的风格增加风格颜色,增加依赖,扩展 AppCompatActivity 。然后所有的神奇的事情就会发生了。</p> <pre> <code class="language-java">public class MainActivity extends AppCompatActivity {</code></pre> <p>我想深入说说那个库里面的内容,和它的一些核心方法。AppCompat 提供了色彩敏感的控件:当我在我的统一风格的应用中定制那个颜色的时候,它们会自动地被风格化而且着好色。这就是说,给我的每个不同的控件统一风格。</p> <p>RecyclerView 和 我们常常用的 ListView 类似……除了 <strong>一点也不</strong> 。</p> <p>RecyclerView 是一个新的 ListView ,它有一个额外的内建功能来使得我们能给我们的列表增加数值,而且它会自动地在对这些数值插入,删除和重排的时候产生动画。</p> <p><a href="/misc/goto?guid=4959674164899749188" rel="nofollow,noindex">RecyclerView</a> 非常强大而且可以扩展,但是使用起来难点。例如,你可以改变你的列表的布局 (像从垂直方向改到水平方向),或者甚至多行,通过定制 LayoutManager 。你不能在 ListView 里做这些事情。现在我们用 RecyclerView 来实现 ListView 的多种风格,但是我们需要做些手动的事情来实现它,这就变得更复杂了,但是更强大。还有一个 ItemDecorators ,你可以用它来给你的列表中的每个元素增加装饰 (比如增加一个列表分割线)。</p> <p><a href="/misc/goto?guid=4959674165031791809" rel="nofollow,noindex">Palette</a> 是一个很酷的库,它让我们能够给 palette 发送任何的图像,然后 palette 会返回一个那个图像的颜色列表,我们可以在代码里面使用这些颜色。在我的应用里面,我有一个白色的标题,这个标题在大多数的不同图像上都不能显现出来,因为它们都是部分白色背景的图片。我把这个图片发给 Palette,然后给标题设为 vibrant - 现在我知道它和图像是反色的,然后可以显示出来了。而且,这在以前的姜饼平台上也能工作 (包括 RecyclerView ) ,2.3 OS,它们只占有少量的市场份额。谷歌能够提供所有的这些功能,而且还能够向后兼容使得我们的应用统一起来,这相当了不起。</p> <p>Material Design 的一个重要的部分就是演进。Material Design 的一个核心的组件是我们熟悉的 X-axis 和 Y-axism 系统。但是它们增加了一个 Z-axis 系统,然后你就可以采纳这些视图,并且在屏幕上提升它们。 CardView 是一个很棒的方式 – 你可以在你的 CardView 里面设置提升,这允许你可以在屏幕上提升这些卡片。</p> <p>我有一个例子运行在两个不同的手机上,一个不支持 (S4) 和一个支持 (MotoX)。你可以看到这些阴影和光影效果是非常棒的,而且能在每个地方都能正常工作。我不能说出这两者的差别,虽然有些差别。</p> <p>如果你在编写一个媒体应用,当有电话进来关掉你的媒体声音的时候,事情就得复杂了,或者如果另外一个媒体应用想得到控制权的时候也一样。 MediaRouter 将接管这部分困难的工作,通过把媒体路由到支持库里来实现,所以你不用担心你的应用会消声了,或者甚至抢占优先级。如果你是使用的媒体的应用,这是个有用的东西。</p> <p>向量图是在 XML 文件里面用语言定义图形元素的方法。他有些坐标,比如说从 0.0 到 0.10 画一条线,然后再画另一条线,等等。如果你使用像 PNG 的光栅图片,像安卓开发者一样,为了使图片资源到处看起来都很不错,我们需要提供不同的大小,HDPI, XHDPI。这很难,而且这会增大你的应用的大小。我们能定义这些向量资源了,在代码里面包括它们,改变它们的大小。如果你想在你的代码里面增加矢量图,你需要增加这行然后你可以通过引用来添加那些可绘制的对象,就像你通过 srcCompat 属性名来引用其他可绘制对象一样。一旦你这样做了,你可以定制多个大小而且图像会无损的调整大小。当他们也开始在支持库里面使用向量的时候,通过使用向量替换光栅图形,他们把应用减少了 9%。这样做,有机会能控制应用膨胀,也能防止 PNGs 的多个版本的麻烦,并且不会出错。尽管这只在版本 23.01 上有效。</p> <pre> <code class="language-java">android { compileSdkVersion 23 buildToolsVersion "23.0.1" defaultConfig { //... vectorDrawables.useSupportLibrary = true }</code></pre> <pre> <code class="language-java"><ImageView android:layout_width="36dp" android: layout_height="36dp" android:layout_gravity="center_horizontal" app:srcCompat="@drawable/bugdroid" tools:ignore="MissingPrefix"/></code></pre> <h3>设计</h3> <p>AppCompat 是核心。设计库就是那些能实现 Material Design <strong>流行</strong> 的漂亮 UI。</p> <p>navigationView</p> <p>navigationView 是用来导航的侧边栏。这也是一个能展示支持库是如何工作的好例子而且能节省我们的工作。如果你去看设计标准,你会发现导航 UI 的样子是有着非常详细的定义的。它们具体到图标应该如何被缩放,旁边的留白应该有多少,和你的关键行。靠你自己完全做到正确是非常困难的。</p> <p>在安卓里,有一个控制控件叫做 NavigationView ,它使得你能在 XML 里面像定义菜单一样实现这些要求。(就像你为一个 Action Bar 或者 menu 所做的事情一样)。你需要定义动作, @drawable 。然后,操作系统自己会为你产生一个 NavigationView 。例如,它在我选择一个条目的时候增加了一个灰色的高亮。它在我的系统颜色的基础上给图标和文字着色。当然,之后它按照它应该的那样把所有的组件准确布局。比如,我能够确定一个图标是准确地离边沿 16dp,因为我知道 <em>谷歌的设计者</em> 已经考虑到它了。我所需要做的事情就是定义一些简单的 XML,然后所有的神奇的事情就发生了。</p> <pre> <code class="language-xml"><menu xmlns:android="http://schemas.android.com/apk/res/android"› <group android:checkableBehavior="single"> <item android:id="@+id/nav_home" android:icon="@drawable/ic_android" android:title="OS Versions" /> <item android:id="@+id/nav_devices" android:icon="@drawable/ic_device" android:title="Devices" /> <item android:id="@+id/nav_favorites" android:icon="@drawable/ic_favorite_on" android:title="Favorites" /> <item android:id="@+id/nav_userinfo" android:icon="@drawable/ic_account" android:title="User Settings" /> </group></code></pre> <p>一个我常常听到的关于 NavigationView 的问题是,”我该如何给我的导航视图添加一个订制化的 X?” 答案是, <strong>“不要这样做”</strong> 一些设计限制的目的就是不要扩展而固定用法。你不被期望来修改导航视图。侧边导航是谷歌计划强推的设计模式,它需要在每一个应用里面都看起来一样。这是一个公共的导航模式;它们就是故意使得修改特别困难 - 当你想修改它的时候,仔细想想你这样做的原因。结果回答会是 “不!,你不应该修改,” ,如果你的设计师要求你这样做,给他发一份设计标准然后说 “Material Design 不支持这样做。我觉得这不是个坏主意,而且 Mike Wolfson 也这么认为。”</p> <p>他们创建的一些额外的控件:</p> <ul> <li>TextInputLayout 提供了当你点击进入一个 TextView 的时候的漂亮动画。这个视觉上的反馈很有用。你只需要增加这个 XML,一个标准的编辑文字。</li> <li>Featured Action Button (FAB),, 这个你打算放到屏幕上的圆圈将是一个神奇的组件,你的主要动作。这以前是很难实现的,但是它们现在给了我们一个 FAB 控制来实现这个强大的事情 ( <em>请看下面</em> )。</li> <li>Snackbar 一个在屏幕底端弹出状态信息的消息,也是一个选择内容的方式。</li> <li>Dialogues 和 SwitchCompat 。 SwitchCompat 一个好看的动画而且当你点击它的时候,着色十分特别,它动画变来变去。警示对话框都是标准的。使用这些标准的警示对话框,然后你知道你的模式是合适的。</li> </ul> <p><a href="/misc/goto?guid=4959646673617527157" rel="nofollow,noindex">Coordinator Layout</a> 使你增加你的主要视图的布局,而且它使得屏幕里面的视图可以互相交互。动画 FAB 是十分容易的。在我的协调布局中,我可以增加一个锚,然后告知 FAB,然后一个一个视图的告知,这样它们就能互相联系起来。协调布局使得一个视图能够监听另一个不同视图的滚动事件。一旦其他的视图滚动的时候,它说,”我也需要滚动” 或者 “我需要做些事情。” 能把这两个视图联系在一起是非常强大的,而且能够一起滚动或者在某个独特的模式下分别做些事情。</p> <p>这是个体现 Froyo API 层的标题是不同的颜色的好例子。当我滚动视图的时候,顶层的标题栏慢慢视差然后消失,而且标题也会有渐入渐出的动画。我们有视图渐进渐出的动画,视图平行地进入,我们也有标题,它会闪烁,扩大,充满活力,有价值。而且我们不需要做任何的事情;我们所要做的事情就是使用应用的 collapsing 工具栏布局控制。</p> <p>希望你开始看到,这里有些视觉的模式能够提供交互能力和强大的图片。</p> <p>百分比布局是网页开发者一直有的东西,现在我们也有了。你可以基于你的全部屏幕的一个百分比来定制布局。这以前在安卓里是不可能的,因此,实现一些复杂的用户接口是很困难的。现在我们有百分比布局,而且我们可以定制,”我想这个功能是 60% 和 20%。”</p> <p>我想展示一个我最近用的例子:</p> <pre> <code class="language-java"><android.support.percent.PercentFrameLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true"> <com.tmm.views.CustomVideoView tools:ignore="LayoutHeight" android:id="@+id/custom_video_view" app:layout_heightPercent="7096" app:layout_aspectRatio="17096" />. </android.support.percent.PercentFrameLayout></code></pre> <p>我的这个应用有一个视频控制,而且我们的视图是一个绝对的大小。它被设置为从屏幕全宽和每边留白 16dp。问题是安卓屏幕是不同大小的:我的 viewport 总是一个不同的大小,有时候我不能控制 video port 是如何配置的。现在我可以用些不一样的事情了。我创建了这个比率然后设置我的视图为 16:9。现在就不是根据具体的屏幕大小计算具体的数值,我可以就只定制一个百分比然后系统自己会计算它。现在我有这个 viewport 而且我知道它总是 16:9。我可以只定制我需要的高度的百分比。以前,为了得到这个信息,视图需要是静态的而且大小要准确,我需要为不同的设备创建多个分辨率,或者在代码里面手工实时计算百分比。知道了这个功能后,我轻松多了;我知道它能工作,而且到处都能工作的很好。我希望你了解到了支持库是最容易采纳 Material Design 的方法。</p> <p>我鼓励你们看看这个应用而且代码在这 <a href="/misc/goto?guid=4959674165197761458" rel="nofollow,noindex">开源代码</a> 。我从 Chris Bane’s Cheesesquare Material Design 的示例应用中拷贝了一份,然后扩展了一些,这样就有你看见的这些东西了,希望这个项目有着清晰和基本的例子,而且也很简单。</p> <p>问: 从你的演讲里我学到的一个很酷的东西就是百分比布局。你展示了一个使用百分比布局的例子而且我认为这是一个有文字视图的百分比框。还有可能使用一个更复杂的视图吗,比如我想要一个菜单或者一个严格的 RecyclerView 里面有 PercentRelativeLayout ?这可能吗,或者它对基础视图有限制?</p> <p>Mike: 不,我觉得你可以在任何容器里面使用它,因为它是一个相对布局。是一个特殊的相对布局类型。你能使用相对布局的任何地方,我认为你可以使用百分比相对布局。也有一个百分比框布局,显然相对布局更灵活。但是我不认为这里面有什么限制。CardView 的例子里面有一个文字视图和两个不同的百分比视图,而且它能工作。</p> <p>问:: 谢谢你的演讲。我有一个关于 PercentRelativeLayout 的问题。关于你的项目你说 178%,16:9 比率,我在想,你是怎么计算出那个数字的呢?我怎么能计算出来?16:9 相关的数字怎么计算得出?</p> <p>Mike:我认为 16 / 9 是比率 1.78:1,所有 16 是 9 的 178%。我从那个例子发现,是因为它是一个需要这样的固定大小的 viewport 的公共例子。</p> <p>问:演讲太棒了。我在想 AppCompat 库。你应该无时不刻都使用它吗,或者如何使用它?</p> <p>Mike:非常正确。这里是原因。 AppCompat 向后兼容老版本操作系统的功能。你知道你能使用它,而且向后兼容的版本。但是如果你实在一台设备上本地支持这些事情, AppCompat 不使用本地方法,它会使用本地抽象层。因为如果本地支持,你不会使用它了,所以你才打算使用 AppCompat 。手机本身知道,”这个东西是本地的,我想使用它而不是 AppCompat 的东西”。</p> <p>问:我想知道因为有些人不打算支持 4.0 以前的版本,所以它们不使用 AppCompat。</p> <p>Mike:: 即使这样, AppCompat 的功能在 4.0 以前也是不支持的。这现在非常常见 – 没有很多人支持 2.3。我看看我之前有着大量用户的典型应用,只有 2% 的人使用 2.3 的手机,所以我们不太需要考虑这些。但是 4.0,4.1 的手机,我认为差不多有 15 个百分点。我们讨论的大多数功能不是都能向前兼容,比如百分比布局。我提倡都用它。</p> <p>See the discussion on Hacker News .</p> <p>Transcription below provided by Realm: a replacement for SQLite & Core Data with first-class support for Swift! <a href="/misc/goto?guid=4959662083241304656" rel="nofollow,noindex">Check out the Swift docs!</a></p> <p> </p> <p>来自: <a href="/misc/goto?guid=4959674165357848211" rel="nofollow">https://realm.io/cn/news/kau-michael-wolfson-material-design-everywhere/</a></p> <p> </p>