Hello. Thank you very, very much
for coming, everyone. My name is Nick Butcher. I’m an Android
designer and developer. And I’m here today to talk to
you about the Material Design principles, about understanding
and building them. We’ve got a lot to cover. I’m going to teach you
a lot of stuff today. So let’s get started. So Material Design. Who’s heard of it? Hopefully everyone. So introduced at Google
I/O a couple of years ago. Right? An amazing design
system for helping you build incredible,
consistent, usable apps. One of the things that
I personally really, really like about Material
Design, and that I think sets it apart from other design
systems out there, is this. It has these principles. It has these kind
of– it strives to go beyond what a lot of
design systems do out there. It tries to answer
the question, what is the material that your
UI is actually built out of? It provides these guidelines
which describe the world that your UI lives in. It’s kind of like how we
have the laws of physics in the real world, which,
once you understand the laws of physics, they can
be applied to other situations. It’s the same in the UI world. If you have this level of
consistency underneath things, it means that patterns
learned in one place can be applied elsewhere. While Material
Design is very wide ranging– it kind of gives you
a lot of patterns and components to work with to build your
UIs with– no design system can be comprehensive. It can’t think of every single
situation, every use case that your app is
trying to solve for. But by having some
underlying principles, some kind of
consistency underneath, if you try and
stick to these, when you solve your
particular use case it will feel consistent with the
other components and patterns out there, making for a better
experience for everyone. But the problem
with the principles is that it’s somewhat
abstract, I feel. Sometimes it can be hard to
understand exactly how they apply to your application. So I’d like today to
talk to you about this. This is an application
I built called Plaid, which attempts to
embody these principles. So by discussing some
concrete examples of applying the
principles, I hope to help you to develop a better
understanding of what they are, to understand how they
can actually help improve your application,
as well as teach you how to build them on Android. So a couple things. This app is completely
open source. So you can grab the
source code on GitHub or you can join– it’s
in beta at the moment on the Play Store, which you
can join at that top link. This app– also, I want to call
out– uses a minimum SDK of 21. It’s a Lollipop and beyond app. I did that mostly
to unburden myself from backwards compatibility,
to see what we could build. But there are efforts going
on– actually, mostly driven by amazing third
party contributions. So there’s a back port branch,
which actually brings it all the way back to API 17. So yeah. Let’s crack on with
the application. So let’s go through the Material
principles one at a time, and let’s see how
we can actually make the application better,
and how to build those things. So the first Material
principle is the idea of Material tangible surfaces. This is the idea that
everything in your UI lives within a surface. And these surfaces can have
different sizes, shapes, and elevations, and so on. Now surfaces really,
really help you to– they tap into a part of your brain
which recognizes that one thing is separate to another. We call that tangible objects. That means you can see
that a button is going to be a tap target,
or that one surface is going to move past each other. It’s also really helpful
for providing hierarchy in your application. We’re really good at
knowing that things which are closer to you are
larger or more important. We just know this
from the real world. And you can use that in your UI
to direct attention to the most important information. Here’s an example. So in the application,
I showed some images from the awesome show and
tell site called Dribbble. And the image is the primary
focus of this application– of this screen. Sorry. So it gives this big old
prominent area at the top. But once you’ve seen
the image, you perhaps might want to take
some other action. So there’s comments or
descriptions and so on, then. I kind of want to get
it out of the way, but still have it accessible. So here’s how I do it in Plaid. Hopefully you can see it
collapses with some parallax to keep it centered. Then at a certain
point, the image pins– I like to think of it–
and lifts up to let the content pass below it. If we were to take a 3D view
of what’s going on here, it’s kind of like– it
collapses to a certain point, and then the surface
itself lifts up into a separate surface. And there’s another
surface going on here. The floating action button. We’re saying that this is
the most prominent thing. I think that liking
a shot is one of the most prominent
actions I want to call out. So having that on
its own surface which moves with certain
physics and then snaps when it reaches the
bottom of that lie there, again, helps to
direct attention. So how would we build this? Well, I decided to use
a stateless animator, because you could imagine
doing this yourself. Listen to the scroll
position of the list, and when you reach a certain
minimum height for the image, then just elevating it. But that would put
on you the burden of having to run an
animation, work out if the user has quickly scrolled
and quickly scrolled back, then you have to cancel
it and reverse it. Instead, using a stateless
animator helps you to– it does it automatically for you. So all I do is I basically
set this state of pinned to true or false, depending
on how far these are scrolled. And then just run an
animation over the translation z property, and it
will produce this lifting up and pinning effect. I use surfaces again
in the same screen when looking at
comments on a shot. So for each of the
comments in the list below, there are certain actions
you can take, replying, liking the comment,
and so on and so forth. Rather than an
alternative presentation– it might have been to have these
comments visible or overflow items and so on and so forth. But that would have led to a
more cluttered look and feel. I wanted this thing
a bit cleaner. So using the idea of surfaces
here, I think helped. Because, as you
tap on a surface, we have this idea that
it raises up and gets an elevation and a little
drop shadow underneath. And the comment actions
reveal themselves. So again, I feel
surfaces help to make it a cleaner presentation. And building it was pretty easy. There’s three steps to it,
which I’ll walk you through. So firstly, it’s a comment–
it’s an adapter at the base, so in the list use
adapter, we work out whether we can hold
onto the position of the current expanded item. And based on if it’s
the expanded one, we just set the visibility of
those little actions there. Then in the onClick handler,
we store the position of the one you are
trying to expand. And then we use one
of my favorite APIs in Android, which
is TransitionManage r.beginDelayedTransition. This is deceptively
simple, because it’s doing lots and lots
of work for us here. So by saying
beginDelayedTransition and, crucially, we parse
the whole of the list view, rather than the individual
view you clicked on. That will then watch
for any changes to any views underneath
the list view. So that’s going to handle
collapsing one item and expanding another
item smoothly for us. We then call
notifyDataSetChanged, which will then rebind
both of the items and set the right visibilities. You notice we also set
the activated state based on whether the currently
selected item’s expanded. We then just pretty simply
is use a stateless drawable for the background. And two of my
favorite attributes, which most people
don’t tend to set, is you can set this enter
and exit fade duration. So this will
automatically handle the color change for you. So when you select
an item, it fades in nicely from the background
color to a pure white, to show it in the
selected state, or fade out the one that
is getting deselected. All, again,
automatically for you. And similarly, we use
a stateless animator again to do some translations
z to lift up and out. So hopefully you can see just–
some pretty simple stuff. There’s no major custom
work going on here. It achieves this quite
smooth, nice effect, and makes for a cleaner layout. So I think surfaces really
helped with this here. Next up is this section of
the Material spec, which I really, really like,
which is talking about navigational transitions. And it talks specifically
about navigating from a parent to a child screen. And it shows this video here. I love this idea that
when you click on an item, it lifts up out of
the parent screen and expands out to
fill the screen. I’ll come back to the motion
part of doing that a little bit later on. But part of the thing
I like about this is the idea– this
permanence idea that the previous
content is still there, and that the new
screen is lifted up and it’s sitting on top of it. I use this idea in Plaid. So for example, here is a grid
of images we’re looking at. When you tap on one
item, it lifts up. But crucially, what
I’ve done here, is that when you
overscroll down, I start to translate and
scale the content downwards. But peek, and you can
see the screen behind. Again this is
reinforcing this idea that this new screen of
content is sitting on top. I feel like it gives it
more of a sense of place. You understand where
you’ve come from. It’s hard to get
lost, because it’s so continuous an experience. So to build this– notice also
that when you try and collapse it, it’s a single gesture. So in the content here,
I’m scrolling down, keep on scrolling
from the same gesture, leads to this
backwards behavior. It’s not like you have
to scroll and then scroll again or
anything like that. It’s one single experience. And that’s all built
on the awesomeness of nested scrolling. So if you haven’t checked
out nested scrolling, it’s really, really cool. So here’s a– it’s a
custom view I wrote to do this, which extends
frame layout. And what nested
scrolling lets you do is listen to scroll events that
the child of that is doing. So inside the
frame layout, there is a ListView here which
is sending scroll events. And basically, you just
overwrite a few APIs. So the first one is
onStartMessageScroll. This is basically
asking, are you interested in listening
to more nested scrolls. Here I’m saying, anything
that’s scrolling vertically I’m interested in, please
send me more events. So if you returned true from
that one, every time the user scrolls in the list, I’ll get
this onNestedScroll event. So you can do stuff
with working out how much the ListView
scrolls by itself, but the one I’m actually really,
really interested in here is that last parameter,
which is dyUnconsumed. So that basically tells me
if the List has scrolled to the end of its scroll
range, but the user carried on trying to scroll, there were
some unconsumed scroll events. So I want to take those,
and I’ll then just use set translation
y and set scale to actually translate and
scale down all the content, moving it away. And then finally, when the
user lets go, I can work out, did they scroll past
a certain threshold? If so, I’m going to
finish the activity and run an animation
to collapse it. Otherwise, I’ll settle it back
into its natural position. The final part of
the puzzle here is that the activity was sat on
top of the previous activity. And you can see through
to it the one behind. The way that you do that
is you set this flag windowIsTranslucent. And what that means is that
you’re telling the system, don’t finish the
previous activity. So it’ll go into onPause,
but it won’t actually go into unDestroyed,
because you’re saying that when the content
on top is translucent, it’s going to be able
to see through to you. It’s kind of like, if you showed
a dialog on top of your app, rather than showing a new
activity, it won’t finish you. And then you set a
semi-transparent window background. For those of you who
don’t read hex colors, that’s like a semi-opaque gray. That’s how you build it. So that was surfaces. Again, I think made it
more understandable. So another example of
surfaces in the application is– this is a Dribbble
profile screen. So here I use surfaces
with great prejudice to basically show
content hierarchy. So here, when you
scroll the content, I actually made the decision to
leave the profile information statically, and have the images
scroll completely on top of it, completely in front
of the content. This is me being
opinionated and saying, I think images are the most
important part of this, and I want to direct
attention to those. And that’s how you do it. So how would you build this? You can consider–
a frame layout lets you overlap content. So you might put the
profile information in one layer, then the
RecyclerView of images on top. And that’s all well and good. But what about the clicks? If the RecyclerView’s
on top, how do you let clicks pass through? So I kind of cheat
a little bit here. So I set an onTouchListener
onto the RecyclerView itself. And then I work out where
the top of the first item is, which I’ve set
down with some padding. So then, if the
touch point where you’re touching on
the RecyclerView is above the first
item, I directly call and dispatchTouchEvent
onto the content behind. This is the description
field behind. So that forwards
on the touch event. So again like letting the touch
pass through the RecyclerView onto the content behind. So it lets you do this
kind of layering trick. And my last example
of surfaces is– I love the idea that
surfaces, while they’re inspired by paper and
things in the real world, they’re not limited to them. I love the idea that we can
transform from one shape or object to another. So here for example,
I’ve got a couple of actions which use the
floating action button pattern. And when you touch
it, sometimes you have more actions to be taken. So if you’re trying
to like a shot, and you haven’t logged
in, I want you to log in. Or if you’re trying to upload
a new shot and a poster design and use, you have to
give details of it. Rather than– you could imagine
a different presentation, where you just show a new
screen or just show a dialogue on top of it, I
feel that by transforming the surface itself,
it’s clearer that you’re trying to act on this thing. And it requires a second step. I think the transformation
aspect of it helps you to have a
continuous experience. I haven’t got time
to show you how I’ve built this
particular– shared element transition is what it is. But if you come to
my talk tomorrow, I actually go through it. So that’s a window
into transitions. That was surfaces. Second principle I
want to talk through is using bold graphic
design inspired by all the great design
literature out there. This talks about using classical
things like color, typography, space, and imagery
to really provide a nice, clear, and
beautiful presentation. So in earlier builds of
Plaid, I tried to use color, like color primary and
distinct blocks of color, but I found that displaying
a lot of imagery, as well as lots of bold
colors somewhat clashed. So in the end, I ended up
backing out a lot of color. In fact, if you look
at the screen here, the only thing I’m
contributing is the kind of floating action button,
that little green button at the bottom. The idea here being that
content was the main thing. I wanted to reduce my
personality to make room for the content to shine. That doesn’t mean you can’t
use color in interesting ways. So I instead use some
dynamic coloring in order to make the app still
feel alive and thoughtful. So here for example, as
you’re clicking on an item, you can see the touch response–
the touche ripple you get is determined by the
item you’re clicking on. So the gray and red one
gets a nice red ripple, and the one below gets
like a bluey-purple ripple. Hopefully that comes out. So the way you do that is from
the awesome, awesome Palette library. So Palette runs over an image
and picks out the palette of colors inside the image. And one thing I want to call out
is it offers this Filters API. So Palette by default
it’s built for working on landscape imagery. So it’ll actually ignore
certain color ranges. It’ll never give you pure white
or pure black, for example. I actually want that
in this application. The imagery that I’m
dealing with here is actually different
to the landscapes. So you have this API to
clear the filters, which will give you a
wider range of colors that it will actually
pick out an image. Worth knowing about. Once you have a Palette, I
then have this little method to create a ripple
drawable for me. Now, Palette will give
you these named swatches. In particular, I really want
to use the vibrant color. So picking out that red
from that first image we saw is a great way to kind
of tie the touch ripple back to the item. So what I do is I walk through
the swatches one at a time. You have to go
through them each, because you’re not
guaranteed that there’s going to be a named swatch. So for example, if I were to
give a black and white image, it’s not going to
be able to return me a vibrant color from that. So you go through them one at
a time, in a preference order. Work out what color
to use, and then create a new ripple drawable. And then set that as the
foreground onto the image you touched on. I actually take this
idea bit further when going into a
details view of an image. Here I am quite zoomed in. So as I click onto each image,
I want to have this immersive, seamless feel to
the application. So what I do is I again
use color picking. I pick a color out of
the image and set it as the status bar color. You could have achieved
something similar by using a semi-transparent,
partially black, perhaps, status bar color and having
the content run behind it. But because the detail screen
is all about the image, I wanted to overlay
as little as possible to not have anything
on top of it. So instead, I used
this color picking. But what about a
situation like this? So here’s an image which is a
couple of major color blocks. If you were to run Palette over
the entire image like this, it’s likely going to pick
out the of purply blue in the middle, because that’s
the most dominant color, but that’s not what I want. So I don’t want have this
purply status bar, then a block of white and then
another purple in the middle, it’s going to look
quite discontinuous. What I really want
is to run Palette over just a subset of the
image, just the top part, such that that’s going to
be the best color to set it against as a status bar. So you could imagine
a situation where you could create a second bitmap
and run Palette over that. That’s going to be
quite inefficient. Palette’s already
walking over bitmap. A better thing you can
do is use the Region API. Palette here offers an
API that says, only look at this area of an image
when you’re picking colors from it to consider. So it’s going to be
much more efficient. And I also want to
call out the fact that Palette lets you set
the maximum number of colors that you look at– that
you consider in an image. Basically what Palette’s
doing is walking through, trying to bucket the colors
into smaller and smaller bucket sizes until it comes out
with this Palette of colors which are in the image. And you can control that. So here I found setting this
allowed me to pick the more dominant colors quicker. And lastly, you
might have noticed I’m using the awesome
LightStatusBar API on Marshmallow. So that basically lets me
set dark icons for the Wi-Fi and the clock and the
battery and so forth. The way you do
that is I basically pick a color from the
image for the status bar. And then check if it’s
light by essentially converting the RGB into
HSL– hue, saturation, and lightness– and then looking
at that third component, just the lightness, and seeing if
it’s over a certain value. Then say, yet, that’s light. And if so, setting the
status bar against dark. So it’s all about creating
this immersive feel where the content is
contributing to the UI. Next up, Material recommends
using certain grids. So here I am overlaying
some of the key lines which we worked with in Material. And I think this
really, really helps in providing a regular
rhythm to your application, making it easier to scan it, and
parse it when you look at it. One section of the Material spec
which I found quite interesting was that it says that you should
use an 8dp grid for most items, but typography should
sit on a 4dp grid. It does this mostly by setting
line height, recommending leading or line height
that you should work with, which are all multiples of 4dp. But unfortunately, Android
doesn’t offer a built-in way and text you right
now for doing that. So how do we do that? How do we make sure our
text all sits perfectly on this 4dp grid in order to
get this nice, regular rhythm? Just for comparison’s
sake, on the left is without the 4dp
base length grid, and on the right is
where– hopefully you can see that this is–
you might consider it a small thing– like maybe
having type sit on the grid, but I really think it helps
the readability of the screen. You can park, scan
down it, and read it. And hopefully it just feels
a lot more regular to you. So what we really want is to
be able to specify that line height. So here’s a style where I’ve set
a– specified the line height to match it. I would call out,
especially, that I called it lineHeightHint,
rather than just lineHeight, because with type,
we all know we should be working with SP units. Right? So that you can
take into account if the user has
bumped up or down the text size for
their particular needs. So I call it lineHeightHint
because this lets you specify the line height in
the same units, in SP, such that, if the user has
set their text to be larger, you want the line
heights to grow with it. Then I created a custom
view, which extends text view and does some magic for us. First it basically
takes that line height you specified, and rounds
it up to the nearest 4dp. Essentially making sure it’s
going to– the line height’s going to be a multiple of 4. I then work out the
height of the font. And then call an API which
TextView does give you, setLineSpacing, which wants
to take the line spacing additions– so that’s
the line height I want, minus the height of the
font, is the addition. And that will give you the
4dp grid that you want. The custom view actually
does some extra stuff. It makes sure the padding
top is at the right, so that the first
baseline sits on the grid. And it adjusts
the padding bottom to make sure the entire element
is a multiple of 4dp as well. So a bit of work, but I really
think it really helps give you this nice regular typography. Speaking of
typography, I also make use of some of the more
advanced features of Roboto. So hopefully you
know that fonts often come with lots of
variations in them. So for example, here I’m using
this small caps presentation. And this is what they call
old style numbering, which gives you a different
numbering format. I feel that using these
different typographic variations help you
to express hierarchy and gives some visual
interest to the screen. You have more range
of presenting text. So rather than using lots of
different text sizes or colors, using different
presentations like this help you to say what
information is more important, making it easier
to scan through it. You can set these font feature
settings really easily. They use this web syntax
where smcp, for example, means use small caps or onum
means use odd numbering. There’s a whole bunch of
things you can fiddle with. But I encourage you to check
out the different range of typographic options the
font you’re using gives you. And while grids
are awesome, I also think it’s interesting
to break out of the grid. So here, for example, we have
this floating action button, which kind of straddles this
title and description field. This breaking out of the
grid draws attention to it. But you can come into
issues when you’re doing this kind of thing. So you don’t want the FAB
to be on top of any text. You don’t want it
to be obscuring any important information. So what are you going to do? You could, for example,
just add some padding to the right,
which might prevent any overlapping of the text. But you’re going to
end up with this less than ideal
presentation, where you have these big empty spaces. What we really want is– my
slide to advance– there we go. What you really want
is to be able to lay it out to the full bounds,
but then kind of flow around any overlapping areas,
like this, which is what we do. Let me go back a second. So everyone knows that TextView
doesn’t have a flowing API, unfortunately. But hopefully you know that
TextView uses something else under the hood to
actually lay out its text, it’s just called
Layout, funnily enough. But Layout got an
interesting– I’ll say static layout,
particularly, which is what’s used for
unchanging text– got an interesting addition in API
23, which is called setIndents. So this API takes an array of
ints specifying the indents to use per line. So we can use that
API to work out which lines of text in the title
field overlap with the FAB, and set an indent. So on that second line, set
an indent on the right, such that we can build this
kind of flowing behavior. So create a custom
view again, which again, works out where the
overlap between these two views are. And it calculates an
array of these indents that we want to set. So essentially, the second
line in the right index is going to have an indent. And then you create a layout
through the Builder object passing those indents,
again, letting you wrap the text around it. This is kind of cool approach. I think is quite a useful thing. But it comes with
a giant warning. So as you can see,
this extends View. Unfortunately, TextView doesn’t
have a set layout method, so you can’t just create
your own static layout and pass it into TextView. So I’m having to extend
view, and then in OnDraw, having to draw the
layout on to the canvas. So it’s a pretty cool
technique, but that means you’re not at
TextView, so if you have to do things like right to
left support or accessibility, you’re kind of on
your own there. So great power,
great responsibility. One of those APIs. Right. While I’m talking
about layouts as well, one of the things I wanted
to do on the grid screen is provide a bit
more visual interest. While a regular grid
is fine, I actually wanted to provide a bit
more visual interest and highlight certain items. So here for example,
the middle image is actually spanning
two columns. So it’s maintaining aspect ratio
but spanning two columns again, to provide visual
interest to certain items. RecyclerView’s gridLayoutManager
makes this super simple to do. You basically set a grid
span– setSpanSizeLookup to return how many
columns it should span. And I basically delegate
that to my adapter which knows more
about each item. The problem with this approach
is that grid layout manager will happily leave gaps. So if you say I want
to span two columns, but it’s actually in
the second column, it’ll actually just
leave a gap and put it on to the next line,
which isn’t what I want. So here’s a protip on
how you can avoid that. I essentially hold onto
the positions of the items that I want to expand
across multiple columns. Do some bookkeeping to basically
work out where in the row that will appear. Because I want to
span all the columns, I know that the item has
to appear in the leftmost, in column 0– row 0– row
position 0 in order to span, otherwise it’s going
to leave a gap. And I then essentially
swap it with the next item it could appear in in order
to not leave any gaps. I want to say that this
approach has some drawbacks. So right now, here’s how
it looks on a tablet. So here I am using
four columns– but essentially,
spanning four columns, maintaining aspect
ratio, isn’t ideal. It’s leading to
this whole thing. So here’s a sneak
peek of something I’m working on right now. So this is a custom
RecyclerView layout manager, which is allowing me
to span both columns and rows simultaneously. So that you can have this item
which is appearing, taking up four cells, as it were. And other items are
flowing around it. So this will be getting pushed
open source real soon now. Promise. And next, I’m going to talk
about what you probably guessed is one of
my favorite portions of the Material spec,
which is talking about meaningful motion. I just want give a
massive shout out, though. It was a really, really
good session last night by John Schlemmer, talking
about their recent updates to the Motion design guidelines. If you haven’t checked it out,
I highly encourage you to do so. So the meaningful
motion section talks about using motion
not just for showbiz, but for actually
guiding focus and giving a spatial model for providing
interaction cues and character. So let’s look at what
these principles mean and how they help me in my app. So here for example,
is a list of players– a list of Dribbble users. And when you click
on one of them, it expands out to go
to a detail screen. So again, that could have
been just a new screen with a default transition. And Motion really, really
helped the design here. It’s going a bit fast, so
let’s slow it down and look at the things that’s happening. When you click on a user,
first thing, I raise it up. So it’s the idea that this
item is lifting out of the list and then grows. You see how the whole
card itself grows out from its original position,
while also the image– the main point of focus
during a transition– smoothly transitions from
its previous position into a new position. And then finally, the rest
of the content enters. So how would we build that? The first bit, raise
on touch, that’s easy. That’s my friend the stateless
animator we looked at earlier. Here we’re keying on the state,
if it’s pressed or not pressed. And we say we want to animate
the translation z based on if it’s pressed or not. That’s pretty simple. Next up, the expanding row. This is a shared
element transition, using API 21’s transitions API. So there’s actually two
shared elements going on here. The first one, the image,
it’s pretty obvious. Right? You say the image is here,
and it’s going to here, and this changeBounds
transition will handle the size and location change for you. The second shared element
is actually the background. So the background of
the list item, I say, is the shared element. And I want it to transition
to the background of the details view. And it grows out like this. So one drawback of
this approach is that, by default,
transitions will use what’s called the
shared element overlay. That means that they’re
on top of everything else. Now if you put the background
on top of everything else, you’re not going to see any
of the rest of the content. So we wanted the
background to come in and the content to come
in at the same time. So you actually have to turn
off that shared element overlay, using this flag in your theme. And that will
prevent that issue. Next thing I’m going to
call out is– hopefully you noticed it’s using
this arced motion approach. So things that move linearly
can often seem robotic. Using arced motion,
curved motion paths, feel more natural and
more organic to us. This is super simple to do in
a shared element transition. You literally just add this
tag here inside your transition definition to say
arcMotion, and it will do this arced path for you. So easy. I love it. And the last bit is
a custom translation which I wrote, called–
which I’ve called LiftOff. Now, it’s easiest to show you
what this does by showing you with and without it. So here’s two versions
of the same video. So you touch on the
item– oh yeah– one’s with, one’s without. I hope you see that. Hopefully you can see there
that, as they start expanding, one of the items is
casting a shadow, using my custom transition,
it’s a classic shadow, and one isn’t. So it’s not [INAUDIBLE]. It’s a bit easier to see
on the way back, actually. This is because, if
you haven’t seen, transitions all happen in
the destination window. They’re all happening
in the details view. So in the details
view, the background has no elevation or anything,
it’s the background. So it, by default,
won’t cast a shadow. So by running a custom
transition, which will actually set some elevation
on the background while it’s transitioning, we
can actually cast this shadow. This might seem– maybe I was
being a bit too nit-picky, and– does this
actually add anything? You might not see
it at full speed, but it just feels better. It feels right. Trust me. This is the easiest transition
I’ve ever written in my life. You basically pass it
in at a value elevation to use during the change. And you just animate the
translations z property to start off from the elevated
value and settle down back to 0 over the course
of the transition. And I actually run this for
a slightly longer duration than the– let me see if I can
get this to show– I run it for a slightly longer duration
than the ChangeBounds, as well. So you see it actually
changes into position and then settles down. So it gives this
effect of lifting up and growing and collapsing
and setting back in. Last piece is that the
image is moving upwards, so I wanted the content
to enter upwards with it, to make it this kind
of cohesive experience. So rather than the image coming
in and the content just popping in, I wanted it to like
feel like it was all moving in the same path. So mostly it’s handled with
this window content transition. So there’s both a shared
element transition and the window content
transition on the same screen. And it’s just using
this slide to slide the content in from the bottom. But as we saw
before, this screen is some static content and
then a RecyclerView of items. So that led to
this weird feeling where some of the
content would slide in, and then the RecyclerView
does a network request, gets the images, and
then they just load in, which wasn’t ideal. So instead, I wrote a
custom item animator for the RecyclerView, which
will then animate the items in upwards, as they load. So just extend the default
item animator that RecyclerView gives you for free. And I overrode the animateAdd
method, where you basically do some set up. You basically translate
it downwards and set it to invisible. And then when you run
the pending animations, you animate those properties
back to their natural place. You fade it in, and animate
it upwards, and do some stuff. So that was one transition. Another transition I want to
talk about is the search view. So this is what searching
looks like in Plaid. And again, there’s quite
a lot going on here. So let’s slow it down and
step through it a little bit. Firstly, when you
come into the screen, I expand out this
scrim, and then also do an animation
on the icon itself to change it from the
search icon to the back. And then fade in
the search field. And then, once you’ve done a
query, we load in the results. So the goal here is really
about directing attention. So when you touch
on the search thing, I want it to feel like
this transient experience. So that it’s just
coming in transiently over the top of
the content, which is why I do that scrim
coming in slowly and gently. But the next thing
I want you to do is to enter a search query
in the search field, which is over on the left. So that’s why I feel the
animation over from one side directs your attention to
what you have to do next. Similarly, once you’ve
entered your query, you can see that the
container expands downwards to make room for
the search results to come in. Again, that’s priming
you for the attention. For you to say,
OK, I’ve done that. Now I’m looking
down here to where the content’s going to be. It’s all about directing
your attention. Like the previous screen, this
is obviously doing network. Right? It’s going out, hitting an
API with a search query, and getting content back,
and loading the images. I feel like this
animation also helps hide some of that work going on. It’s distracting. The animation
stretching downwards is buying time while I’m
doing this networking and coming back to make it
feel more responsive than it, perhaps, technically is. Now I’m not going to go
through every single step of this animation, because it’s
using a lot of the principles we’ve talked about before,
using animators and so on. One thing I do want to focus
on is on the icon animation. I feel like doing
the icon animation, as well as directing attention,
it also is a playful element. It embodies some character
to the application, I feel. I also have to
call up some credit to– I was inspired to build
this animation from something I saw on Dribbble. So it feels quite apt. A dribbled line
referencing Dribbble. Anway– How would we build an
animation like this? So this is a animated
vector drawable. So hopefully if anyone here
has worked with vectors, you know that you can basically
draw lines and fill paths and so on and so forth. But not many people, I think,
know about the trim properties you can set on a line. So here’s a line,
which is stroked– which goes from left to right. And you can set these
trim properties, which basically say how much–
which portion of the line you draw. So if I set a trim end of 0.75,
it means from 75% of the way to the end won’t be drawn. And similarly, if you set
from trimStart of 0.5, then the first half won’t get drawn. So knowing how
that works, we can see this is actually
just four lines. So there’s one line which joins
at that stem, as I call it. And there’s two lines
for the arrowhead and one line for the
circle at the top. And all we do is we
animate the trim start and end values in order to get
it to trace out this animation. So the arrowhead and the circles
are going to go completely, clipping it to make it hide. Whereas the stem thing– part
of it’s always on screen. We never actually trim the
whole thing, as it were. It just animates
between the two states. Notice also that the
stretching out of the lines. As it stretches out,
this is really, really easily achieved just by
setting different durations for animating the start and end. So here’s how you build it. So this is one vector drawable. Like I say, there’s four lines. So each of these path
objects is a line. So it has a name, so you
can identify it later on. And a couple of
protips for building these things I
found really helpful is to create a resources file,
like a regular resources file that you put your strings
and ints and stuff in. And reference that and put
the paths and the fraction of the trim values in
that, because if you’re going to refer to
these a few times, it makes it easier to
only have it in one place. And then you define
object animators for animating each
of those properties. So here’s one where we’re
animating the trim start and end. And then here, referencing
out to those fractions that I want to trim to. And again, this is where
setting a different duration allows you to have that
stretching out and coming back together feel really,
really simply. Then the last
piece of the puzzle is the animated vector,
which pulls together the drawable and the animator. And says, what to run it on. So here you identify it by name. So on that stem,
run this animator. And then finally, to use it,
you just load it as a drawable, set it on ImageView
and call start. So hopefully you can see,
maybe a bit of effort, but I think worth it for the
quality of some character to the application. So I want to call
out– this is the way to run an AVD for a
one-shot type operation, just to run the animation. But a nice way you can do it
is often to do state changes. So for example, here
is when you like or unlike a shot on Dribbble. Basically you have animations
between those two states. So when you like
it, it’s basically– there’s two versions
of the heart. There’s a stroked version
with a filled version on top, and then you apply
a clip, which you animate the clip
up and down, which gives you this filling up. And unliking is basically,
two paths and you just rotate and fade them, and then
do the the trim line thing. That’s a fun little
animation that you can write. But Android offers you
this animated selector, which makes it way easier. You don’t have to manually
run all these animations all the time. It’s a bit like a
drawable selector. So you have states like,
for example, the FAB is just checkable. So when you press it,
it’s state checked. But the animated selector,
unlike its regular selector cousin, lets you
define a animation to run when moving from one
of these states to another. So when it goes from
checked to unchecked, it will run that animated vector
drawable, the avd_heart_break. And you’ll get that
nice little animation. So here’s just a few
more examples of where we’ve used little animations. I really, really, really
believe that these are a real opportunity to
bring character and whimsy to your application, and
make it more fun to use, have more personality. You might think,
are these necessary? Are these strictly necessary
to make your application functionally good? Probably not. But I really, really
think it’s worth it. And I encourage you
to look into using it. And they’re also really,
really fun to write. So that’s it. That’s hopefully given you a
appreciation of the Material Design principles. I really feel that
they’ve helped make my application better. The purpose of this
talk today wasn’t to say you should all copy over
the code from my application and put it into
your applications. [LAUGHTER] Although you can,
it’s open source. What I really want to encourage
you to do is to see it’s worth it. I think it’s worth putting
in the effort of going the extra yard, the extra
mile to really bring some quality, some character
to your applications. And go out and make
something which is awesome. There’s a few
links to follow up. Again, you can get the source
code or you can join the beta. There’s also an awesome
code lab for anyone wanting to get their hands
dirty with some Material Design goodness. And always, you should
subscribe up to Google Design. And that is it. Thank you very much. [APPLAUSE] [MUSIC PLAYING]