Android Wear UI Development Best Practices (Google I/O ’17)

Android Wear UI Development Best Practices (Google I/O ’17)

my name is Aga, and I’m one of the TLs on the
Android Wear Support Library. OLI LAN: And I’m Oli Lan. I’m the lead engineer for watch
faces on the Android Wear. It’s great to be here. We’re excited to tell
you about some new things to help you build apps and
watch faces on Android Wear. I’m going to
introduce some tools to help you build watch faces
with support for complications. But, first, Aga’s
going to tell you about some big changes
coming to the support libraries for Android Wear. AGA MADURSKA: Thank you. So when smartwatches first
launched, a lot of developers struggled to build apps
for this new form factor. There were issues with small
screens, round screens, for the first time, and
also bridging information from the phone to the watch. We built a wearable
support library to help with these issues. And, today, I’m pleased to
announce that we are starting to open source our code. The wearable
support library will be moving to the
Android Support Library and will become the
so-called wear module. This is similar to other modules
in the Android Support Library. Ones that, hopefully,
you already know– like the Core UI or
the Recycler View or Design. So it will just become
another module for you, again, open sourcing the code. This is launching with Android
Support Library 26.0.0-beta1, so it launched,
actually, two days ago, so you can start using it
pretty much immediately. It’s very easy to
add to your code. You just add your
regular dependency with a very similar
structure to other modules. Just make sure to mention
wear there, and beta1. So, hopefully, this
change makes you happy. There’s a few
reasons to be happy. First and foremost,
as I said before, the code is not open source. You can stop trying to
reverse engineer it now. It’s all going to be out there. The APIs will now be part
of the support library, and they will be consistent
with the rest of Android and the rest of the
support library. We will have more frequent
releases along the Android Support Library that will
be roughly every two months. And this means we
will be able to take in more of your feedback and
react to it a lot quicker than we were before. But we won’t be moving
all of the code at once. That would be a bit of
a shock to the ecosystem to move everything. So we’ll start with
the UI components. And I’m going to focus on
that for the rest of my talk. So the first package
we’ll be open sourcing is the view package,
or now it’s going to be called the widget package. And there, we want to focus
on enabling round-friendly UIs and space-efficient
interaction patterns. So we’re targeting the two
main issues that developers had with UIs, which
is building stuff for round screens for the
first time in Android, and also building for
really, really tiny screens– very little screen estate. It’s not trivial to build
good UIs in such conditions. So that’s why those are the
things we’re focusing on first. Here’s a good example
of how we’ve enhanced a typical Android list. You used to have, on Android,
a very straight list– all the elements would
just go one by one– start at the top. What we’ve done
with wear here is we’ve played to the round
factor of the watch. We’ve adopted the list
to follow a curve. And that means, also, it
fits a lot more information on the screen than it was able
to with just a straight list. Here are some other examples
of our best round-friendly UIs. We’ve got the Launcher. We’ve got the Date/Time Picker– launched recently in the new
pocket– in the new Desk Clock app. And then we’ve
got LifeSum, which is a great example of
a third-party app that encompasses a round-friendly UI. So all of these make use of
the curvature of the screen. All of them manage to fit
more information in the UIs and are just, generally,
more pleasant to use. So these are the kind
of UIs that we want you to build in the future. And we want to help you build
those UIs with the support library. So when building the
wear widget modules– so the UI components– we were
thinking of the UI, generally, in terms of components– much like Android Framework,
much like the Android Support Library. So with this module,
we want to double up a suite of building blocks
that would make it easier for developers to put
together a UI, which is both intuitive and like
feels native on Android Wear– as well as build it
in a flexible manner enough that it will kind
of express the personality and the character of your app. So we’re exploring both tiny
building blocks, like views– so images views or text views. We’re also exploring
larger ones– like the WearableRecyclerView
or SwipeDismissFrame layout. And we call these,
specifically, components. And these components– these
larger pieces of data– come together to form UIs. So this is where you
come in as developers and will reuse our
components and views to build your own apps. Some of these views and layouts
already exist in Android, and some of them need to
be implemented specifically for wear. Those are the ones
that we would want to go to put in the wear module
in the Widget UI Library. So here’s a
visualization, again, of how we think about UI. It’s reusable building
blocks, rather than custom-tailored or
special-case interfaces. Hopefully, that’s
not big news to you. But I wanted to
make it very plain that this is what we’re going
for with this new library. So, again, with this in mind,
we hope we will enable you to build good interfaces–
functional interfaces, very rich ones– that feel native to Android
Wear but also express the character of your app. So this is quite a long project. The complete construction
of the wear module will take some time. So I want to now to
spend the rest of my time to talk a little bit about how
where we will make it happen and what’s the timeline for it– step by step. So we have divided all the
existing wear UI elements, broadly speaking,
into three categories. We will migrate the components
that are already built for wear and that are wear-specific
into the new wear module. Some components we will merge. Those are the components
that are useful not only for wearable devices
but also for handheld devices. So they can be reused on phones. There’s no need for them to
live only in the wearable space. So we will graduate or merge
them into the framework or into other handheld or
generic support modules. And then the last
group is the components that we will deprecate. Those are the ones
that are mostly associated with all the design
patterns that have not proven successful with our users. And I’ll talk a little bit
more about that in a second. So, first, I want to talk
about the components that will migrate. I want to, kind of, shine
a spotlight on them. Those are the most
important bits. They are the ones that are
launching with the Support Library 26.0.0-beta1. And that’s the
WearableRecyclerView, which gives you that nice
curved list that we used also to build the Launcher. And then we have
the BoxInsetLayout, which enables you to fit all
of your UIs on the screen into the center middle
square of the screen. So you can reuse, basically,
your UIs between a square and the round watch. And then we’ve got this
SwipeDismissFrameLayout, which is quite an
interesting case because it encapsulates
a design pattern that we want you to use. So this pattern is
replacing the Back button on the handheld device. On wear, we don’t use the
button for a back gesture. We want you to swipe
away your views. That was a specific
request from the developers during our Developer
Preview Program, so we’re making this
component available to you in the Wearable Support Module. The next group– oh,
sorry– so in terms of code, should be a really
simple short slide. On the example of the
WearableRecyclerView, this is how you import
it now into your code. And this is how you would
use it in an onCreate method and the activity, for example. So when– now with the
migration to the new module, there are very few
changes that we would need from you in terms of code. Hopefully, very simple
and easy to implement. So, first, we change the package
name to support.wear.widget– to distinguish this new UI wear
module in the support library. And then the second thing
is that we would introduce minimal tweaks to
the API, so that it is consistent with the existing
Android APIs and Support Library APIs. These are better APIs
and, hopefully, will make your code healthier in general. So super easy to
update your apps– really not much of an issue. Clicker, OK, so
then some classes– the ones that we’re
merging– are not only applicable to wear. This we will, as
I mentioned, merge into the main framework or
different support library modules. So here we’ve got mostly what I
call round things with an icon inside, sometimes. There’s a lot of them. All of them look the same. There’s no point in having
separate UI components for it– separate kind of
pieces of layouts that you would need to use. And also there already
is a circle image view in the support
library for handheld. So we’re going to take all
of those additional APIs that we’ve created and merge
them into that one component. So that there’s only one kind of
really strong, really flexible component for you to use. And then the third
group here, I want to talk about it on this
example of a conversation. And Hangout is a group of
layouts that we’re deprecating. So those are the layouts
that are associated with user patterns that didn’t
prove successful– didn’t prove popular with our users. So here, we are taking the
two-dimensional spatial model– where you could move either
vertically or horizontally in an app or in the system UI– and we’re transforming
it into a linear layout, like here just vertically,
which is following the material design principles. So all of the classes
associated with that two-dimensional spatial
model will be deprecated. So that’s the GridViewPager. That’s different action
buttons, action layouts, things like that. So this will, hopefully, slim
down your dependencies as well. That pretty much
encompasses everything that we’re going to
be doing in 2017. And here’s a rough
timeline of what I’ve just been speaking about. So, today, we’re
announcing and launching the wear module with the
first three core components. Just, again, to remind
you that’s launching with the Android Support
Library 26.0.0-beta1. When that program
graduates out from beta– alongside the O Launch– we will deprecate the old
APIs in the current place, and then we will
really encourage people to move over to the new APIs. Then we will, subsequently,
have regular bug fixing and update releases
of the wear module with the Android
Support Library. And then some time,
saying mid-2018, mid-next year, we
would be starting to remove old APIs, so
that we slim down, again, dependencies to the ones
that we want people to use. So that’s all from me. With that, I’m
going to hand over to Oli to talk
about complications. OLI LAN: Thanks, Aga. Some important changes there. [APPLAUSE] So I’m going to talk about
some new things we’re adding for watch face developers. And as this is a big win for
anyone building a watch face– yes, it’s another reason
to jump in the air in front of a sunset. More personalized
helpful watch faces are a key part of Wear 2.0. That’s why last
year, here at I/O, we introduced the Complications
API for Android Wear. On wear, just like in
traditional watchmaking, a complication is a display
of data on the watch face. So these are all examples
of complications. Apps using the Complications
API can be data providers, or they can be watch faces. And Android Wear manages the
flow of data between the two. So watch faces
using the API can be configured to show any
of the data providers that are installed. This lets users put
the information they care about just a glance away. And if you build
a data provider, you can get your app’s data onto
a whole range of watch faces. All of these apps already
include data providers for complications. There’s fitness
apps like Strava, there’s finance
apps like Robinhood, and there’s weather apps like
AccuWeather and lots of others. So if you add complication
support to a watch face that you’re building,
users will be able to choose from
any of these apps– if they’re installed as well
as from built-in providers like the World Clock, Next
Event, and Battery Life. It’s like you’re
adding functionality from all of these
apps without having to know a thing about them. Many watch faces have already
added complication support, including classic styled
ones like Ultimate Watch 2– more abstract styles like Venom,
and super customizable ones like Pujie Black. And there are ones that
are a bit different. On Move, from the [INAUDIBLE]
[? Moods ?] Collection– The ring around the
outside is a complication. So here it’s showing
your battery life, but it could also show
your fitness progress. Mesh Turbine HD shows the
complications on spokes, coming out from the
center of the screen, with a scrolling text effect. And Fit Cat– it has a cat. But it also has
complications using the API in their own style. So there’s a huge
variety of styles of watch face on Android Wear. And that’s why the API gives
watch faces complete control over how they draw the data– to ensure complications
fit perfectly and to allow new interesting
ways of representing the information. But this freedom can make
it hard to add complications support to a watch face. When you build a watch
face, you don’t have access to layouts or views. You draw directly
onto the canvas. And you have to create
the settings UI yourself. Today, we’re introducing a few
things to make this easier. There’s TextRenderer, which
helps draw all kinds of text onto a canvas. ComplicationDrawable is a
complete rendering solution for complications. A new setting sample shows how
to let users easily configure complications and style. And a test suite
provider lets you easily check if complications
will display correctly. So first up is
TextRenderer, and you might have noticed this has
been in wearable support for a few months. TextRenderer makes drawing
text onto a canvas easier. And that’s important
because many of the most useful
complication types include text, such as the
short text type, the long text type, and the range-value type. The strings in the short
text and range-value types will be short. They should only be
seven characters maximum. While, as in long text, the
strings can be any length, and there are challenges
rendering the text in both cases. So here’s a short text example. This string here is
seven characters long, and it fits nicely
at this font size. But this string is also
seven characters long. So to handle both of
these and make them fit, you have to measure the text
before you draw and adjust the font size accordingly. Here’s a long text example. A short string looks
good centered vertically, but the text can be any
length, so it can easily flow outside the box. You can use something
like a static layout to help with this. But you need to be
careful not to relay out the text on every frame. With TextRenderer,
you tell it the bounds that you want the
text to fit in. If seven characters
don’t fit, it will shrink the
font until it does. And longer text can be
flowed over multiple lines and ellipsized at the end. So let’s look at some code. So when you initialize
your watch face, create a TextRenderer using
this simple constructor, and you pass in the TextPaint
that you want to use. The TextPaint defines
the font, the text size, the color– things like that. Now because TextRenderer
caches things like the layout, you should create
one for each field. So we have one
for the text here, and we also have
one for the title. Don’t share TextRenderers
between fields. Now when you want
to draw, you need to set the text on the renderer. So you do that calling setText. And to get the text,
you call getText. Now this takes the
current time, and you need to do this every time you draw. And that’s whether you’re
using TextRenderer or not. And that’s because
some complications are time-dependent. So imagine a World Clock
complication, the text changes, depending on the time. Once you’ve set the text,
draw into the bounds that you specify. Now, it’s OK to pass in
the text and the bounds every time like this, because
TextRenderer only lays the text out again if
something has changed. That does mean
that sometimes you need to tell TextRenderer
that a change has occurred, such as if you
change the paint’s text size. And that’s because the
paint is a different object from the TextRenderer. So let’s imagine that we have
code that makes the text bigger when something happens. In that case, you should
call requestUpdateLayout on the TextRenderer,
so that it can adjust. Now one other thing
that TextRenderer can do is adjust the rendering
for the Always On screen, so for
the ambient mode. Many watch faces are black
and white in this mode, so you might not want things
like color emoji appearing. So you need to tell
the TextRenderer that the device has entered
ambient mode, so inAmbientMode change in your
watch face, you just pass the inAmbientMode Boolean
into the TextRenderer, like so. So that’s TextRenderer. We strongly suggest we use it
whenever you’re rendering text directly onto a canvas. But what if you
want not just text but the entire
complication drawn for you in a standard way? That’s where the new
ComplicationDrawable comes in. ComplicationDrawable
can render all of the six main
complication types, and it handles all of the
layout and styling for you. As an example,
let’s look at what you’d need to do to
render a short text complication like this. Now without
ComplicationDrawable, when data arrives, you need to
decode any of the images which are included. And you also need to cache those
images because you certainly don’t want to decode
them more than once. Now every time you
draw, first, you need to check that
that data is active. And that’s because
some complication data is only relevant within
a certain time frame. For example, if it’s
for your next meeting, you don’t want to show it
after the meeting is finished. And then to draw, well,
we draw the background. We draw the image,
and we draw the text– probably using TextRenderer. With ComplicationDrawable,
it’s much simpler. When data arrives, you
pass it to the drawable by calling setComplicationData. And then on every frame,
you just call draw. It is a drawable. Now like TextRenderer,
and like other drawables, ComplicationDrawable
draws within bounds. And the layout adapts to
the shape of the bounds, so here you can see,
within square bounds, you get a circular complication. Whereas, the wider
bounds give a pill shape. And you can also see that
the position of the icon is different in the two cases. If you don’t set any
style parameters, you’ll get a default
look, but there’s many things you can set, such
as the background color– the corner radius, if you’d
rather have something more like a square and a circle. You can change the border
or have no border at all. You can change the colors, and
you can change the typeface. You can create a
ComplicationDrawable programmatically with
a simple constructor. And then you can set the
styling options for active mode and for ambient mode. But if you have lots
of styling to set, you might find it easier
to use XML instead. You will need to be using
API Level 24 to do this. But as long as
you’re doing that, now you can just inflate the
drawable in the standard way. Now we do need the
context to render. So you’ll need to pass that into
us as well, into the drawable. And if you do that,
then you’re XML might look something like this. So attributes at
the top level apply to both ambient
and active modes– unless they’re overridden
in ambient mode by the attributes in
the ambient section. So there were a few things you
need to pass to the drawable. As I mentioned earlier,
you, of course, have to give it the
complication data. So in onComplicationDataupdate,
for your watch face, which is where you receive
the data, you just pass that data to the drawable. You also need to tell
the complication drawable when the device goes in
and out of ambient mode. And that’s because
the drawable handles the change of styles for you. So all you need to do
is call setInAmbientMode every time it changes. And you also need
to tell the drawable if there are any special
properties of the screen. So if it uses
tell the drawable that, and it can adapt the rendering
for those properties. And then to draw, now
if it’s the first time, or if something’s changed, then
you’ll need to set the bounds. So set the bounds, and
you just call setBounds on the complication drawable. Now the bounds that
you pass in here should be defined in proportion
to the watch face bounds. So you might say, position it
one-quarter of the screen width across. Don’t use fixed
dimensions, and that’s because watches vary
hugely in their size, so you don’t want to be defining
things in an absolute way. Then you need–
you just call draw on the ComplicationDrawable. This method also takes
the time, and that so it can get the correct
up-to-date value. So that’s it in
ComplicationDrawable, so that should really make it a
lot easier to add complication support to your watch faces. Now, ComplicationDrawable
is the biggest addition to wearable support. But the next two things
are available as samples, so that you can adapt them to
meet the needs of your watch face. The first is for settings. Any watch face
with complications should include a way
to configure them. And, usually, that’s in
your watch face settings. But if you bury complications
deep in your settings’ UI, it can be frustrating
for users who want to change things around. For the LG Watch
Style and support, we worked with our
partners, ustwo, to design a UI that
lets users have a visual interface for
setting up complications and also have quick
access to other settings. So here’s how it’s set up. At the top, we have
an image of the watch face with the complications
slots clearly shown. This lets users get
a good idea of where the data is going to appear. Provider icons show
what’s currently selected in each slot. Below, if you
scroll down, you can see all of the other settings. Now a background image
here is a special case. Technically, it
is a complication using the large image type. But in studies, we found
users understand this better as a separate item. So this is what it looks like
on the portions watch face. And now let’s see it in action. So you’ll see the user can
just tap on one of those slots at the top. It opens the complication
provider chooser, and they can quickly choose
what they want in each slot. It’s much easier
than having a list with left slot, right
slot, top slot, et cetera. If you’d like to try this
on a real watch face, download the ustwo looks
or Moods Collections on any watch running Wear 2.0. All of those watch
faces use this UI. Now, you’ll find this what
UI implemented in the updated watch face sample. So check out AnalogComplicati
onWatchFaceService in the sample. This has been updated
for the new stuff that we’re introducing
today, so it also uses ComplicationDrawable now. The config UI is
an AnalogComplicati onConfigActivity. And the items that
are shown in the UI are defined here in
AnalogComplicationConfigData. Complication Let’s take a quick
look at that class. So in here, you’ll
find this method gets data to populate adapter. And it returns a
list of config items. So those define what the entry
in that settings list are. So the top entry will probably
be the PreviewAndCompli cationConfigItem. That’s the view of the
watch face with the slots. And then we might have
a Background option. We might have some more
options and then return. The actual sample has a
few more details than this. So that’s settings. Now let’s say you’ve
added complication support to your watch face. How can you check that
everything’s working? For most complication
types, there are several combinations of
fields that you must handle. So, for example, if your
watch face supports short text complications, that might be in
the form of an icon with text, or it might be a text and
another piece of text, or just a single piece of text. The test suite provider
makes it easy to make sure that every combination looks
good on your watch face. So when you install
the test suite, it’ll appear in the
list of data providers. And when you pick it,
you’ll be able to choose which complication
type you want to test. So let’s say we
choose short text. Here’s how it might
appear on the watch face. And then all you have to
do is tap the complication, and it will cycle through
the different combinations. So all of these are
short text complications. And if your watch face
supports short text, it has to render all
of these correctly. This is a long-text
example, and for long text, there’s even more combinations. So it’s really useful
to give this a go and check that everything
works properly. You can have icons with text
and title, just text and title, or images as well. We’re releasing the test suite
provider open source on GitHub, so that you can
see how it works, and so that you can add your
own test cases, if you want. If you’re building a data
provider and not a watch face, I suggest you also
take a look at this because it’s a good example
of a provider for each of the different
complication types. So that’s it. So these four tools
should make it a lot simpler and easier to add
complication support to a watch face. Please do give them a go. There are code labs to
try out here at I/O, or you can check out the
samples on the dev site or through Android Studio. Or you can start using the new
version of wearable support, and try it out on your
own watch face right away. And please do let us
know what you think. [APPLAUSE] So this is just one last slide
that sums up our presence– Android Wear Presence
at Google I/O 2017. If you haven’t seen the talk
of yesterday at 9:30 AM, it is recorded. It was a general overview
of how the platform is doing and what’s new in the
platform this year. And today’s talk
is also recorded, so you can come back to
it after I/O is done. Thank you very much.

12 Replies to “Android Wear UI Development Best Practices (Google I/O ’17)”

  1. One thing I missed from 1.x is the ability to recover an accidentally swiped away card. A dialogue remains onscreen for a few seconds immediately after swiping away where one could hit an icon to get the card back for about 3 seconds. About text in the complication areas, has anyone thought of scrolling or paging?

  2. Can't find sdk build tools 26, is it not available yet?

    Edit: nevermind seems build tools weren't updated, only the platform tools?

    Checked, but the repository for that dependency cannot be found, is it available when the Android Wear O preview comes out?

  3. How do I add an ActionButton with xml? Can't find the right XML tag besides ActionLabel…. The developer site is also not very helpful in this regard by showing only very minimal examples :/

Leave a Reply

Your email address will not be published. Required fields are marked *