What's new in Android Studio UI design and debugging tools (Google I/O'19)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[MUSIC PLAYING] VADIM CAEN: Good morning, everyone. Thank you for coming so early to our talk up, What's New in Android Studio, UI Design and Debugging Tools. Thank you. [APPLAUSE] I'm Vadim, from Android Studio, working on the design tools. JEROME GAILLARD: I'm Jerome, from the Android Studio team. JOE BAKER-MALONE: I'm Joe, from Android Studio team. ASHLEY ROSE: I'm Ashley, from Android Framework and JetPack. VADIM CAEN: All right. Before we start, a little word about product mobile. You've heard maybe yesterday that the Android Studio team has been focused on product mobile to improve the end-to-end user experience of Android Studio. Improving Android Studio is not just about fixes. It's also about improving how you use it, and filling any gaps that we might have identified. Our tool chain-- when it comes to design-- it's building new layout, building new navigation between this layout, managing your resources, and dealing with the inspection at runtime on your device. To go through this tool chain, we're going to go through a typical user journey, building the Google Trips application. And to start with, Jerome will talk about the Layout Editor and how to build the first layout that you see here. JEROME GAILLARD: Thank you, Vadim. So first of all, we're going to build the first screen of our Google Trips app, using the Layout Editor. Upon opening the Layout Editor, this is the kind of screen you're going to see. Here, it's just a blank layout. The first thing we're going to do is switch to blueprint mode, as it is faster, and it's just less distracting when trying to just build the constraints on your layout. You don't want to be just looking at what the components actually look like. I'm just going to-- from the palette-- just dragging all the components that I need for my layout, more or less in the definite place. Once I'm done with that comes the time to build the constraints. As a way to be a bit more efficient building constraints, I could build them one by one. But using the contextual menus, we can build several constraints in one go. For example here, I want to center the RecyclerView within the layout. One thing I can do is right clicking on the RecyclerView, and in the contextual menu there is the option of centering horizontally. What that does is it creates both a left and a right constraint in one click, ensuring that the RecyclerView will be centered. Once I'm done building all my constraints, this is what my layout looks like in the blueprint mode. Obviously, it doesn't really tell me right now if I built the right thing, compared to the design that I was given. So I'm going to go back to Design mode, and see what it looks like. In the Design mode, you can see that it looks not very much like the original design I was given. The reason for that is that the RecyclerView view is pretty much empty. As you know, RecyclerView usually get the data populated at runtime, but that's not very helpful when you're trying to build your layout and make sure that it displays correctly with the data that you're going to see. To solve that problem, you can use design [? tools ?] attribute. So design time attributes, you can simply-- in the RecyclerView-- use the contextual menu again, and the sample data picker, just like you see on screen. And from the sample data picker, you can pick one of the predefined templates that we provide for you for RecyclerView items. Here, I just picked the first one, the email client. Doing that creates a layout for that RecyclerView item, that email client card. And at the same time, it links it to your RecyclerView, so that in the Layout Editor it shows populated. Of course, we're not building any email client. What we want to build in the RecyclerView is those Trips card. So I'm going to edit that RecyclerView item that was created to be a Trip card. In the resource manager panel-- in the left hand side that you can see here, and that Vadim is going to present to you in much more detail-- I can simply first, rename my RecyclerView item to something more appropriate to my project, and then I can start editing it. Double clicking on the layout in the Resource Manager will simply open that layout in the Layout Editor. As you can see on screen, I pretty much have all the right components right there for my Trip card, like an ImageView, couple of tags views, but they're obviously not having the right constraints. So I'm going to start by deleting all the constraints, clicking that button in the toolbar. Once that's done, I'm going to just reorganize all those constraints. One issue here is that we have quite a few components overlapping each other in a small area. That can be a bit cluttered. And we've heard from you that in this situation, building constraints can be a bit difficult. It can be sometimes difficult to drag the constraint to the right target, on the right components-- especially when components are overlapping. So what we are now allowing to do is dragging the constraint directly onto any place in the component that you want to attach it to, and then a pop-up menu opens, asking you what type of constraint you want to set. It gets really interesting when you are dragging a constraint into a location that has overlapping component. In that situation, we are offering not only several types of constraint, but you can also select which of the overlapping components you want to attach that constraint to. And that should make it much easier to build constraint layouts in the cases where you have overlapping and small components. One final way that can be helpful for you to build constraints efficiently is using the componentry. So in the componentry, if you do multi selection of components-- like here, we selected two text views-- again with the contextual menu, right clicking and selecting one of the constraints available, you can create that one constraint over the multi components that are selected. So here, we create two constraints at the same time on those two text views. Once we're done building all our constraints, it's time to customize our views a little bit. For that, we're going to use the Attributes Panel, on the right hand side of the Layout Editor. We have redesigned the Attributes Panel to show a new section at the top called Declared Attributes. In that section, we put all the attributes for the selected view that have been set specifically for that view. So right there, you can edit any attributes that have already been set. If you want to set a new attribute on that view, you can simply click the plus button and add the name and value for that attribute. Another thing you can do in the Attributes Panel is use the Constraint Widget to set margins. From your feedback, we've heard that you would have liked to see-- in addition to being able to set just actual values, like number value for the margin-- you wanted to also be able to set custom dimensions defined in your project. That's why we've added that @ dot dot dot option at the bottom of your dropdown. Clicking on that button opens a resource picker, where you can pick a dimension that you've already defined in your project, or you can create a new dimension right there. One final thing that needs to happen-- looking at that layout-- you see that the ImageView is populated with sample data, but it's just default sample data coming from Android Studio. So that's not really representative of the kind of data that your RecyclerView will receive at runtime. So what you can do is set your own sample data to that ImageView. We've added images of cities into a directory called cities, in the sample data folder of our project. You can see that it appears in the sample data picture, and we can select it to set that sample data. Going back to our original layout, we can now see that it looks much more like the original design that you got. From there, you can really see if the design has been implemented properly, and will work when receiving real data, once the application is running on a device. Now we're done with the building of the first constraint, the first screen, and we want to move on to building our next screen in our application. But instead of just going back to creating a layout file, and building it from the Layout Editor, we want to start right there thinking of the navigation flow of our app, and how the first screen will transition into the second screen. To do that, we're going to have a look at the Navigation Editor. The Navigation Editor is a visual tool that makes it easier to use the Navigation Architecture component from the JetPack library. The way the Navigation Architecture component works is it relies on having a navigation host fragment as the main layout in your application. Here in our activity main layout file, we're going to drag from the Layout Editor palette a NavHostFragment-- it's there by default-- and we're going to drag it onto the design surface. When doing that, it will ask you to select a navigation graph associated with that NavHostFragment. If you haven't already created a navigation graph, you can do it right in that dialog, which is what we're doing. This is what your layout will look like. It's empty. There's just this NavHostFragment, because the Navigation Architecture component is the one that's going to populate it with the various fragments that you are going to load. But double clicking on it will open the Navigation Editor. This is what a Navigation Editor looks like when it's empty. First thing we're going to want to do is add our first screen as the starting destination for our app. In the add destination menu, you have pre-selected all the layouts that exist in your app. So for us, we're going to just select that fragment welcome-- which is the layout we've been working on previously-- and set it right there. Next, we want to select, to add the second screen. But because we haven't created a layout for it already, we can simply create a new destination from the add destination menu. Doing that will offer you the possibility of creating a new fragment class and its associated layout, and that's the layout that's going to be used as the second screen. Once the two screens are in the Navigation Editor, comes the time of linking them together. That can be done with actions. You can simply create an action as shown on screen. In addition, you can directly-- in the Attributes Panel of the Navigation Editor-- set some of the properties for that action, like what animation will be played when transitioning through that action, or pressing back. Another very interesting thing that can be done with action is pass type-safe data from one screen to the next. If you want to do that, you can-- on the receiving destination-- click the plus button in the arguments section of the Attributes Panel, and that opens a dialog where you can simply specify the name of the argument, and the type of the argument. That can be a type that is predefined, or that can be a type that you defined in your project, for whatever object you want. Of course, building the navigation graph is not enough to fully specify the navigation of your app. You also need to write a little bit of code. But it's pretty simple, as you can see. Here, I'm just on the item of the RecyclerView. For the OnClickListener, I want to transition and go through that action. So what I do is I create the action object, passing it the argument that I specified in the Navigation Editor. And once I have the action, I can simply call the navigate method of the navigation library to actually perform that transition. That's all you need to actually do the transition you defined. One final thing you can do in the Navigation Editor is use placeholder to fill the rest of your navigation flow, if you don't want to bother at that moment creating new fragments. Later on, when you're ready to do so, you can simply go back and replace them with layouts. I think now it's time to actually build our second layout. As you can see, it's a layout that involves a lot of images, and a lot of resources. We're going to see how the resource manager can help us build it. VADIM CAEN: I was talking before about filling gaps. One gap that was existing in Android Studio was how to manage your resources. So let's go to see what the issue was. The Android Studio resource directory structure is made for the framework, not really for the user, because when you get resources from your designer, it might look like this. You might have a bunch of folders-- I'm sorry, the other issue first is that in Android Studio, you don't have any thumbnail view of all the specific Android view. So layout, vector rubble, or shapes-- the only way you can preview those are is to double click on one layout, or on one file, and see it in the preview. To solve this problem, we've introduced in Android Studio 3.4 the Resource Manager, which is a new tool that helps you import, use, and explore your resources in a more graphical way. To open it, simply click the button, Resource Manager, right below the project button, on the left side of Android Studio, and it will open this neutral window. One more time. So back to our problem. On the left side, we have our project structure, and on the right side, we have what the designer gave us. We can see the different program on the file that the designer gave us. Maybe they used their favorite design software, and used a default export option, and it might be missing the drawable prefix on the folder names. Or maybe they used the web format, with the suffix, @2x. And what you would need to do is to remove the @2x suffix, and then copy paste every single file, one by one. The other issue is the folder might be missing, and you would have to jump back to the documentation to remember what the qualifier for this specific folder was, and you have to put them in the right order. How does it work with the Resource Manager? Now you can simply drag and drop the whole bunch of files that you got onto the Resource Manager, and that will be automatically imported and grouped by name. So as you can see here, our resources are grouped by name, and the right qualifier has been applied. So what just happened here? [APPLAUSE] Thank you. If we identify a qualifier-- it could be web or Android, in your file path, like here-- we would simply create the corresponding Android folder, and strip out any suffix that might be present in the file, and copy it onto your project. Of course, if you want to add more qualifiers, for example, randomly a local, and a random language like French, and the region France, you can simply do it here. And you don't have to remember the order, or create manually the folder, it will be created automatically for you with the right qualifier. You can also rename your file if you want to, at this point. Now, our resources are grouped in the Resource Manager, and you can see them all in one go. So you will see only one version of your resources by default. But when you double click on the resource, you will see all the different versions with the different qualifier applied on it, and the file type if you were to analyze what files were taking the most space on your application. Now, this is a feature I'm really excited about. You can now drag and drop your SVG, and they will be all converted at once into VectorDrawable. [CROWD CHEERING] Thank you. So here, I have my file picker open. I don't need to select anything. I can simply click, open, and all my SVG will be imported and converted. Another really cool feature is previewing all your layouts. It might be hard just recognizing a layout by name. So when you open the Resource Manager on the Layout tab, you can see all the layouts, and it's way easier to find the one you're looking for. As I was saying before, we have a tool chain. I want to integrate this whole tool chain together. What we did is integrated [INAUDIBLE] with the Layout Editor. For example, here I have a layout that I want to include, so the top part. I can simply drag and drop this layout onto the Layout Editor, and it will create an [INAUDIBLE].. The same applies for Drawable. Drag and drop Drawable, and the ImageView will be created. Let's fast forward to the end of this view. We can see that on the previous layout our toolbar is not the right color. What we can do is open the color tab, and see all the colors that are defined on our project. You can simply double click on one of them, and it will move open the file, and move the cursor where the color is defined. Then you can use a new color picker to visually choose a color. The color picker works in RGB and HSB, if you were to were to work with a designer that chooses HSB value, or you can use the material palette that is already there. So now, our two layouts are ready, and we want to run them on the app. We're going to welcome back Ashley and Joe to tell us about inspecting new layouts. [APPLAUSE] JOE BAKER-MALONE: Thank you, Vadim. Now, we're onto the next part of the development cycle where we actually get to run the app, see how it works with real data, and make any adjustments that we might need to. Now today, if you want to see how your layouts are working at runtime, there's the Layout Inspector tool in Android Studio. The Layout Inspector gives you a snapshot of the complete view hierarchy of one screen, and some information about the attributes that are set on each view. But right now, it has a number of limitations. This is due in part to what data the Android framework makes available to Studio to show. Now in Android Q, the framework has added a number of new APIs for Studio to use to expose more view and layout debugging information in Studio. Ashley is going to talk about those new APIs shortly. To verify that the framework additions are sufficient for us to show the information that we want to, to the users, a couple of us from the Android Studio team have taken a little bit of time out from our Project Marvel work to adopt the new APIs, and see what we can do with them. We started work on a completely new Layout Inspector. What I'm going to show you now is a sneak peak of the work that we've done so far. Now, this is early work. It's not yet in the latest preview builds. But as Chad said yesterday in the Developer Keynote, we love previews. We love developer feedback. And so, we're going to get it out into your hands as soon as possible. Now, let's see how it works. We'll start with the Google Trips app that we've been working on. You can see now that it's running in the emulator. We've hooked things up so that it's running on real data from a user, rather than the sample data that we were using at design time. As we scroll down here, you can see that some of the trip descriptions in the real data are significantly longer than what we had in the sample data, to a point where the text is sort of dominating the images in a way that we hadn't intended. Let's take a look at this in the new Layout Inspector. You can see that the new Layout Inspector gives us a view similar to what we have in the Layout Inspector today. If we select the text view in question here, and then look at the Attributes Panel on the right, we can see that there are a few differences compared to what we have in the current Layout Inspector. First of all, we have the actual attribute names here, whereas previously we had a collection of getter methods that may or may not have corresponded very well to the actual attributes. This should make it much easier for you to map back from what you see here, to what you have defined in your own layouts and styles. Secondly, we have nicely formatted attribute values for a number of different value types, and we couldn't always get that before. So for example, you can see we have an ID, an enum value, a color, et cetera. Thirdly, we have some information now about where that attribute value is being set. So you can see that we have this declared attributes section here, similar to what we have in the Layout Editor, for those attributes that are set directly on the view that's selected. Now, let's look at the relevant attribute here, text size. Once we have this selected, you can use your preferred navigate to declaration keystroke to go directly from here to the layout xml where that value is being set. Let's change it to make it a little bit smaller. As you heard in the Developer Keynote, in Android Studio 3.5 preview they have this new apply changes functionality. You can hear more about that right after this, in the What's New in Android Developer Tools talk. But right now, we'll use it to see our change in the emulator without having to redeploy our app. In fact, we'll see the update right away in the new Layout Inspector as well. This is because Layout Inspector is mirroring what happens on the device live. If we were to scroll back up here, we'd see that the Layout Inspector scrolls right along as well. [APPLAUSE] Yay. Let's take a look at another scenario. Let's say we want to implement a dark theme for our app. Here you see we have a light background color. Let's find out where that background color is coming from. If we look in the fragment xml we have here, we don't see it set there directly. Let's take a look in the Layout Inspector. If we select the background here, you can see-- if you can see really well-- that we don't have the background color set directly on this view. Now, why might that be? Well, we've only selected the top most view here, and the background color might be set somewhere lower down in the view hierarchy. But which view is it being set on? Well, the new Layout Inspector gives us an easy way to find out. [CROWD REACTION] [LAUGHS] So in the 3D view, it's easy to see which view is drawing what here. Now, if we select that view, you can see that the background color is indeed being set. But in what file is it being set? It's not at the top in the declared attributes section, so we know it isn't being set on this view directly. But again, if we select the property in the Attributes Panel, we can navigate directly from there to where it's being set. In this case, it's being set in a style. And we can navigate directly to that style, even if it isn't referenced explicitly by your view. The 3D representation we saw allows us to visualize things in other ways as well, and we're still exploring what might be useful here. For example, it might be useful to just focus on one view, and its children. Or it might be useful to group views together based on what layout file they're defined in. So example for this screen, you can see that at the top, we have the RecyclerView items, and then the fragment, and then the activity. And behind that, the various views that are defined by the framework. We have a lot more planned for the light new Layout Inspector, and I'm excited to see what we can come up with. Now, to talk about the framework changes that were needed to enable this, here's Ashley. ASHLEY ROSE: Thanks, Joe. [APPLAUSE] For Android Q, we've added three new APIs to enable these new inspection features. We have the ability to take all the drawing commands that went into building a frame on the screen and serialize them and send them back over to Studio so it can replay them, and build that lovely 3D view. We significantly sped up how long it takes to get the properties of views in the view hierarchy, as well as adding additional metadata to that and making it more correct. And we added some new APIs to the resource framework that let us see where an attribute value came from, as well as some more insight into the decision process of which themes were applied when reaching that attribute value. So let's talk about the Skia Picture. Skia is our 2D graphics library that underlies the UI toolkit. This is a simplified view to actually fit it on the slide, but it's a list of drawing commands that go into building one of our trip cards from earlier. If we look at it, it's composed of shadows, rounded rectangles, images, text-- all of that, along with the assets needed to render it, the image data, the font data, et cetera. We get this from Skia natively. It's very quick. It allows us to do our live preview because we can get this a few times a second. It's generally very small. But the problem with this is, if we want to zoom in on the switch here, it's composed of a text, a rounded rectangle, and a little image for the circle slider switch. We don't know which views those came from. They're just drawing commands. We wanted some way to group drawing commands by what view they came from. We looked at the render note API-- which is an organization tree that underlies both views and drawables-- and we added a unique ID to each render note. We then exposed this unique ID on the views, and annotated the Skia Picture itself with where each render node started and stopped drawing. This lets us on the studio side walk through and see where a view started and where it stopped, and associate these three drawing commands back to the switch view. Additionally, since we have start and stop, we have a nice nested framework-- kind of like, HTML-- that lets us see, here's all the drawing commands again, simplified, that went into building this card view, as [? long as well ?] which views they start and stop from, which let's us do nesting. Let's talk a little bit about how we fix property inspection. To Joe's point earlier-- where everything was getter names, or method names-- that was because we were using reflection at runtime on the attributes inside the view instance. Reflection isn't the fastest thing in the world, especially on a mobile device. And for a very complicated app, that could take up to several seconds to render an entire view hierarchy. So we looked into an approach of-- we have a method that serializes everything. That gets a little brittle. If you add a new attribute to your view, it's not updated. We added in a annotation processor, which allows us to retain the flexibility that the reflection provided us. All you have to do is add an annotation if you add a new getter. Let's take a look at what that might look like for a custom view because this will be relevant for anyone who's building library views soon. We have a color view. It's property is a color, and we annotate it with InspectableProperty. This gets us-- when the annotation processor looks at it-- this gets us a little bit more context than we had before of just looking at the getter. So we're in Kotlin, and we can see the @ColorInt annotation, as well as the integer type, which we know that we've packed a color into this integer and it's not just a numerical value. We've got the name of the property, which we can use to make inferences about its attribute ID, what to call it. And of course, we can override any of the inferences using properties on the annotation itself. So what the code generation for this looks like, is it builds a companion object that will sit alongside this view. Let's take a look at what one of those might look like. This is an inspection companion. It's a new API for Q. It has two purposes. One, defines a list of-- given a class-- here are the properties defined on that class. In this case, we've defined color. If you look into the call to map color, we have the type there, since it's a color. We have the property name color, and we've inferred the attribute of ID off R.attr. This will also enable us to-- if you didn't have an inferred attribute ID, or you supplied one-- we would put it in there. This teaches the Studio, if I have a view, here's what properties I have on it, here's what their attribute IDs are, and this allows us to enable that part of that jump to code completion function. The next step is when we actually have an instance of the view, we want to read the property. Again, since our view is defined in Kotlin, and we're in Java-- because this is generated code-- we call view.getColor, we have a direct call to the getter, no reflection required. It's very fast. This enables us to do the live updating of the view hierarchy in Studio, because we do not have all the additional overhead we did previously. Where all that gets us is to a current value. We can say, here's this lovely blue text color we have here. We can say what it is, regardless of whether it was set in runtime. Maybe you called view.setColor. Or if it was set in resources. But most attribute values are set in resources, so we wanted to help with that case. We wanted to help with a case where, in this case, it's defined in your widget. We added an API to resources that lets you say, I've gotten this value. Tell me where it came from. We track that data, and we store it through the entire resources framework. Additionally, we wanted to get some insight into how styles affected this. So the resources framework-- when it's resolving an attribute value-- has to make a decision about which style to apply. We took the decision tree and we add an API to expose that. So it's essentially the list of styles that were considered, but eventually maybe used or not used while resolving that attribute value. The problem with all this is it's ephemeral, because views, once they've been inflated, they forget their relationship to resources. Once they've been constructed, they don't remember where they came from, for the most part. We added a developer option that allows views to store both the map of attribute IDs, and locations where they came from, and the style resolution stacks from the themes on the view. So Studio-- when it's ready, or you're interested and you want to drill down more into a property-- come back to a view and ask the view, hey, where did your attribute values come from, and what are their styles? That pretty much wraps up everything we have for Q, and I'd like to welcome Vadim and Jerome back on the stage to wrap us up. [APPLAUSE] VADIM CAEN: You've heard about the whole tool chain, and I hope you're going to be using it when you go back home. There is building your layout with the Layout Editor, and the new feature we've added. Building your navigation with the Navigation Editor, managing resources with a resource manager, and doing your inspection with a new Layout Inspector. This year, I/O is packed with Android Studio talks. Right after-- in the Amphitheater-- you can watch the What's New in Android Development Tools, presented by Tor and [? Ja. ?] Then you have What's New in the Android Build System on Stage 2, which is on the other side, which starts this afternoon. I have little red dots here. Android Studio Tips and Tricks, presented by a curated selection of engineers and project managers, Stage 2. And finally tomorrow, What's New in ConstraintLayout and Motion Layout by Nicolas and John. We're going to be taking questions right outside here. Thank you very much for coming, and I'll probably see you next year. [MUSIC PLAYING]
Info
Channel: Android Developers
Views: 49,050
Rating: undefined out of 5
Keywords: type: Conference Talk (Full production);, pr_pr: Google I/O, purpose: Educate
Id: oWTG5g5rT4s
Channel Id: undefined
Length: 36min 49sec (2209 seconds)
Published: Wed May 08 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.