Compose - List / Detail: Basics - Styling Android
source link: https://blog.stylingandroid.com/compose-list-detail-basics/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Compose – List / Detail: Basics
In a recent post on Styling Android we looked SlidingPanelLayout
. This can simplify the implementation of a List / Detail UI. It handles the logic of whether to show a side-by-side layout or a two-page layout depending on the screen size. Currently, there is no equivalent for this in Jetpack Compose. In this article, we’ll see how Compose makes this relatively easy.
Before we dive into this it’s worth pointing out the word “currently” in the opening paragraph. This is an area of Compose that is under active development. So keep an eye out for an official implementation of this kind of functionality. Even if this is only a temporary solution there are still some interesting techniques that we’ll cover.
It’s also worth mentioning that, we’ll have a working solution by the end of this article. This may be fine for many cases. But we’ll add further functionality in the second article. This will make the behaviour even better on foldable devices.
List / Detail
The basic behaviour that we’re after is when the UI has a list of items. When the user taps an item in the list then we display the details in the detail view. On larger screens, there may be sufficient space to display both the list and detail view side-by-side. However, on smaller devices tapping an item may replace the list view with the detail view, and hitting back will return.
We can do this on older View-based UIs by having different layouts for different screen sizes. More recently, SlidingPaneLayout
can handle the heavy lifting.
To do this with Compose, let’s first look at the List and Detail composables:
I have deliberately kept these as simple as possible. This is to keep the code easy to understand.
List() uses a LazyColumn
to display a list of items provided as an argument, and the selection action is handled by a listener argument. Detail() simply displays a piece of text.
Split Layout
The split layout (i.e. the side-by-side one) is the easier to implement:
Here we use a mutable state to hold the currently selected text.
We display the List and Detail components side-by-side using a Row
. I have used equal weights here to divide the screen in half. But it would be trivial to change that to meet differing requirements.
When the user taps on a list item, the text is displayed in the right hand pane:
Two Page Layout
Implementing the two page layout is slightly tricker because we have to consider how to handle the back behaviour. Using Navigation Compose makes this much easier.
We create a NavGraph which consists of two destinations – the List and the Detail. The route for the Detail includes an argument for the selection string.
When the user taps on a list item, then it triggers navigation to the Detail view, including the selected text as an argument. We extract this value from the backStackEntry arguments and use it as the argument for the Details()
composable. Navigate Compose now handles the back behaviour for us.
This gives the basic behahviour that we’re after:
To keep the code simple and easier to understand I haven’t included any navigation animations. But that is certainly something I’d look to add when using this for real.
Dynamic Layout
Now that we’ve implemented the basic behaviour patterns, we need to add the logic of when to use each. This is actually really easy in Compose:
A Configuration
instance is passed in as an argument, and we apply some simple logic. We’ll look at where this comes from in a moment. If the smallest screen width is less than 580dp
, then we emit TwoPageLayout
otherwise we emit SplitLayout
.
The Configuration
object is not specific to Compose, it is what is used by the resource management framework to provide alternate resources. So we can leverage it in much the same way we. In this case, we’re applying the same logic as when we put a layout in res/layout/sw580
.
Putting It All Together
We can now call DynamicLayout
with two arguments: The list of strings to display, and the Configuration
instance:
We obtain the current Configuration
by calling LocalConfiguration.current
.
The user will now see different UIs depending on the window size. This also works in multi-window – as the window size crosses the 580dp
width boundary the UI switches automatically.
Conclusion
None of the individual composables here are particularly complex. That is very much by design. Keeping the composables small and focused makes them much easier to combine to create the desired UI. For example DyanmicLayout
is solely about the logic for which UI to emit. TwoPageLayout
and SplitLayout
are solely responsible for their own specific behaviour
While this may seem like we have the behaviour that we want now, this doesn’t quite match the functionality of SlidingPaneLayout
. In the next article, we’ll look at how we can get this playing even nicer with foldables.
The source code for this article is available here.
© 2021, Mark Allison. All rights reserved.
Related
Jetpack ComposeMay 14, 2021In "Compose"
Gradle: Version CatalogsMay 21, 2021In "Build"
NumberPickerJune 26, 2020In "NumberPicker"
Copyright © 2021 Styling Android. All Rights Reserved.
Information about how to reuse or republish this work may be available at http://blog.stylingandroid.com/license-information.
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK