Best Practices for Themes and Styles (Android Dev Summit '18)

[Music] everyone thank you for joining us at best practices for themes and styles I'm Alan hi my name is Nick butcher and we're gonna be talking about some ways to think about themes and styles at a high level and how to apply those when you're designing themes and

styles for your application so first let's start at a high level the way that designers create mocks and the way that developers are interpreting them so here's the latest iteration of the material design theme palettes so if you're not using material design components for Android yet you may

recognize primary as the color primary attribute from the material theme in the platform primary variant as something like color primary dark and when you get a mock from your designer you may be doing a mental mapping of well this is gonna be my primary dark color in my

theme this is going to be the primary color and embedding those directly in your theme but it's important to make sure that your designer understands that there are these canonical attributes so if you're getting a mock that just has a hex color specified it can be helpful to

maybe push back a little bit and say let's call this the primary variance or let's call this the primary color and it's great that we have all of these predefined theme colors with meaningful names and meaningful contrast ratios that have to exist between foreground and background and additional

colors in the material palette occasionally you will get a brand new color that doesn't exist anywhere and finding a name for this may be difficult so here we have a purple color that's a little bit lighter than our primary variants and it has contrast against white so we're

going to be displaying white text on top of it if we want to come up with a name for this we should find something that can generalize but is self documenting and captures these constraints so that if we decide well we had a purple theme now we need

a blue theme we can reuse the name of that color and reuse those constraints so you could move from purple to blue very smoothly so what are we gonna call that well Oh in the material palette we have these on colors on primary means this is a foreground

color displayed on a primary background and we ensure that it's going to meet certain accessibility related contrast ratios so you'll be able to read the foreground text color against the background we have on secondary which does the same thing for secondary so if we're displaying something on that

light blue color it would be black text if we're displaying something on this purple color it would be white text so we can use these to generate the new name for this lighter primary color what should we call that well we're gonna use on primary so that determines

the foreground color protection for background color protection we want to make sure that it contrasts a little bit with primary so we'll include both of these in the name we can call it something like primary lights which seems incredibly straightforward and it is so you can tell your

designer hey every time we're talking about this lighter version of our primary color let's refer to that as primary light and it's going to have these constraints for foreground colors and background color protection so if your designer decides well in this next screen we want it to be

blue instead of purple we can continue to use the same constraints on this color and use our semantically defined color name in our theme as well alright similarly we provide common patterns for text appearances so here you see on the Left we have headline over line body these

are semantically defined terms they're meaningful names for where these appearances are going to be used and that determines the pixel size that determines the font weights that can determine the font itself and that's going to determine the color on the right we see what these values actually map

to so in this case headline is going to be Roboto and in fact we're using Roboto throughout our entire app however if we decided that instead we wanted to use let's say Comic Sans we could make our headline map to Comic Sans we wouldn't have to go through

and create a new style everywhere in our application because we do have these names that imply how they're used so always make sure to use meaningful names when you're extracting patterns from your mocks and applying those in your implementation so learn the material design attributes they're documented at

material dot IO make sure your designers learn them too and use this as a common language when you're looking at mocks and when you get something new that may have a random gray color in it that you're gonna see throughout your moths make sure it has a name

that you can use over and over again and if you happen to be implementing dark mode for anybody who attended that talk earlier today you'll know that this gray needs to turn into a light white because it needs contrast against a certain text color or a certain other

background color use meaningful attribute names they should be more or less self documenting something like primary light is going to have more constraints than just it looks sort of like the primary color and the text color should be consistent with other primary so go ahead and document these

somewhere start a doc that you share or start an internal site that you share with your designers to make sure you're always using a common language when talking about the components the colors the reusable textiles in your designs you'll expand beyond what's available in material I'm sure but

that's a good starting place to get a sense of how to name them and how to talk about them and part of that is avoid hard coding values so when you get a mock that just says this is the hex color for a 360 F make sure that

you push back on that and say no this isn't a hex color this color has some sort of meaning and we need to be able to smoothly transition from this hex color to a hex color with similar constraints all right so now Nick is going to talk a

little bit more about what this means in implementation and key right so we talked a lot about them and about supporting different semantical semantically named values in your applications and what that means on Android is essentially it can be implemented as theme attributes and Allen says something really

interesting there I said what happens if your design changes and all of a sudden instead of a purple theme you have a blue theme and how do you apply that these semantic names protect you almost against these cases and it's actually more widespread than you might realize and

I'll go dig into that a little bit so if you want to have areas of your app or screens which can support this kind of theming there are different ways you could achieve this one way might be that you just you know say define different styles so in

this one scenario I'm gonna surpass tile to give it a certain appearance we call that style one and in another scenario I want it to look different so I'll give it another style on style too the problem with this approach is that there's probably going to end up

being a lot of duplication between start one and style 2 and there's now two places for you to maintain or bug fix or you know maybe refactor at some point using these semantical pointers to kind of describe what the appearance should be like and or in kind of

coding terms it's going to end up as a theme attribute and protect you against this so while it we might be more work to kind of like establish this language and to set up your Styles to refer back to female beauty what it does is it ends up

with just a single place a single style and that will refer back to the theme attributes defined for a given theme and the benefits of this is it's going to reduce that duplication you don't end up with like two styles which are 80% the same but you know

have the potential to diverge in the future which they will and it also localizes the modifications so that means that if you need to change an attribute you just go to that one place where it's defined and change that rather than have to track it down where it's

leaked out into all the variety of styles you have across your code base it also has a benefit I think of consolidation how many times have you opened your colors XML file and found 50 different shades of very similar looking colors and then you see a mark and

it's not quite the same color and you go I don't know I'll just create another color resource because it's just me that is that and it's kind of like protects you against this you really really really want to kind of condense it down to this kind of small

palette which is used consistently throughout the applications you have a nice looking film so to sum up basically this approach really really helps you with the maintainability of your app and so as such I really urge you to prefer theme attributes where possible by which I mean if

you find yourself writing code like this top line so he's saying the text color should be you know this color resource and almost think of that as a code smell like just think for a second hang on is there this layout is there chance this might appear in

a different theme could this be like included in like a different area of the application and if so should I be instead be looking at this bottom form using the question mark actress in tax which refer it is how you refer to these theme attributes so we talked

about the importance of having these kind of semantically pointers but like how might your theme vary so hopefully everyone's familiar that you can set a theme directly on an activity so in this example two activities are using material components which is a dark theme and then a light

variant or perhaps you're using night mode like an ally mentioned before and it's also talked about in the cost of a pixel talked earlier today so this is a theme which will change between dark and light depending on the time of day but what happens if you have

a screen like this which is from and this is a Google i/o app where we have largely similar content so most of these list items are the same but the design called for some of them to be light on dark I'm Sun to be on dark on light

I mean you can think of ways you might implement this as separate layouts or perhaps setting text colors in unbind or something like that but both of those basically either leaking out the sliding information beyond where you want it or liter and like an explosion of more and

maintenance instead what you probably want to do is look at applying themes the view level rather than ever the whole activity level and so the theme attribute was added not theme attributes the attribute Android Quillen theme was added in API 21 but also back ported through Android X

so in this you can set a theme on a view or a view group and apply a different theme to a subsection of your view hierarchy and so in these examples here you might say you have a light theme and then apply a dark portion of it or

vice versa you can do the same thing in code if need be by using the context phim wrapper which takes an existing context which has a theme and overlays a style on top of it I think it's really important to emphasize that fact that it is overlaid that

means that you have an existing theme in any values from the theme you set on top of it are going to be applied on top so you need to be a little bit conscious of this fact in either and you don't want to overlay a theme which supplies

too many values so for example if I was using just material components dot light and I overlaid material components off dark they define a lot of the same attributes and you might be relying on some of the attributes you set in the first theme to still be present

so you might overwrite too much conversely you want to make sure the team you over writing sets the things you need so as such you might want to take a look at these team overlays of which there are some in-app compatible material components or create your own female

overlays extending from them just to theme the attributes that you want such that when it's overlaid on top of the existing theme you get the resulting kind of combination of themes one thing to be note as well is that while the context cream wrapper approach looks tent-like tantalizingly

close to dynamic feeling and it's not by which i mean that you have to apply a theme which you've defined at compile time you can't use this technique to say take some server derive color values or whatever and create a dynamic theme this is all about this kind

of ahead of time thinking all right so before you start setting a bunch of theme attributes it's important to understand how those are applied throughout the platform so we're going to do a whirlwind tour of the layers of indirection that occur between what you see on screen and

what's defined by the platform and what your setting in your application themes so at any point in your application it's good to have background understanding that it you can point it something on-screen and understand all of the layers of indirection all of the theme attributes and styles that

were applied to render it this way on-screen so if we want to set this color for a single button how would we do that well let's dive into the way that this gets resolved at runtime so we have button defined in layout XML that gets inflated in the

button class if you watch the demystifying themes and styles talk that Chris Bane's and I gave two years ago you have a complete understanding of how this works if you haven't watched that go watch it the important part is that the button style that you see here is

pulled from the theme that the theme of the context in which the button is inflated so relevant buttons style attribute here at the bottom of the screen next where is that button style defined it is defined on the material theme if we have not redefined it otherwise so

the default value there that you'll see in themes themes material XML is widget material button where do we find the definition for widget material button over in styles material so we can see here the background is defined to be this button default material drawable we'll also notice that

right below that bordered ink button style we have a colored border ding button style which if we've looked over the material spec we realized this probably going to be a little bit closer because it provides a color in the button so let's dive into the background that's used

there to see what gets pulled from our theme and what we might be able to change in the button color material XML you'll notice the XML file names match up exactly with the drawable names so there's an easy chain that you can follow we have a shape it's

a rectangle it is colored with a tint which is our button colored background material this gets applied to the white color of the shape so it's got a solid white fill here so let's dig into that tint and see what's gonna be applied on top of that white

color it is our color accents so this is a color state list it is named button colored background material XML which is the exact name of the color that we were just looking at again a very clear line of indirection so where does this color accent come from

well because it's a theme attribute it's gonna come from whatever exists in our application theme as I mentioned that inherits from material and if we haven't redefined color accent to be anything else it will be the default teal so here all the levels of indirection that we've just

looked at some of the important ones are if we want to change the style for all buttons that get inflated that's our button style and the theme that we could set the button style that we're getting by default is widget material button we can change that to something

else like button dot colored in our theme if we wanted color buttons everywhere we can also change our color to accent which is what gets loaded by the colored button style so if we set that in our theme that gets used everywhere we'll see that color everywhere but

what we want to do is one button so what would happen if we set button style on our activity theme we would see color buttons everywhere we don't want to do that what would happen if we set it in the style attribute on our button in XML we

would see it only on that single button which is what we want but now we're getting the default teal color from our theme so how can we fix that well what if we set color accents on our activity theme now we're getting that blue button but we're also

getting blue switches and blue everything else that inherits color accent if you just do a search over the platform XML files for color accent you'll see it in a lot of places so instead we can set it in we could try setting it in layout XML you'll notice

that this does absolutely nothing because it's a theme attribute and you shouldn't try to set theme attributes directly in layout XML theme attributes get set in your theme so what we'll actually do is create a theme overlay as Nick was just talking about that sets just that color

and contains nothing else we will apply that to the button using Android theme in layout XML and we'll get what we wanted so back to Nick for more implementation yes so I said you should prefer theme and attributes where you can but to do so you kind of

need to know what is out there what exists and honestly I don't have a great answer for this for you other than looking through the Atlas file of this is from the Android platform or from app compat or material components so looking through these they're not that long

you can see what is available for you that you can reference rather than hard coding conversely you can look at some of the common themes like themes that material and see which and theme attributes they set and as such you are able to reference or override yourself so

it's good to kind of have a look through these and get an idea of what's out there one note is that you might see that some theme attributes are kind of double defined so the platform defines a Android you know color control highlight and then app compat defines

its own in order to provide backward-compatible functionality so which to use basically the answer is always if there is one defined in the libraries like app compat or material Capone's prefer that because they all tend to set the platform one for you and then be available for backwards

compatibility and so on you can of course refer to these three match boots in code you're using something like this where we're doing obtain some attributes to get ahold of it and then using K T X's get color or fro to make it a little bit more convenient

so so far we've talked about using platform few match boots and you absolutely should but you can also create your own and you should do that as well to make your applications morpheme able let's walk for example of what this looks like so here from the dev summit

application we have two screens which display very similarly else list of sessions in the both the schedule and on speaker details they only differ in basically the how far and some space of the left and the keyline essentially that we wanted to align it to one needs to

leave room for the sticky ahead of time things and so to accomplish this we defined our own theme attribute so here this is in artists file called session list key line and then in the different activity themes for those two screens we can provide different dimension values for

that key line and then we just have to have a single layout which references that and that theme attribute using the question mark atra syntax in order to vary it without having to create separate layouts which we then have to maintain in another place that theming comes in

to the massive handiness is in teaming drawables so we looked an example from the platform button about how from API 20 21 onwards all platform drawable support tints and tint modes so here we are applying their color button normal you can also do this in in vectors where

they support and theme attributes both for tints as well as for fills and strokes and so you can use this not just for 21 words but in the back was compatible library as well and if you need to apply tints in the backwards compatible way to exist built

on prior to 21 you can use drawable compact like this in order to set some tints on existing drawable drawable compact also offers an override which lets you set a tint list a color state list to be applied and which is something we have learned is to be

extremely handy so like the example we left out before you can define a single color state this which provides these different tints and/or colors for different states so this example is taken from text primary and one of the things I love about color statelets as some of the

improvements that arrived in marshmallow 23 and which allowed you to separate out the color and an alpha component and why this is great is because this really protects you against that explosion of like 20 different asset ease of black you might have in your colors file by actually

separating out the kind of the color information from the Alpha information allows you to define more specifically what you want so here we're saying say this is a light screen so color foreground will be dark you can say the text should be black and it should have these

different alphas depending if it's enabled or disabled in these two here so you don't have to have to find all these different combinations you defined specifically the semantically named things like disabled alpha primary content alpha and foreground possessed separately and then they get combined by the color state

list at runtime one thing to note is I've actually cheated here and changed to the Android alpha 2 alpha because app compat backports this new function new features added to color cyclist but it requires you to use app alpha and one thing to note is that the alpha

channel of the the color and the alpha are combined and multiplied so be careful don't specify don't do this essentially if you specialize this is like say a 50% white text if you don't speak X and a 50% alpha you'll end up with a 25% alford white so

you probably want to refer to colors which have full alpha and then and only supply variable alphas by the Alpha Channel separately and like I said I've compat bakbox this so use app compat resources to inflate that in order to get this backwards compatible behavior and then you

can apply those and to draw balls so overall if you apply this theming and you can get to something a state like this and so on the left these look quite similar but on the left we have the Google i/o app and which we fork to create the

android dev summit application and to reefing it to fit in with the and the look and feel of this conference rather than io this is basically the diff essentially we just had to change a few of these semantically named colors and if we go back in this ripples

outwards to all the components so the fab changes the bottom nav changes some of the tints on drawables changes the style color changes like think about if your product manager comes to you and says hey the company's had a rebrand and we're changing all the colors wouldn't you

rather just have a tip that looked like this rather than trying to go through every you know layout XML or colors file and work out which color is which and where it's used and then can I change this and where is it going to effect you really want

to like limit the changes to these semantic or semantic names so it's a kind of summary of this and really really like team attribute all the things essentially use them as it's kind of like protection and you should probably like push that kind of semantic system back upwards

to your designers so they're kind of giving you values that work with this in your layout xml's prefer that for you Matt repeat syntax the question about Actress in tax or be care when you're right you're not writing that thinking is this a smell should I be doing

something else and with your drawables think about using tints so to protect yourself against these changes down the line just think if like all these are those draw balls have been pings and said I had to you know we had a rebrand am I going to have to

completely generate all these pings again with a new color into which is already baked into it it can all that don't do that use tints instead basically if every time you use a PNG like think should this be a PNG is this going to be usable like or

tinted later maybe prefer of that do prefer vectors pretty much the only time you should be using PNG is for nine patches so that's a summary protect yourself using semantic names and fema tributo and have fun with themes and styles [Applause] [Music]


See More Android:

Hãy bình luận đầu tiên

Để lại một phản hồi

Thư điện tử của bạn sẽ không được hiện thị công khai.