ThemeExtensions | Decoding Flutter

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[MUSIC PLAYING] CRAIG LABENZ: When I started my software career as a web developer, one of the first things I learned was not to mix my semantic information with my presentation rules. On the web, this concept comes to life by storing your semantics in HTML and your cosmetics in CSS. Of course, you can inline your styles directly into your HTML. But if you do, (IMITATING GANDALF) you shall not pass (NORMAL VOICE) code review. A decade later, when I found Flutter, I knew I liked what I saw, but the common mixing of my raw information with its presentation was unsettling. I looked up how to stop doing this and was, of course, pointed at Flutter's theme system. I thought, neat. And then I dug into it a little bit and thought, what? And so today we're going to talk about a few tricks and a new API to squeeze the most juice out of your apps theme and make sure that your custom widgets rarely require inline styling. Hello, widgets department. Who's this? Raw styling code? I told you to stop calling. To start, let's explore how material widgets use Flutter's theming system to figure out how to dress themselves. Put simply, most material widgets have three places they look when resolving each of their cosmetic attributes. The first is any raw parameters exposed in their constructor. Sometimes this is in top-level color or padding parameters, and sometimes it's in dedicated style parameters that wall off all the details. Either way, these are all those random styling parameters we all use every day. At least for me, the most common situation is this, where I start from my existing theme but modify it in some way, because my current purposes were hard to capture in the actual theme itself. The second place material widgets look is up the tree to an inherited theme widget and its associated ThemeData instance. This is what Count Dracula taught us in his guest Widget of the Week appearance back in October of 2021. Pray that you remembered it. Note that this is what happens when you supply a theme or a dark theme to your material app. Internally, it sticks those in a theme widget. The third option, if no one has picked up the phone yet, is the default theme, which can be found at the ThemeData.light or ThemeData.dark factory constructors. And this is what produces the infamous blue-white color palette of the counter app. Within a given material widget, the code that looks in these three places will often look like this. Step one-- the widget checks any of its own parameters. This part is optional because not every widget has such parameters for every detail. Step two-- the widget asks the theming system. And step three is sneakily wrapped up in step two, because the material widget app adds a default theme if you don't. So this will return something. And this all happens on a per-attribute basis, which is why you can use the convenient TextButton.styleFrom method that we talked about in the last episode. In this scenario, our TextButton will resolve its background color in step one, and for everything else, continue on to steps two and three. Now, this is all good and fun, but here's the rub. Material widgets are hooked into this pattern directly, so anything they care about just so happens to appear in one of the theme variables. How convenient. It's almost as if the same people wrote both sides of that code. But how does that help your widgets? If you're designing heavily custom controls and want this same ordered approach, which allows most or all of your styling code to stay out of your raw widgets, you're out of luck, until that new API I mentioned earlier. Coming in the next stable release of Flutter is a new system called ThemeExtensions. To start, use the extensions parameter and either a brand new theme or a copy of an existing theme. Into that variable, put an iterable of ThemeExtensions and use the dynamic type. Next, instantiate a class of your own creation that contains whatever cosmetic details are important to you. Imagine you're working on an all new widget, which is like a card/hero image hybrid. To support its build method, you decide to introduce a HeroCardStyle class. This means you can use the same tricks above in your HeroCard build method and check for all the variables incrementally. The only the problem is Flutter's ThemeData class doesn't know about your custom HeroCardStyle class, so would have no idea what you're talking about, which is where extensions come in. Back to our Theme class, register this HeroCardStyle as an extension. Of course, the class doesn't exist yet, so let's write it. To be valid, our class should subclass ThemeExtension and use itself as its own generic. Trippy, I know. Obviously, it needs to know about all of its relevant variables. And beyond that, there are two methods we must override. The first is CopyWith, so that our extension can play along with the ThemeData class's normal copying mechanisms. And the second is lerp, because all theme things need to know how to linearly interpolate themselves. Finally, everything is in order to finish our HeroCard widget. In its build method, check the parameters you exposed first, then fall back to the ThemeExtension by way of Theme.of(context).extension, using our type as the generic. Finally, we have a HeroCardStyle instance, and we can get to assembling whatever widgets make up a HeroCard. And it's worth noting that your ThemeExtensions don't have to be this fancy and serve a specific widget. They could just hold some extra colors and expand your app's color palette. Before ThemeExtensions, it wasn't easy to keep your presentation rules out of your custom widgets. But now, it can be done. Hopefully, these tricks help you write cleaner, more predictable layouts. For more info on Flutter, head to flutter.dev. [MUSIC PLAYING]
Info
Channel: Flutter
Views: 55,047
Rating: undefined out of 5
Keywords: purpose: Educate, pr_pr: Flutter, series: Decoding Flutter, type: type: DevByte (deck cleanup 2-10min), GDS: Yes, developer tutorials, Flutter, Flutter tutorials, Flutter developers, flutter app development, Flutter course, how Flutter works, Flutter best practices, Decoding Flutter, Google developers, flutter 101, get started with flutter, flutter apps, flutter widgets, build apps with flutter, flutter developer, flutter developers, Craig Labenz
Id: 8-szcYzFVao
Channel Id: undefined
Length: 6min 13sec (373 seconds)
Published: Tue May 03 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.