实现Instagram的Material Design概念设计(1)

几个月前(本文发表于2014年11月10日),Google 发布了app和web应用的 Material Design 设计准则之后,设计师 Emmanuel Pacamalan 发布了一则概念视频,演示了 Instagram 如果做成Material风格会是什么样子:

这仅仅是停留在原型设计上,估计很多人都会问,能否用相对简单的办法实现它呢?答案是肯定的。不仅仅能实现,而且无须要求在最新的 Lollipop 版本,实际上几年前 Android 4.0 发布之后我们就可以实现这些效果了。

鉴于此,我决定开始写一个新的系列文章,那就是如何将《INSTAGRAM with Material Design》视频中的效果转变成现实。当然,我们并不是真的要做一个Instagram应用,只是将界面做出来而已,并且尽量减少一些不必要的细节。

开始

本文将要实现的是视频中前7秒钟的效果。我觉得对于第一次尝试来说已经足够了,同时也考虑到了我们也要准备和配置我们的项目。

我想要提醒诸位的是,里面的实现方法不仅仅是能实现,也是我个人最喜欢的实现方式。还有,我不是一个美工,因此项目中的所有图片是直接从网上的公开渠道获取的。(主要来源是 resources page )。

好了,下面是最终效果的两组截图和视频(分别从 Android 4.0 和 5.0 上获得的):

视频地址:http://www.youtube.com/embed/rTucTiIlQDA

视频地址:http://www.youtube.com/embed/fYhpc1LddHE

 

准备

在我们的项目中,将使用一些热门的 Android 开发工具和库。并不是所有这些东西本篇文章都会用到,我只是将它们准备好以备不时之需。

初始化项目

首先我们需要创建一个新的 Android 项目。我使用的是 Android Studio 和 Gradle 构建系统。最低版本要求sdk是15(即 Android 4.0.4 )。

然后我们将添加一些依赖。没什么好讲的,下面是 build.gradle 以及 app/build.gradle 文件的代码:

build.gradle

简而言之,我们有如下工具:

  • 一些兼容包(CardView, RecyclerView, Palette, AppCompat),我喜欢使用最新的控件。当然你完全可以使用 ListView、Actionbar 甚至 View/FrameView 来替代,但是为什么要这么折腾?
    • ButterKnife – View注解工具简化我们的代码。(比方说不再需要写 findViewById() 来引用 View,以及一些更强大的功能,比如 onClick() 等等)。
    • Rebound – 我们目前还没有用到,但是我以后肯定会用它。这个 Facebook 开发的动画库可以让你的动画效果看起来更自然。(它提供了一些工具使用弹性动画,从 Facebook 的 Messager 的 Chat Heads 中你可以看到他们是如何展示的,我确定你希望在你的下一个项目中使用它)
    • TimberHugo – 对这个项目而言并不是必须的,我仅仅是用它们打印log日志。

图片资源

本项目中将使用到一些 Material Design 的图标资源。应用程序图标来自于 NSTAGRAM with Material Design视频,这里 是项目的全套资源。

样式

我们从定义app的默认样式开始。同时为 Android 4.0 和 5.0 定义 Material Desing 样式的最简单的方式是直接继承 Theme.AppCompat.NoActionBar 或者 Theme.AppCompat.Light.NoActionBar 主题。为什么是 NoActionBar?因为新的sdk中为我们提供了实现 Actionbar 功能的新模式。本例中我们将使用 Toolbar 控件,Toolbar是比 ActionBar 更好更灵活的解决方案。我们不会深入讲解这个问题,但你可以去阅读 Android开发者博客 AppCompat v21

根据概念视频中的效果,我们在 AppTheme 中定义了三个基本色调:

styles.xml

colors.xml

关于这三个颜色的含义,你可以看这里 Material Theme Color Palette documentation

Layout

布局

项目目前主要使用了3个主要的布局元素:

  • Toolbar – 包含导航图标和应用程序logo的顶部bar
    • RecyclerView – 用于显示feed
    • Floating Action Button – 一个实现了 Material Design 中 action button pattern的 ImageButton。

在开始实现布局之前,我们先在 res/values/dimens.xml 文件中定义一些默认值:

dimens.xml

这些值的大小是基于 Material Design 设计准则中的介绍。

现在我们来实现 MainActivity 中的layout:

activity_main.xml

稍微解释一下上面的代码:

  • 关于 Toolbar 最重要的特征是它现在是 activity 中 layout 的一部分,而且继承自 ViewGroup,因此我们可以在里面放一些UI元素(它们将利用剩余空间)。本例中,它被用来放置logo图片。同时,因为 Toolbar是比 Actionbar 更灵活的控件,我们可以自定义更多的东西,比如设置背景颜色为colorPrimary(否则 Toolbar 将是透明的)。
  • RecyclerView 虽然在 xml 中用起来非常简单,但是如果 java 代码中没有设置正确,app是不能启动的,会报 java.lang.NullPointerException 异常(原因是没有配置好 LayoutAdapter,它负责调度 RecyclerView 中的每一项)。
  • Elevation(ImageButton中)属性不兼容API 21以前的版本。所以如果我们想做到 Floating Action Button 的效果,需要在 Lollipop 以及之前的设备上使用不同的背景。

Floating Action Button

为了简化 FAB 的使用,我们将用对 Lollipop 及之前的设备使用不同的样式:

  • FAB for Android v21:

  • FAB for Android pre-21:

我们需要创建两个不同的xml文件来设置按钮的背景: /res/drawable-v21/btn_fab_default.xml(Lollipop之后设备) 和 /res/drawable/btn_fab_default.xml(Lollipop之前的设备)

drawable-v21/btn_fab_default.xml

 _drawable/btn_fab_default.xml

上面的代码涉及到两个颜色的定义,在 res/values/colors.xml 中添加:

可以看到在 API 21 之前的设备上显示阴影有点复杂。不幸的是,在xml中达到真实的阴影效果没有渐变方法。其他的办法是使用图片的方式,或者通过Java代码实现(参见creating fab shadow)。

Toolbar

现在我们来完成 Toolbar。我们已经有了背景和应用的logo,现在还剩下navigation以及menu菜单图标了。

关于navigation,不巧的是,在xml中 app:navigationIcon=”” 是不起作用的,而 android:navigationIcon=”” 又只能在Lollipop上有用,所以只能使用代码的方式了:

至于menu图标,我们使用标准的定义方式就好了:

menu_main.xml

在 Activity 中 inflate 这个menu:

一切本应正常,但是正如我在 twitter 上提到的,Toolbar onClick selectors 有不协调的情况:

为了解决这个问题,需要做更多的工作,首先为 menu item (res/layout/menu_item_view.xml) 创建一个自定义视图:

menu_item_view.xml

现在我们为 Lollipop 及之前的设备分别创建 onClick 的selector,在 Lollipop 上有 ripple 效果:

drawable-v21/btn_default_light.xml

现在,项目中的所有的color应该是这样子了:

colors.xml

最后我们应该将自定义视图放到menu item中。在 onCreateOptionsMenu() 方法中:

以上就是 Toolbar 的所有东西。并且 onClick 的按下效果也达到了预期的效果:

Feed

最后需要实现的是feed,基于 RecyclerView 实现。我们需要设置两个东西:layout manager( RecyclerView 需要知道如何管理每一个item)和 adapter(提供这些item)。

首先要做的很简单,因为这里其实只是想实现 ListView 的效果,所以直接用 LinearLayoutManager 就行了。其次,我们需要做更多的事情,但是没有捷径去实现这些。

我们首先从item的布局开始(res/layout/item_feed.xml):

item_feed.xml

在上面的代码中:

  • CardView – 在我们的每一个list item周围包装成圆角和阴影轮廓(这在 Android API 21及以前都可以实现)
    • ImageView 对应于feed元素的设计( SquaredImageView 是一种 ImageView 的实现,它具有整齐的dimensions)

FeedAdapter 也非常简单:

FeedAdapter.java

没什么特别之处需要说明。

通过以下方法将他们放在一起:

下面是整个 MainActivity 类的源码:

MainActivity.java

当你在设备上build并运行应用程序之后,你应该看到如下画面:

  • Android Lollipop:

  • Android pre-21:

动画

最后一件也是最重要的事情就是进入时的动画效果,再浏览一遍概念视频,可以发现在主 Activity 启动的时候有如下动画,分成两步:

  • 显示 Toolbar 以及其里面的元素
    • 在 Toolbar 动画完成之后显示 feed 和 floating action button。

Toolbar 中元素的动画表现为在较短的时间内一个接一个地进入。实现这个效果的主要问题在于navigation图标的动画,navigation图标是唯一一个不能使用动画的,其他的都好办。

Toolbar animation

首先我们只是需要在activity启动的时候才播放动画(在旋转屏幕的时候不播放),还要知道menu的动画过程是不能在 onCreate() 中去实现的(我们在 onCreateOptionsMenu() 中实现)。

MainActivity 创建一个布尔类型的变量 pendingIntroAnimation,在 onCreate() 方法中初始化:

onCreateOptionsMenu() 中实现:

在我们启动程序之后,startIntroAnimation() 将只被调用一次。

现在该来准备Toolbar中元素的动画了,也非常简单。很好的一点就是保持注意力,一般情况下,动画由一下两步组成:

  • 准备 – 我们为每一个动画元素创建初始状态。如果我们希望展现扩展动画,我们需要确保我们的每一项是隐藏的。
    • 动画 – 这一步我们的view会进行动画至最终状态或位置。

好的,让我们尝试为 Toolbar 实现这两个步骤:

在上面的代码中:

  • 首先我们将所有的元素都通过移动到屏幕之外隐藏起来(这一步我们将FAB也隐藏了)。
    • 让Toolbar元素一个接一个的开始动画。

当动画完成,调用了 startContentAnimation() 开始 content 的动画( FAB 和 feed 卡片的动画)

Content动画

在这一步中我们将让 FAB 和 feed 卡片动起来。FAB 的动画很简单,跟上面的方法类似,但是 feed 卡片稍微复杂些。

  • startContentAnimation 方法:

FAB animation

  • FeedAdapter,包含 feed item 的动画:

就是这些了!如果我们build并运行我们的项目,我们就会得到看到文章开头展示的最终版本的效果。

源代码

完整的代码在 Github repository

作者: Miroslaw Stanek

1 1 收藏 7 评论

相关文章

可能感兴趣的话题



直接登录
最新评论
跳到底部
返回顶部