Fonts, Emoji and Text Using Support Libraries
CC Attribution 3.0 Unported:
You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal purpose as long as the work is attributed to the author in the manner specified by the author or licensor.
Singh, Anita
Beginner / APIs / Talk Android Oreo introduced exciting text changes that make it easier to use custom fonts, communicate with emojis, reduce APK size, and expand or contract textviews dynamically. Luckily, the Support Libraries from v26 onwards allow us to implement these features with backwards compatibility. In this talk, you will learn how to implement these text changes with the help of the Support Libraries, and their limitations. You will also learn about how they are natively implemented by the framework versus the Support Libraries. At the end of this session, you will have an increased understanding of the inner workings of Fonts in XML, Downloadable Fonts, EmojiCompat and autosizing of TextViews, as well as be ready to update your apps with them without the fear of the unknown!
 Hi everyone, welcome to the last talk of the day in this cupcake room. My name is Anita Singh. I am based out of San Francisco where I work for an early stage startup called Winnie, which is an affer parents. But today I'm here to talk to you about fonts, emoji and text. We're going to learn how to implement them with backwards compatibility, but we're also going to learn how they work internally, which is actually quite interesting. So if you use text in your app at all, you're in the right place. Something worth noting is that the support library is now repackaged as Android X, which is part of Jetpack. And here is a dancing cupcake to honor this room, but also it is the end of the day, so hopefully this will help wake you up. If you need to stretch or anything, now is a good time. And assuming the cupcake has woken you up, we're going to talk about changes that were introduced with support library 26 plus. We're going to learn how to implement custom fonts using fonts in XML and downloadable fonts. How to future proof emojis using emoji compat and how to have beautiful readable text using text view auto sizing. So of course, the fun always begins in your build.gradle file. Make sure to have either the support library or the Android X dependency in there and make sure it matches the appropriate compile SDK version for things to go smoothly. And the first topic that we're going to talk about is fonts in XML, which really makes it easy to implement custom fonts in our app. What it is, is you can add your.ttf custom font files to a font resource directory under resources, and you can refer to it with the res slash font or add font or r.font tag, just like you would for any resource type. So now you can refer to fonts in your XML layouts, which is really convenient. Another thing you can add to the font resource directory is something called a font family file. It sets up the relationship between styles and weights of fonts. So for example, typically when you use a font, you have a lot of different weights. I'm going to use Lotto as an example, which is a Google font. So in the case of Lotto, you have Lotto black, Lotto semi-bold, Lotto bold, and you don't want to refer to five, six different custom fonts all throughout your layout files. So this is where font family files are really helpful because you can set the relationship between the weight and the style, and you can just use the font family all over your layout file. You don't have to use different custom fonts, which is really convenient. And so why do we need fonts in XML? If you've ever used a custom font, you've probably used something like calligraphy or font binding, which are really helpful third-party libraries, or you've done something like this where you have a custom text view, and all you're doing in this custom text view is you're setting the font in the constructor, and then you use this custom text view all throughout your layout files, which is not fun. That is a lot of drama just to use custom fonts, having to use custom text views everywhere, or having third-party dependencies, but that is not the case anymore thanks to fonts in XML. So how does it work? It essentially works using apt and appcompat. Here apt stands for the Android asset packaging tool. So when you compile with SDK 26 and above, we use Android Oreo's version of apt, which understands fonts and is able to bundle them into resources, and then the support library is able to read the attributes through the appcompat layout inflation process. So for example, this is a beautiful, beautiful stack trace. Of course, as developers, we love our stack traces, but the reason I put this here is because you can see exactly what's going on right from when you do set content view in your appcompat activity. As you can see here, it goes set content view, goes to layout inflator, then appcompat text helper all the way up to typeface compat API, or typeface compat. And typeface compat has different implementations, so typeface compat API 21, 26, and all these different implementations essentially load the typeface from the font resource file for you. So it's using apt, the Android asset packaging tool, and appcompat that Android was able to add a new resource type with it being backwards compatible, which is pretty cool. So we know how it works. How do we actually use it? There's a handy font family tag that you can use, and it can refer to either a font family or just a font. And this next part is my favorite. Now all that you need to do in order for all your text views in your app to have your custom font is just one line of XML in your app theme. No more third-party dependencies, no more custom text views all throughout your app. So as you can see, this is a pretty big improvement when it comes to custom fonts in terms of support straight from Android. And there's also an API you can use, resourcescompat.getfont to load it programmatically. Great. So it's not Android development without its gotchas. Make sure to use both the Android and the app namespace in your font family file for it to work in all versions of Android, so basically pre-o and after-o. And you have to use app-compad components like app-compad activity, et cetera, because it works using the app-compad layout inflation process. And some useful reading. This next topic, downloadable fonts also helps make implementing custom fonts really easy for us. Downloadable fonts essentially helps apps share fonts with each other. So how it works is different apps can request for fonts from a central font provider application using the fonts contract compact API. And what the font provider does is it looks into the cache to see if there's the font. If it is, great. If it's not, then it essentially downloads it from the internet, caches it, and now the different apps can use it. The publicly available font provider is the Google font provider, which lives in Google Play services and currently gives you access to around 800 plus Google fonts. And so that's what I'm going to be using going forward in the examples. So why do we need downloadable fonts? It helps us reduce our APK size because you don't have to bundle fonts in your app anymore, sometimes that can take up to 7MB. And a reduced APK or app bundles can have a huge impact on your app installs. And because different apps are sharing fonts, it results in less usage of precious memory, disk space, and cellular data because can you imagine how many Roboto font files are on your phone right now? Roboto, Lotto, or any popular font, you have multiple copies of those font files in your phone right now. And downloadable fonts can help eliminate those duplicates. So if your users understood how much data and space you were saving them, they would be happy like that emoji with sunshine and rainbows. And that should be the goal of these developers to make our users feel that way. So downloadable fonts is a good option. So how do we get it set up? One way to do it is programmatically using the support library. You can set up a font request where you pass in where you're going to get the font from, which in this case refers to Google Play Services. You pass in the name of the font, which in this case is Lotto, and you pass in the certificates, which avoids getting fonts from unknown sources, which is great. And then you have the callback, the font request callback with the success and failure callbacks. And then in the success callback, you want to set the typeface on the text view. And then you definitely do not want the download to happen on the main thread. And so you need to set up a handler. And then you can put all of this together by calling fontscontractcompact.requestfont, where you pass in the font request, the callback, and the handler. And when the font is retrieved either from the cache or from the Internet, you will get the success or failure callback, and you can deal with each that way. So what you just saw is cool, but you probably don't want to do that in every activity or fragment or custom view group. And that's why I think using Android Studio with fonts in XML is a better way to do it. Open up the graphical editor, find the font family attribute, scroll down to more fonts, and then select the Google font that you're looking for. Again, you will mostly only see Google fonts, and select create downloadable font. If you do these steps, three files get downloaded automatically via Android Studio. The first being the font family file. However, in this case, the attributes are for downloading the fonts versus what you saw earlier, which were for bundled fonts. Something worth pointing out is that there is a font provider fetch strategy which can either be blocking or async. Async is the default. You might be wondering, why would I ever use blocking? Well, there could be uses for it. For example, let's say you have a custom view that is not a text view, and it's drawing some text, and you want to set the typeface on it. So one way to do that would be to implement the font family property so that you can set it in XML. But if you did that and you used async, it would actually fail. And the reason is because the framework, when it fetches the fonts, it sets the text view typeface and the callbacks automatically when you apply the font family attribute to a text view. But in this case, you are not applying it to a text view so that callback will fail. So blocking fixes it because it waits to get the font. But if you still want to do it asynchronously, you can. You will just have to do it programmatically using the method I just showed you. Also if let's say you are working with fonts in XML and you change it to blocking and it suddenly works, that's a signal that there is something wrong with your callbacks so you can also use it for debugging. The second file that is downloaded by Android Studio is font underscore certs.xml, which contain your prod and dev certificates. And this essentially helps us from not getting fonts from unknown sources, which would have been a huge security vulnerability if we could do that. And the third file that is downloaded is preload fonts.xml. This essentially lists out the fonts that need to be preloaded. So what this does is this helps the app preload or fetch the font as soon as the app is launched so that by the time the first layout pass happens, you can see the font. Because otherwise you would likely see like five seconds of rubato before you see your custom font. And that is not a good experience. So using preloaded fonts, it reduces your chance of seeing the five seconds of rubato before you see your custom font. It can still happen, but it becomes much rarer. And this file needs to be referenced in your Android manifest for it to work with the preload fonts metadata. Sorry, for it to work. Android Studio does automatically add this to your manifest file. So just check to make sure it's there. And once this is done, you're ready to apply the downloaded fonts to your layouts. And you would do it the same way you would earlier where you can just set the font family in your app theme. And all the custom text views in your app will have this font applied to it. So pretty simple. Android Studio basically generates everything you need, and you just need to apply it and just check that things went well. All right. So what are the gotchas? You need to use Android Studio 3.0 and above if you want to generate the font files, which I hope people are using by now. It does depend on Google Play services if you're using the Google font provider, version 11 and above. I initially thought this might be a deal breaker, but Google Play does a pretty good job of keeping Google Play services up to date. I think it updates it every three weeks or so. But that being said, there will definitely be users who won't have Google Play services or will have outdated Google Play services. So my recommendation there is to use styles in your XML because you don't want them to see unstyled text. If all of your styling depends on your custom fonts, then when they have it all in Roboto, they won't see bold. They won't see italic if you're using Lado underscore italic, Lado underscore bold. So make sure to use styling in your text so the people without Google Play services or outdated Google Play services can still see styled text. There is a crash with a certain version of support library. It happens under low Internet connectivity when you launch the app. So just if you haven't updated yet, this is a good one to skip if you're using downloadable fonts. And you can use, if you use resources, compact.get font, it might throw resources not found exception because your font may not have been downloaded yet. So make sure to handle this. What I do is if this is thrown, I just initiate the download programmatically in that case. But it's really up to you how you want to deal with it. If you are using a custom font that is not a Google font, then you'll have to write your own font provider, which doesn't have a lot of documentation yet. However, Twitter used this for twi emoji. So it is possible, but you'd have to sort of go down your own road. So I think this is worth it if you are Adobe or Uber and you have a custom font that you want to share among different suite of your apps. But if you're the only one using your own custom font, it's not that big of a benefit to the user. But fonts are very persistent once they are downloaded, which is great for users, but a little annoying if you're a developer. Clearing Google Play services will not clear it. Clearing the app space won't clear it. You actually need access to a router device where you go to that position in the directory structure and you have to delete the font files and also clear Google Play services and also clear your app space. Not only if you do that, can you retest the download. So if you want to do that, you can have fun with it. And here are my links. And this next topic is Emoji Compat, which can be used in conjunction with downloadable fonts and also who doesn't love emojis. Emoji Compat essentially gives us access to backward compatible emoji support. And it helps us essentially prevent seeing the squares of sadness that you see instead of an emoji. It is very sad when you see that because you don't know what your friend meant. Was your friend being funny, sarcastic, sad? You'll never know. And so this square of sadness is known as tofu and we want to avoid people seeing this as much as possible. And that's essentially the goal of Emoji Compat. Why do we need it? Well, this way, users up to API 19 can see the latest emojis without upgrading their operating systems, which is huge because we know that Android people are not great at updating their operating system. And sometimes the hardware just doesn't let you. And so this way, even I think KitKat users can see head exploding emojis, unicorns, tacos, and most importantly, the updated hamburger and beer emoji. If you saw the Google I.O. live stream or were there, the CEO opened Google I.O. with the announcement of fixing the hamburger emoji on Android. So now the cheese is on top of the meat and not below the meat. And apparently this was a big deal that it needed to be in the Google I.O.'s keynote. And so it's because of Emoji Compat that users up to API 19 can see this new hamburger emoji. So that's pretty cool. So great. How does it work? Emojis are represented by Unicode code points. And what Emoji Compat essentially does is it identifies the Unicode code points that represent emojis. And it checks to see if the system can render it. If it can, great. If it can't, then it replaces the Unicode code point with something called Emoji spans. Emoji spans are nothing but replacement spans. And replacement spans can replace care sequences with any customization. And in this case, Emoji span has an Emoji metadata object, which has information to render the Emoji glyph using the support font. So it's using this Emoji span replacement technique and the support font that Android, but Emoji Compat is able to provide backwards compatible Emoji support across operating systems. And so how do we get started with it? One way is to do it using downloadable fonts. The first dependency here is for regular text views. And the second one here is for app-compat text views and edit text, et cetera. And again, you have your font request, which is what we saw with downloadable fonts, except that over here we use the Nauticaler Emoji Compat, which contains, which is the font that allows us to have the latest emojis in Android. And then you have the font request Emoji Compat config, which has the uninitialized and onfailed callbacks. And then you call, oh, sorry. And then that's highlighted. And then you call Emoji Compat.init with the config. And you want this to happen as soon as possible in your app lifecycle. So I put this in the applications on create. And that seems to have been working fine. So just as we saw preloading for downloadable fonts, there's also a preloading for Emoji Compat. There's this handy font provider request tag that you can use that Google Play services will read either at install time or at update and will initiate the font download then. And this is great because by the time you launch your app, you will likely have the emojis ready instead of seeing five seconds of tofu and then suddenly seeing your emojis. So this helped, again, it's not guaranteed, but it really reduces the likelihood of that happening. Another way of using Emoji Compat is through bundled fonts. You add in your dependency and then you use bundled Emoji Compat config. And then you have these optional properties that you could also use with downloadable fonts. But you can set this set replace all to true, which essentially tells Emoji Compat to replace every emoji that it finds with the one in the support font. So this way, you can have consistent looking emojis across all devices. So if you don't want your users to see ugly Samsung emojis, they don't have to. They can have consistent emojis this way, which is pretty cool. One thing, though, it does add around 7MB to your APK and you have to update your app at least once a year to get the latest emoji, but it does not depend on Google Play services. So depending on your user demographic, do what's best for your app. Another way, so now we have it configured, so now we can start using Emoji Compat. One way is to use the out of box components like Emoji TextView, Emoji AppCompat Edit Text, Emoji Button. So each of these have their appCompat variations and they will render emojis out of the box. But what if you have other widgets, like let's say a text input edit text that you want it to render an emoji? And you can use something called the Emoji Compat.get.process, or if you have a custom text view or custom edit text, you have these helper classes called Emoji TextView Helper and Emoji Edit Text Helper. I'm going to go over the first one right now and I've included code samples for the second one in the slides. So let's say you want your text input edit text to render emojis, you listen on the call back from when Emoji Compat is initialized, and in the call back you call Emoji Compat.get.process and you pass in the string. So what this does is it goes through the whole Emoji Span replacement technique and now text input edit text are able to, at least this end text input edit text is able to render emojis. This only works for widgets that can render spanned instances. So for example, if you were going to do it for the hint of an edit text, it would not work. And definitely unregister your callbacks. All right. So what our gotchas, it is API 19 plus. You can still use it if you're supporting lower operating systems. It just won't render the latest emojis. The process only works on widgets that can render spanned instances, so others may not be able to render the emojis. Make sure to handle the failure cases. So it's easy to set the text on initialized and not do anything and on failed, but that way the user won't see text at all. Seeing tofu is better than not seeing text. So make sure to handle the failure cases wherever you're using Emoji Compat in the code. And if you're using it in conjunction with downloadable fonts, all of the gotchas apply like being dependent on Google Play services. And more reading. All right. This last topic was also introduced with support library 26 and above. It's text view auto sizing. It essentially allows text views to expand or contract dynamically based on its bounds. So as you can see here, it's expanding on contracting as it gets bigger and smaller. And it's based on constraints. Why do we need this? Material design has since forever recommended using dynamic text types over truncated text or compromising on text size. So as you can see here, the shorter the text, the bigger it is, the more readable it is, and the longer the text, it sort of auto sizes to fit in. So this way you don't have to truncate text. You don't have to sort of pick like a middle ground text that probably works for everyone. This can just auto size and do the best it can, which is great. So how does it work? Whenever text is set or changed or whenever you set auto sizing using text view Compat, there is an auto size method that lives in the app Compat text view classes, which essentially runs binary search calculations. So it uses binary search to figure out the largest text size that can fit in the bounds. And so it uses this a lot to figure out to set the text size when it's auto sizing. How do we use it? There is a handy auto size text type tag that you can use or attribute, and you can either set it as uniform or none, none being the default. And once you set that, you can optionally specify the min size, the max size, and the step granularity. And then you can also set preset sizes. So you can give it a list of sizes and it will pick the largest that it can fit in the bounds. But for this to work, you have to first set the auto size text type as uniform, otherwise it wouldn't work. And you can also do it programmatically using text view Compat. You can pass in the auto size text type, the auto size step granularity, and also the preset sizes. These are ridiculously long method names, like what is this objective C? But I mean, it does the job and I guess that's what matters. And here are the defaults if you don't set the granularity in the min and the max. So it's 12, 1, 12, and 1. All right. Last slide. It's API 14 plus, which I think is fine. Do not use wrap content when dealing with auto sizing. Either use match parent or have a set text size. And the reason is because it needs constraints to know how much it can expand or contract. So if you use wrap content, you'll probably have unexpected results. In my case, it just didn't work. And text view auto sizing is a little bit of a new world. You might expect a word to auto size to fit into one line, but instead it will split to the second line because it wants to fit the space, or if you have a text view and another text view right below it, because it expands uniformly, it can only be so big and so you might end up having more space. So definitely think of what the minute can be, what the max can be, and make sure to test those cases because it is a different world from wrap content, match parent. And if you're not using app component component, app compact activity, that's okay. You can just straight up use the app compact text view. And so this essentially wraps up the talk. I hope you'll take advantage of these features. Things like downloadable fonts and emoji compact can have a huge impact. Like the more apps use it, the bigger benefit it will be to the user. Think of the sunshine and the rainbows. That's how we want our users to feel. And I don't think we have time for questions. So I'll be hanging around if you have any questions. Yeah. Thank you so much to the organizers of dry con and enjoy the rest of your conference.
 Hi everyone, welcome to the last talk of the day in this cupcake room.  My name is Anita Singh.  I am based out of San Francisco where I work for an early stage startup called Winnie,  which is an affer parents.  But today I'm here to talk to you about fonts, emoji and text.  We're going to learn how to implement them with backwards compatibility, but we're also  going to learn how they work internally, which is actually quite interesting.  So if you use text in your app at all, you're in the right place.  Something worth noting is that the support library is now repackaged as Android X, which  is part of Jetpack.  And here is a dancing cupcake to honor this room, but also it is the end of the day, so  hopefully this will help wake you up.  If you need to stretch or anything, now is a good time.  And assuming the cupcake has woken you up, we're going to talk about changes that were  introduced with support library 26 plus.  We're going to learn how to implement custom fonts using fonts in XML and downloadable fonts.  How to future proof emojis using emoji compat and how to have beautiful readable text using  text view auto sizing.  So of course, the fun always begins in your build.gradle file.  Make sure to have either the support library or the Android X dependency in there and make  sure it matches the appropriate compile SDK version for things to go smoothly.  And the first topic that we're going to talk about is fonts in XML, which really makes  it easy to implement custom fonts in our app.  What it is, is you can add your.ttf custom font files to a font resource directory under  resources, and you can refer to it with the res slash font or add font or r.font tag, just  like you would for any resource type.  So now you can refer to fonts in your XML layouts, which is really convenient.  Another thing you can add to the font resource directory is something called a font family  file.  It sets up the relationship between styles and weights of fonts.  So for example, typically when you use a font, you have a lot of different weights.  I'm going to use Lotto as an example, which is a Google font.  So in the case of Lotto, you have Lotto black, Lotto semi-bold, Lotto bold, and you don't  want to refer to five, six different custom fonts all throughout your layout files.  So this is where font family files are really helpful because you can set the relationship  between the weight and the style, and you can just use the font family all over your  layout file.  You don't have to use different custom fonts, which is really convenient.  And so why do we need fonts in XML?  If you've ever used a custom font, you've probably used something like calligraphy or  font binding, which are really helpful third-party libraries, or you've done something like this  where you have a custom text view, and all you're doing in this custom text view is you're  setting the font in the constructor, and then you use this custom text view all throughout  your layout files, which is not fun.  That is a lot of drama just to use custom fonts, having to use custom text views everywhere,  or having third-party dependencies, but that is not the case anymore thanks to fonts in  XML.  So how does it work?  It essentially works using apt and appcompat.  Here apt stands for the Android asset packaging tool.  So when you compile with SDK 26 and above, we use Android Oreo's version of apt, which  understands fonts and is able to bundle them into resources, and then the support library  is able to read the attributes through the appcompat layout inflation process.  So for example, this is a beautiful, beautiful stack trace.  Of course, as developers, we love our stack traces, but the reason I put this here is  because you can see exactly what's going on right from when you do set content view in  your appcompat activity.  As you can see here, it goes set content view, goes to layout inflator, then appcompat text  helper all the way up to typeface compat API, or typeface compat.  And typeface compat has different implementations, so typeface compat API 21, 26, and all these  different implementations essentially load the typeface from the font resource file for  you.  So it's using apt, the Android asset packaging tool, and appcompat that Android was able to  add a new resource type with it being backwards compatible, which is pretty cool.  So we know how it works.  How do we actually use it?  There's a handy font family tag that you can use, and it can refer to either a font family  or just a font.  And this next part is my favorite.  Now all that you need to do in order for all your text views in your app to have your custom  font is just one line of XML in your app theme.  No more third-party dependencies, no more custom text views all throughout your app.  So as you can see, this is a pretty big improvement when it comes to custom fonts in terms of  support straight from Android.  And there's also an API you can use, resourcescompat.getfont to load it programmatically.  Great.  So it's not Android development without its gotchas.  Make sure to use both the Android and the app namespace in your font family file for  it to work in all versions of Android, so basically pre-o and after-o.  And you have to use app-compad components like app-compad activity, et cetera, because  it works using the app-compad layout inflation process.  And some useful reading.  This next topic, downloadable fonts also helps make implementing custom fonts really easy  for us.  Downloadable fonts essentially helps apps share fonts with each other.  So how it works is different apps can request for fonts from a central font provider application  using the fonts contract compact API.  And what the font provider does is it looks into the cache to see if there's the font.  If it is, great.  If it's not, then it essentially downloads it from the internet, caches it, and now the  different apps can use it.  The publicly available font provider is the Google font provider, which lives in Google  Play services and currently gives you access to around 800 plus Google fonts.  And so that's what I'm going to be using going forward in the examples.  So why do we need downloadable fonts?  It helps us reduce our APK size because you don't have to bundle fonts in your app anymore,  sometimes that can take up to 7MB.  And a reduced APK or app bundles can have a huge impact on your app installs.  And because different apps are sharing fonts, it results in less usage of precious memory,  disk space, and cellular data because can you imagine how many Roboto font files are  on your phone right now?  Roboto, Lotto, or any popular font, you have multiple copies of those font files in your  phone right now.  And downloadable fonts can help eliminate those duplicates.  So if your users understood how much data and space you were saving them, they would  be happy like that emoji with sunshine and rainbows.  And that should be the goal of these developers to make our users feel that way.  So downloadable fonts is a good option.  So how do we get it set up?  One way to do it is programmatically using the support library.  You can set up a font request where you pass in where you're going to get the font from,  which in this case refers to Google Play Services.  You pass in the name of the font, which in this case is Lotto, and you pass in the certificates,  which avoids getting fonts from unknown sources, which is great.  And then you have the callback, the font request callback with the success and failure callbacks.  And then in the success callback, you want to set the typeface on the text view.  And then you definitely do not want the download to happen on the main thread.  And so you need to set up a handler.  And then you can put all of this together by calling fontscontractcompact.requestfont,  where you pass in the font request, the callback, and the handler.  And when the font is retrieved either from the cache or from the Internet, you will get  the success or failure callback, and you can deal with each that way.  So what you just saw is cool, but you probably don't want to do that in every activity or  fragment or custom view group.  And that's why I think using Android Studio with fonts in XML is a better way to do it.  Open up the graphical editor, find the font family attribute, scroll down to more fonts,  and then select the Google font that you're looking for.  Again, you will mostly only see Google fonts, and select create downloadable font.  If you do these steps, three files get downloaded automatically via Android Studio.  The first being the font family file.  However, in this case, the attributes are for downloading the fonts versus what you  saw earlier, which were for bundled fonts.  Something worth pointing out is that there is a font provider fetch strategy which can  either be blocking or async.  Async is the default.  You might be wondering, why would I ever use blocking?  Well, there could be uses for it.  For example, let's say you have a custom view that is not a text view, and it's drawing  some text, and you want to set the typeface on it.  So one way to do that would be to implement the font family property so that you can set  it in XML.  But if you did that and you used async, it would actually fail.  And the reason is because the framework, when it fetches the fonts, it sets the text view  typeface and the callbacks automatically when you apply the font family attribute to a text  view.  But in this case, you are not applying it to a text view so that callback will fail.  So blocking fixes it because it waits to get the font.  But if you still want to do it asynchronously, you can.  You will just have to do it programmatically using the method I just showed you.  Also if let's say you are working with fonts in XML and you change it to blocking and it  suddenly works, that's a signal that there is something wrong with your callbacks so  you can also use it for debugging.  The second file that is downloaded by Android Studio is font underscore certs.xml, which  contain your prod and dev certificates.  And this essentially helps us from not getting fonts from unknown sources, which would have  been a huge security vulnerability if we could do that.  And the third file that is downloaded is preload fonts.xml.  This essentially lists out the fonts that need to be preloaded.  So what this does is this helps the app preload or fetch the font as soon as the app is launched  so that by the time the first layout pass happens, you can see the font.  Because otherwise you would likely see like five seconds of rubato before you see your  custom font.  And that is not a good experience.  So using preloaded fonts, it reduces your chance of seeing the five seconds of rubato  before you see your custom font.  It can still happen, but it becomes much rarer.  And this file needs to be referenced in your Android manifest for it to work with the preload  fonts metadata.  Sorry, for it to work.  Android Studio does automatically add this to your manifest file.  So just check to make sure it's there.  And once this is done, you're ready to apply the downloaded fonts to your layouts.  And you would do it the same way you would earlier where you can just set the font family  in your app theme.  And all the custom text views in your app will have this font applied to it.  So pretty simple.  Android Studio basically generates everything you need, and you just need to apply it and  just check that things went well.  All right.  So what are the gotchas?  You need to use Android Studio 3.0 and above if you want to generate the font files, which  I hope people are using by now.  It does depend on Google Play services if you're using the Google font provider, version 11  and above.  I initially thought this might be a deal breaker, but Google Play does a pretty good job of  keeping Google Play services up to date.  I think it updates it every three weeks or so.  But that being said, there will definitely be users who won't have Google Play services  or will have outdated Google Play services.  So my recommendation there is to use styles in your XML because you don't want them to  see unstyled text.  If all of your styling depends on your custom fonts, then when they have it all in Roboto,  they won't see bold.  They won't see italic if you're using Lado underscore italic, Lado underscore bold.  So make sure to use styling in your text so the people without Google Play services or  outdated Google Play services can still see styled text.  There is a crash with a certain version of support library.  It happens under low Internet connectivity when you launch the app.  So just if you haven't updated yet, this is a good one to skip if you're using downloadable  fonts.  And you can use, if you use resources, compact.get font, it might throw resources not found  exception because your font may not have been downloaded yet.  So make sure to handle this.  What I do is if this is thrown, I just initiate the download programmatically in that case.  But it's really up to you how you want to deal with it.  If you are using a custom font that is not a Google font, then you'll have to write your  own font provider, which doesn't have a lot of documentation yet.  However, Twitter used this for twi emoji.  So it is possible, but you'd have to sort of go down your own road.  So I think this is worth it if you are Adobe or Uber and you have a custom font that you  want to share among different suite of your apps.  But if you're the only one using your own custom font, it's not that big of a benefit  to the user.  But fonts are very persistent once they are downloaded, which is great for users, but  a little annoying if you're a developer.  Clearing Google Play services will not clear it.  Clearing the app space won't clear it.  You actually need access to a router device where you go to that position in the directory  structure and you have to delete the font files and also clear Google Play services  and also clear your app space.  Not only if you do that, can you retest the download.  So if you want to do that, you can have fun with it.  And here are my links.  And this next topic is Emoji Compat, which can be used in conjunction with downloadable  fonts and also who doesn't love emojis.  Emoji Compat essentially gives us access to backward compatible emoji support.  And it helps us essentially prevent seeing the squares of sadness that you see instead  of an emoji.  It is very sad when you see that because you don't know what your friend meant.  Was your friend being funny, sarcastic, sad?  You'll never know.  And so this square of sadness is known as tofu and we want to avoid people seeing this  as much as possible.  And that's essentially the goal of Emoji Compat.  Why do we need it?  Well, this way, users up to API 19 can see the latest emojis without upgrading their  operating systems, which is huge because we know that Android people are not great at  updating their operating system.  And sometimes the hardware just doesn't let you.  And so this way, even I think KitKat users can see head exploding emojis, unicorns, tacos,  and most importantly, the updated hamburger and beer emoji.  If you saw the Google I.O.  live stream or were there, the CEO opened Google I.O. with the announcement of fixing  the hamburger emoji on Android.  So now the cheese is on top of the meat and not below the meat.  And apparently this was a big deal that it needed to be in the Google I.O.'s keynote.  And so it's because of Emoji Compat that users up to API 19 can see this new hamburger emoji.  So that's pretty cool.  So great.  How does it work?  Emojis are represented by Unicode code points.  And what Emoji Compat essentially does is it identifies the Unicode code points that  represent emojis.  And it checks to see if the system can render it.  If it can, great.  If it can't, then it replaces the Unicode code point with something called Emoji spans.  Emoji spans are nothing but replacement spans.  And replacement spans can replace care sequences with any customization.  And in this case, Emoji span has an Emoji metadata object, which has information to  render the Emoji glyph using the support font.  So it's using this Emoji span replacement technique and the support font that Android,  but Emoji Compat is able to provide backwards compatible Emoji support across operating  systems.  And so how do we get started with it?  One way is to do it using downloadable fonts.  The first dependency here is for regular text views.  And the second one here is for app-compat text views and edit text, et cetera.  And again, you have your font request, which is what we saw with downloadable fonts, except  that over here we use the Nauticaler Emoji Compat, which contains, which is the font  that allows us to have the latest emojis in Android.  And then you have the font request Emoji Compat config, which has the uninitialized  and onfailed callbacks.  And then you call, oh, sorry.  And then that's highlighted.  And then you call Emoji Compat.init with the config.  And you want this to happen as soon as possible in your app lifecycle.  So I put this in the applications on create.  And that seems to have been working fine.  So just as we saw preloading for downloadable fonts, there's also a preloading for Emoji  Compat.  There's this handy font provider request tag that you can use that Google Play services  will read either at install time or at update and will initiate the font download then.  And this is great because by the time you launch your app, you will likely have the  emojis ready instead of seeing five seconds of tofu and then suddenly seeing your emojis.  So this helped, again, it's not guaranteed, but it really reduces the likelihood of that  happening.  Another way of using Emoji Compat is through bundled fonts.  You add in your dependency and then you use bundled Emoji Compat config.  And then you have these optional properties that you could also use with downloadable fonts.  But you can set this set replace all to true, which essentially tells Emoji Compat to replace  every emoji that it finds with the one in the support font.  So this way, you can have consistent looking emojis across all devices.  So if you don't want your users to see ugly Samsung emojis, they don't have to.  They can have consistent emojis this way, which is pretty cool.  One thing, though, it does add around 7MB to your APK and you have to update your app  at least once a year to get the latest emoji, but it does not depend on Google Play services.  So depending on your user demographic, do what's best for your app.  Another way, so now we have it configured, so now we can start using Emoji Compat.  One way is to use the out of box components like Emoji TextView, Emoji AppCompat Edit  Text, Emoji Button.  So each of these have their appCompat variations and they will render emojis out of the box.  But what if you have other widgets, like let's say a text input edit text that you want it  to render an emoji?  And you can use something called the Emoji Compat.get.process, or if you have a custom  text view or custom edit text, you have these helper classes called Emoji TextView Helper  and Emoji Edit Text Helper.  I'm going to go over the first one right now and I've included code samples for the second  one in the slides.  So let's say you want your text input edit text to render emojis, you listen on the call  back from when Emoji Compat is initialized, and in the call back you call Emoji Compat.get.process  and you pass in the string.  So what this does is it goes through the whole Emoji Span replacement technique and now text  input edit text are able to, at least this end text input edit text is able to render  emojis.  This only works for widgets that can render spanned instances.  So for example, if you were going to do it for the hint of an edit text, it would not  work.  And definitely unregister your callbacks.  All right.  So what our gotchas, it is API 19 plus.  You can still use it if you're supporting lower operating systems.  It just won't render the latest emojis.  The process only works on widgets that can render spanned instances, so others may not  be able to render the emojis.  Make sure to handle the failure cases.  So it's easy to set the text on initialized and not do anything and on failed, but that  way the user won't see text at all.  Seeing tofu is better than not seeing text.  So make sure to handle the failure cases wherever you're using Emoji Compat in the code.  And if you're using it in conjunction with downloadable fonts, all of the gotchas apply  like being dependent on Google Play services.  And more reading.  All right.  This last topic was also introduced with support library 26 and above.  It's text view auto sizing.  It essentially allows text views to expand or contract dynamically based on its bounds.  So as you can see here, it's expanding on contracting as it gets bigger and smaller.  And it's based on constraints.  Why do we need this?  Material design has since forever recommended using dynamic text types over truncated text  or compromising on text size.  So as you can see here, the shorter the text, the bigger it is, the more readable it is,  and the longer the text, it sort of auto sizes to fit in.  So this way you don't have to truncate text.  You don't have to sort of pick like a middle ground text that probably works for everyone.  This can just auto size and do the best it can, which is great.  So how does it work?  Whenever text is set or changed or whenever you set auto sizing using text view Compat,  there is an auto size method that lives in the app Compat text view classes, which essentially  runs binary search calculations.  So it uses binary search to figure out the largest text size that can fit in the bounds.  And so it uses this a lot to figure out to set the text size when it's auto sizing.  How do we use it?  There is a handy auto size text type tag that you can use or attribute, and you can either  set it as uniform or none, none being the default.  And once you set that, you can optionally specify the min size, the max size, and the  step granularity.  And then you can also set preset sizes.  So you can give it a list of sizes and it will pick the largest that it can fit in the  bounds.  But for this to work, you have to first set the auto size text type as uniform, otherwise  it wouldn't work.  And you can also do it programmatically using text view Compat.  You can pass in the auto size text type, the auto size step granularity, and also the preset  sizes.  These are ridiculously long method names, like what is this objective C?  But I mean, it does the job and I guess that's what matters.  And here are the defaults if you don't set the granularity in the min and the max.  So it's 12, 1, 12, and 1.  All right.  Last slide.  It's API 14 plus, which I think is fine.  Do not use wrap content when dealing with auto sizing.  Either use match parent or have a set text size.  And the reason is because it needs constraints to know how much it can expand or contract.  So if you use wrap content, you'll probably have unexpected results.  In my case, it just didn't work.  And text view auto sizing is a little bit of a new world.  You might expect a word to auto size to fit into one line, but instead it will split to  the second line because it wants to fit the space, or if you have a text view and another  text view right below it, because it expands uniformly, it can only be so big and so you  might end up having more space.  So definitely think of what the minute can be, what the max can be, and make sure to  test those cases because it is a different world from wrap content, match parent.  And if you're not using app component component, app compact activity, that's okay.  You can just straight up use the app compact text view.  And so this essentially wraps up the talk.  I hope you'll take advantage of these features.  Things like downloadable fonts and emoji compact can have a huge impact.  Like the more apps use it, the bigger benefit it will be to the user.  Think of the sunshine and the rainbows.  That's how we want our users to feel.  And I don't think we have time for questions.  So I'll be hanging around if you have any questions.  Yeah.  Thank you so much to the organizers of dry con and enjoy the rest of your conference.
_DCBerlin18_411_Singh_Fonts__Emoji_and_Text_Using__rzuzWFY3mOo_0_1475.png _DCBerlin18_411_Singh_Fonts__Emoji_and_Text_Using__rzuzWFY3mOo_1476_2123.png _DCBerlin18_411_Singh_Fonts__Emoji_and_Text_Using__rzuzWFY3mOo_2124_2603.png _DCBerlin18_411_Singh_Fonts__Emoji_and_Text_Using__rzuzWFY3mOo_2604_2879.png _DCBerlin18_411_Singh_Fonts__Emoji_and_Text_Using__rzuzWFY3mOo_2880_3575.png _DCBerlin18_411_Singh_Fonts__Emoji_and_Text_Using__rzuzWFY3mOo_3576_4883.png _DCBerlin18_411_Singh_Fonts__Emoji_and_Text_Using__rzuzWFY3mOo_4884_5771.png _DCBerlin18_411_Singh_Fonts__Emoji_and_Text_Using__rzuzWFY3mOo_5772_6191.png _DCBerlin18_411_Singh_Fonts__Emoji_and_Text_Using__rzuzWFY3mOo_6192_6779.png _DCBerlin18_411_Singh_Fonts__Emoji_and_Text_Using__rzuzWFY3mOo_6780_7043.png _DCBerlin18_411_Singh_Fonts__Emoji_and_Text_Using__rzuzWFY3mOo_7044_8447.png _DCBerlin18_411_Singh_Fonts__Emoji_and_Text_Using__rzuzWFY3mOo_8448_8987.png _DCBerlin18_411_Singh_Fonts__Emoji_and_Text_Using__rzuzWFY3mOo_8988_9635.png _DCBerlin18_411_Singh_Fonts__Emoji_and_Text_Using__rzuzWFY3mOo_9636_10331.png _DCBerlin18_411_Singh_Fonts__Emoji_and_Text_Using__rzuzWFY3mOo_10332_10403.png _DCBerlin18_411_Singh_Fonts__Emoji_and_Text_Using__rzuzWFY3mOo_10404_10631.png _DCBerlin18_411_Singh_Fonts__Emoji_and_Text_Using__rzuzWFY3mOo_10632_11867.png _DCBerlin18_411_Singh_Fonts__Emoji_and_Text_Using__rzuzWFY3mOo_11868_13355.png _DCBerlin18_411_Singh_Fonts__Emoji_and_Text_Using__rzuzWFY3mOo_13356_13583.png _DCBerlin18_411_Singh_Fonts__Emoji_and_Text_Using__rzuzWFY3mOo_13584_14123.png _DCBerlin18_411_Singh_Fonts__Emoji_and_Text_Using__rzuzWFY3mOo_14124_15815.png _DCBerlin18_411_Singh_Fonts__Emoji_and_Text_Using__rzuzWFY3mOo_15816_16235.png _DCBerlin18_411_Singh_Fonts__Emoji_and_Text_Using__rzuzWFY3mOo_16236_18539.png _DCBerlin18_411_Singh_Fonts__Emoji_and_Text_Using__rzuzWFY3mOo_18540_20159.png _DCBerlin18_411_Singh_Fonts__Emoji_and_Text_Using__rzuzWFY3mOo_20160_20495.png _DCBerlin18_411_Singh_Fonts__Emoji_and_Text_Using__rzuzWFY3mOo_20496_21371.png _DCBerlin18_411_Singh_Fonts__Emoji_and_Text_Using__rzuzWFY3mOo_21372_21647.png _DCBerlin18_411_Singh_Fonts__Emoji_and_Text_Using__rzuzWFY3mOo_21648_23399.png _DCBerlin18_411_Singh_Fonts__Emoji_and_Text_Using__rzuzWFY3mOo_23400_25823.png _DCBerlin18_411_Singh_Fonts__Emoji_and_Text_Using__rzuzWFY3mOo_25824_25895.png _DCBerlin18_411_Singh_Fonts__Emoji_and_Text_Using__rzuzWFY3mOo_25896_26087.png _DCBerlin18_411_Singh_Fonts__Emoji_and_Text_Using__rzuzWFY3mOo_26088_27011.png _DCBerlin18_411_Singh_Fonts__Emoji_and_Text_Using__rzuzWFY3mOo_27012_28511.png _DCBerlin18_411_Singh_Fonts__Emoji_and_Text_Using__rzuzWFY3mOo_28512_30083.png _DCBerlin18_411_Singh_Fonts__Emoji_and_Text_Using__rzuzWFY3mOo_30084_30563.png _DCBerlin18_411_Singh_Fonts__Emoji_and_Text_Using__rzuzWFY3mOo_30564_31715.png _DCBerlin18_411_Singh_Fonts__Emoji_and_Text_Using__rzuzWFY3mOo_31716_32591.png _DCBerlin18_411_Singh_Fonts__Emoji_and_Text_Using__rzuzWFY3mOo_32592_32771.png _DCBerlin18_411_Singh_Fonts__Emoji_and_Text_Using__rzuzWFY3mOo_32772_34115.png _DCBerlin18_411_Singh_Fonts__Emoji_and_Text_Using__rzuzWFY3mOo_34116_34667.png _DCBerlin18_411_Singh_Fonts__Emoji_and_Text_Using__rzuzWFY3mOo_34668_35387.png _DCBerlin18_411_Singh_Fonts__Emoji_and_Text_Using__rzuzWFY3mOo_35388_36515.png _DCBerlin18_411_Singh_Fonts__Emoji_and_Text_Using__rzuzWFY3mOo_36516_37799.png _DCBerlin18_411_Singh_Fonts__Emoji_and_Text_Using__rzuzWFY3mOo_37800_38507.png _DCBerlin18_411_Singh_Fonts__Emoji_and_Text_Using__rzuzWFY3mOo_38508_39503.png _DCBerlin18_411_Singh_Fonts__Emoji_and_Text_Using__rzuzWFY3mOo_39504_40331.png _DCBerlin18_411_Singh_Fonts__Emoji_and_Text_Using__rzuzWFY3mOo_40332_40859.png _DCBerlin18_411_Singh_Fonts__Emoji_and_Text_Using__rzuzWFY3mOo_40860_41279.png _DCBerlin18_411_Singh_Fonts__Emoji_and_Text_Using__rzuzWFY3mOo_41280_42119.png _DCBerlin18_411_Singh_Fonts__Emoji_and_Text_Using__rzuzWFY3mOo_42120_42263.png _DCBerlin18_411_Singh_Fonts__Emoji_and_Text_Using__rzuzWFY3mOo_42264_43931.png _DCBerlin18_411_Singh_Fonts__Emoji_and_Text_Using__rzuzWFY3mOo_43932_44843.png _DCBerlin18_411_Singh_Fonts__Emoji_and_Text_Using__rzuzWFY3mOo_44844_44852.png