Learn to construct nice person experiences for big screens & foldables in Android. Additionally discover ways to design and take a look at adaptive Android apps.
Massive screens are an vital and fast-growing phase of energetic Android gadgets. There are greater than 270 million large-screen Android gadgets in use. They embrace tablets, foldable gadgets and Chrome OS gadgets. To achieve this rising phase of Android customers, study to make your app UI adaptive throughout a variety of gadgets.
On this tutorial, you’ll construct an app referred to as Artful Pocket book, which reveals a listing of notes. Alongside the way in which, you’ll study:
- APIs and instruments to construct nice person experiences for large-screen Android gadgets.
- Designing adaptive apps for various display screen sizes, orientations and kind components.
- Google Play updates for large-screen gadgets.
- Testing your app layouts for big screens.
Getting Began
Obtain the starter undertaking by clicking the Obtain Supplies button on the high or backside of the tutorial.
On this tutorial, you’ll use a resizable emulator to check your app’s UI throughout completely different gadgets. To arrange a resizable emulator, open the starter undertaking with Android Studio model 2021.2.1 or newer and comply with these steps:
- Click on Instruments ▸ SDK Supervisor. Within the SDK Instruments tab, choose Android Emulator and click on OK. This may set up the newest model of the emulator if it isn’t already put in.
- To create a digital gadget, click on Instruments ▸ Machine Supervisor. Then, click on the Create gadget button and choose Cellphone ▸ Resizable. Click on Subsequent and choose the newest API degree. Verify the emulator particulars and click on End. This may create a resizable emulator.
- On the listing of digital gadgets, choose the resizable gadget and click on the Launch icon to begin it.
Construct and run the undertaking. Right here’s what you’ll see:
Within the emulator window, click on the Show Mode drop-down and choose Pill:
On a large-screen gadget like a pill, content material stretches to fill the obtainable display screen area like this:
However customers anticipate an excellent expertise whereas utilizing your app throughout completely different Android gadgets. Your purpose is to make use of the additional display screen area to enhance the person expertise and supply nice accessibility on large-screen gadgets.
Wanting Into Android 12L Updates
Android gadgets are available in numerous kind components: telephones, tablets, foldables and Chrome OS gadgets. They differ in display screen sizes from small to giant display screen sizes.
At Android Dev summit 2021, Google introduced Android 12L. Android 12L is a function replace for Android 12 that was constructed for large-screen gadgets. Android 13 builds on updates made in Android 12L. A few of the updates embrace:
- Taskbar interplay: The brand new taskbar makes it simple to launch and swap apps. Gestures equivalent to drag and drop enter split-screen mode. In gesture navigation, customers can flip by current apps. This allows highly effective and intuitive multitasking on giant screens.
- Default multi-window mode: To boost the cut up display screen expertise, Android 12 or greater permits multi-window mode by default in all apps.
- Improved compatibility expertise: Some apps aren’t optimized for big screens but. They aren’t resizable or are utilizing fastened orientation. These apps are launched in compatibility mode to make them look higher by default. Such apps are centered on the display screen with black bars filling the unused show space.
- Digicam preview enhancements: This makes the digital camera app adaptive to giant screens, multi-window mode and completely different foldable gadget postures.
- Media projection updates: Beginning in Android 12L, the digital show is scaled to suit obtainable display screen area. This improves display screen casting on giant shows like televisions. It maximizes the dimensions of floor photos and ensures the right facet ratio.
You’ve realized about updates for large-screen gadgets beginning in Android 12L. Subsequent, you’ll discover ways to construct responsive apps throughout completely different gadgets.
Designing Adaptive Apps
Responsive apps present an excellent person expertise throughout completely different display screen sizes and kind components. They help completely different display screen orientations and resizable configurations like multi-window mode.
That will help you create adaptive layouts, Materials Design 3 supplies canonical layouts. Canonical layouts function a tenet for creating responsive layouts for big screens. They embrace:
- Record-detail view: In a list-detail view, you place a listing of things on the left. On the suitable aspect, you present particulars of an merchandise.
- Supporting panel: A format consists of focus and help areas. The main target area reveals the first content material. It covers two-thirds of the show space. The supporting panel occupies the remaining display screen area to indicate extra content material like feedback on a doc. It’s positioned on the backside third on an expanded top or trailing third on an expanded width.
- Feed: Feed layouts are widespread in information or social content material apps. For instance, with a RecyclerView, use a special format supervisor like GridLayoutManager when the width is just not compact.
Realizing what sort of gadget the person is utilizing gained’t assist you to determine which app layouts to make use of. On tablets, for instance, an app could possibly be sharing the display screen with one other app in multi-window mode. Or, on a foldable gadget, there could possibly be multiple bodily display screen. As an alternative, make choices based mostly on the precise portion of the display screen that’s allotted by utilizing Jetpack WindowManager library.
Within the subsequent part, you’ll discover ways to use Window Dimension courses to find out the format in your app. Window dimension courses are decided by the window dimension obtainable to your software no matter the kind of gadget the app is operating on.
Exploring Window Dimension Lessons
Window dimension courses are viewport breakpoints to information you in designing responsive and adaptive layouts. They classify display screen area obtainable in your app as compact, medium or expanded.
Out there width and top are categorized individually. The obtainable width is extra vital than the obtainable top as a result of vertical scrolling is widespread throughout gadgets. The obtainable width is classed as follows:
- Compact width: The gadget width is lower than 600dp. Telephones in portrait orientation and foldables in folded state are on this class.
- Medium width: The gadget width is greater than 600dp. Medium-width gadgets embrace tablets and enormous unfolded foldables in portrait orientation.
- Expanded width: Tablets and enormous unfolded foldables in panorama orientation fall on this class. They’re greater than 840dp huge.
You’ll use the material3-window-size-class
library to get the window dimension class of a tool. The library calculates the window dimension class utilizing present window metrics.
Open construct.gradle(app)
. The next library dependency has already been added:
implementation "androidx.compose.material3:material3-window-size-class:1.0.0-alpha14"
Open presentation ▸ MainActivity.kt, and substitute // TODO 1
with the next:
val windowSizeClass = calculateWindowSizeClass(exercise = this)
The code above returns the window dimension class for the offered exercise. calculateWindowSizeClass(exercise: Exercise)
calculates WindowSizeClass
for the offered exercise. The strategy returns a brand new WindowSizeClass
throughout display screen rotation or window resize. The app recomposes the UI with the brand new window dimension class.
Add any lacking imports by urgent Possibility-Return on Mac or Alt-Enter on PC.
You might even see an error squiggly line. It is because the library continues to be experimental. To repair the error, add the next earlier than onCreate()
and import the corresponding package deal:
@OptIn(ExperimentalMaterial3WindowSizeClassApi::class)
Subsequent, you’ll move windowSizeClass
to the NoteApp()
composable. You’ll use this info later to find out the app layouts.
Change // TODO 2
with the next:
windowSizeClass = windowSizeClass.widthSizeClass,
Earlier than updating the app to answer modifications in display screen sizes, you’ll take into account gadget fold posture additionally.
Wanting Into Machine Fold Posture
A foldable gadget may be in numerous states and postures. It might be folded or unfolded, in portrait or panorama orientation. It could possibly be in a tabletop or e-book posture. An adaptive design helps completely different foldable postures.
Jetpack WindowManager library’s WindowLayoutInfo
class supplies the next details about foldable shows:
-
state: This describes the fold state. Its worth is
FLAT
when the gadget is absolutely opened, orHALF_OPENED
. -
orientation: The orientation of the hinge. It may be
HORIZONTAL
orVERTICAL
. -
occlusionType: The worth is
FULL
when the hinge hides a part of the show. In any other case the worth isNONE
. -
isSeparating: It’s
true
when the hinge creates two logical shows.
You’ll use this info to find out gadget fold posture. Open presentation ▸ util ▸ DevicePostureUtil.kt. DevicePosture
interface defines the next postures:
- Regular posture: Whether or not a tool is absolutely opened or absolutely folded.
-
Guide posture: The gadget is in portrait orientation and its fold state is
HALF_OPENED
. -
Separating posture: The gadget is totally open and its fold state is
FLAT
. It’s much like the case of gadget posture the placeocclusionType
isFULL
due to a bodily hinge. Keep away from inserting touchable or seen elements underneath the hinge.
Analyzing Machine Fold Posture
To get gadget fold posture, open MainActivity.kt and substitute // TODO 3
with the next:
// 1
val devicePostureFlow = WindowInfoTracker.getOrCreate(this).windowLayoutInfo(this)
.flowWithLifecycle(this.lifecycle)
// 2
.map { layoutInfo ->
val foldingFeature =
layoutInfo.displayFeatures
.filterIsInstance()
.firstOrNull()
when {
isBookPosture(foldingFeature) ->
DevicePosture.BookPosture(foldingFeature.bounds)
isSeparating(foldingFeature) ->
DevicePosture.Separating(foldingFeature.bounds, foldingFeature.orientation)
else -> DevicePosture.NormalPosture
}
}
.stateIn(
scope = lifecycleScope,
began = SharingStarted.Eagerly,
initialValue = DevicePosture.NormalPosture
)
Additionally embrace the next imports to keep away from Android Studio’s complaints:
import androidx.lifecycle.flowWithLifecycle
import androidx.lifecycle.lifecycleScope
import androidx.window.format.FoldingFeature
import androidx.window.format.WindowInfoTracker
import com.yourcompany.android.craftynotebook.presentation.util.DevicePosture
import com.yourcompany.android.craftynotebook.presentation.util.isBookPosture
import com.yourcompany.android.craftynotebook.presentation.util.isSeparating
import kotlinx.coroutines.stream.SharingStarted
import kotlinx.coroutines.stream.map
import kotlinx.coroutines.stream.stateIn
Within the code above, you’re utilizing Kotlin Flows to work with WindowLayoutInfo information assortment.
-
windowLayoutInfo(exercise: Exercise)
returns show info of a tool asCirculate
. The strategy emitsWindowLayoutInfo
each time the show info modifications. - It makes use of
map
operator and show info returned bywindowLayoutInfo(exercise: Exercise)
to find out the gadget fold posture.
Subsequent, you’ll observe gadget posture as compose state. In MainActivity.kt, substitute // TODO 4
with the next and import the corresponding package deal.
val devicePosture = devicePostureFlow.collectAsState().worth
Then, move devicePosture
in NoteApp()
composable name. Change // TODO 5
with the next:
devicePosture = devicePosture,
Up so far utilizing window dimension courses, the app is aware of the display screen area obtainable. It additionally is aware of the gadget fold posture. You’ll use this info to find out the app UI. First, you’ll implement responsive navigation.
Selecting Applicable Navigation Sort
Responsive UIs embrace several types of navigation parts akin to show dimension modifications.
Materials library supplies navigation parts like backside navigation, navigation rail and navigation drawer. You’ll implement probably the most acceptable navigation relying on the window dimension class of a tool:
- Backside navigation: Backside navigation is most acceptable for compact window sizes.
- Navigation rail: Use navigation rail for medium display screen sizes.
- Navigation drawer: This might be appropriate for large-screen gadgets like tablets. There are two sorts of navigation drawers: modal and everlasting. Use a modal navigation drawer for compact to medium sizes as a result of it may be expanded as an overlay on the content material or hidden. Use a everlasting navigation drawer for fastened navigation on giant screens like tablets and Chrome OS gadgets.
Now, you’ll swap between completely different navigation sorts relying on the window dimension of a category and gadget fold posture.
Open NoteApp.kt and substitute // TODO 6
with the next and import the package deal for NavigationType
:
// 1
val navigationType: NavigationType
// 2
when (windowSizeClass) {
WindowWidthSizeClass.Compact -> {
navigationType = NavigationType.BOTTOM_NAVIGATION
// TODO 13
}
WindowWidthSizeClass.Medium -> {
navigationType = NavigationType.NAVIGATION_RAIL
// TODO 14
}
WindowWidthSizeClass.Expanded -> {
// 3
navigationType = if (devicePosture is DevicePosture.BookPosture) {
NavigationType.NAVIGATION_RAIL
} else {
NavigationType.PERMANENT_NAVIGATION_DRAWER
}
// TODO 15
}
else -> {
navigationType = NavigationType.BOTTOM_NAVIGATION
// TODO 16
}
}
The code above does the next:
- Declares the
navigationType
variable. - Utilizing a swap assertion, it initializes
navigationType
with the right worth relying on the window dimension class. - Handles fold state to keep away from inserting content material or touching motion on the hinge space. When a tool is in
BookPosture
, use a navigation rail and divide content material across the hinge. For big desktops or tablets, use a everlasting navigation drawer.
Subsequent, you’ll move navigationType
to NoteNavigationWrapperUi()
composable name. In NoteApp.kt, substitute // TODO 7
with the next:
navigationType = navigationType,
Now, the app is aware of navigation sorts to use to completely different window dimension courses and gadget fold postures. Subsequent, you’ll implement completely different navigation to make sure glorious interplay and reachability.
Implementing Responsive Navigation
Open NoteNavigationWrapperUi.kt
. Change NoteAppContent()
composable name with the next:
if (navigationType == NavigationType.PERMANENT_NAVIGATION_DRAWER) {
PermanentNavigationDrawer(drawerContent = {
NavigationDrawerContent(
navController = navController
)
}) {
NoteAppContent(
navigationType = navigationType,
contentType = contentType,
modifier = modifier,
navController = navController,
notesViewModel = notesViewModel
)
}
} else {
ModalNavigationDrawer(
drawerContent = {
NavigationDrawerContent(
navController = navController,
onDrawerClicked = {
scope.launch {
drawerState.shut()
}
}
)
},
drawerState = drawerState
) {
NoteAppContent(
navigationType = navigationType,
contentType = contentType,
modifier = modifier,
navController = navController,
notesViewModel = notesViewModel,
onDrawerClicked = {
scope.launch {
drawerState.open()
}
}
)
}
}
As common, there are a number of imports it’s essential to add as nicely:
import kotlinx.coroutines.launch
import androidx.compose.material3.*
The navigation drawer is the container for notes UI. Within the code above, you’re wrapping the NoteAppContent()
composable name with a everlasting or modal navigation drawer relying on the worth of navigationType
.
In NoteAppContent.kt, substitute the Column()
composable with the next:
Row(modifier = Modifier.fillMaxSize()) {
AnimatedVisibility(seen = navigationType == NavigationType.NAVIGATION_RAIL) {
NoteNavigationRail(
onDrawerClicked = onDrawerClicked,
navController = navController
)
}
Column(
modifier = modifier.fillMaxSize()
) {
NoteNavHost(
modifier = modifier.weight(1f),
contentType = contentType,
navController = navController,
notesViewModel = notesViewModel
)
AnimatedVisibility(seen = navigationType == NavigationType.BOTTOM_NAVIGATION) {
NoteBottomNavigationBar(navController = navController)
}
}
}
To make Android Studio glad, add the next imports as nicely:
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.basis.format.Row
The code above makes use of navigationType
to find out placement of navigation rail or backside navigation. You wrapped each navigation rail and backside navigation within the AnimatedVisibility()
composable. This animates the entry and exit visibility of every navigation relying on navigationType
.
Construct and run.
For compact window dimension class like a cellphone, the app makes use of backside navigation like within the display screen beneath:
In a medium window dimension class, the app makes use of a navigation rail like within the display screen beneath:
The app makes use of a everlasting navigation drawer in an expanded window dimension class, like this:
Congratulations! You’ve efficiently applied dynamic navigation on completely different gadgets. Subsequent, you’ll make the most of the extra display screen area to indicate extra content material. You’ll implement list-detail on giant screens.
Displaying Extra Content material
Open presentation ▸ util ▸ ConstantsUtil.kt. ContentType
enum defines two constants: LIST_ONLY
and LIST_AND_DETAIL
. These will assist you to decide content material format relying on the window dimension class.
Open NoteApp.kt. Change // TODO 12
with the next and import the corresponding package deal:
val contentType: ContentType
Right here, you’ve declared a variable of sort ContentType
.
Subsequent, you’ll initialize the contentType
variable with the right worth relying on display screen state.
In NoteApp.kt, substitute the TODOs within the when
assertion as proven beneath:
Change // TODO 13
with the next code:
contentType = ContentType.LIST_ONLY
It units the worth of contentType
with as LIST_ONLY
when the window dimension class is compact.
Change // TODO 14
with the next code:
contentType = if (devicePosture is DevicePosture.BookPosture
|| devicePosture is DevicePosture.Separating
) {
ContentType.LIST_AND_DETAIL
} else {
ContentType.LIST_ONLY
}
The code above initializes contentType
with LIST_ONLY
for medium window dimension class. For a foldable gadget in e-book posture, set the worth to LIST_DETAIL
. This may separate listing view and element view on the hinge space. It helps keep away from inserting content material or contact targets on the hinge space.
Change // TODO 15
with the code beneath:
contentType = ContentType.LIST_AND_DETAIL
This units the worth of contentType
as LIST_AND_DETAIL
on giant screens.
Lastly, substitute // TODO 16
with the code beneath to incorporate the default case:
contentType = ContentType.LIST_ONLY
Subsequent, move contentType
to the NoteNavigationWrapperUi()
composable. Change // TODO 17
with the next:
contentType = contentType,
You’ll use the contentType
parameter to find out whether or not to indicate a listing format or a list-detail format.
Open NotesScreen.kt. Change the NotesListComposable()
composable name with the next:
if (contentType == ContentType.LIST_AND_DETAIL) {
NoteListDetailComposable(notes = notes)
} else {
NotesListComposable(
notes = notes,
onItemSelected = onNoteItemSelected,
)
}
The code above checks the worth of contentType
to find out which format to indicate. The app will present a list-detail format on giant screens. In compact and medium display screen sizes, the app will present a listing format.
Construct and run.
On a compact or medium display screen dimension, the app reveals a listing format like within the screens beneath:
On giant screens like a pill or desktop, the app reveals a list-detail format like this:
Making certain Knowledge is Out there for All Display screen Sizes
A responsive UI retains information when a cellphone is rotated or a foldable is unfolded or folded. Altering cellphone orientation, folding and unfolding a foldable or resizing a window are configuration modifications. Throughout configuration modifications, the system recreates app actions, fragments or composables. The advisable methods to protect information throughout configuration modifications are utilizing a ViewModel class and rememberSavable API for compose apps.
On giant screens, you might be displaying extra content material to make the most of the additional display screen area. So, you might be tempted to fetch information when the display screen dimension modifications. This goes in opposition to the precept of unidirectional information stream — that state flows down and occasions stream up — the place information ought to be hoisted and offered to the composables for displaying.
You must present sufficient information to the composable in order that it all the time has what it must show throughout any display screen dimension. Then, you should utilize a flag like contentType
to find out what information to indicate on a given display screen dimension.
Open NotesScreen.kt. You’ll see code like this:
val notes = notesViewModel.notes.collectAsState().worth
if (contentType == ContentType.LIST_AND_DETAIL) {
NoteListDetailComposable(notes = notes)
} else {
NotesListComposable(
notes = notes,
onItemSelected = onNoteItemSelected,
)
}
An inventory of notes is handed to each NotesListComposable()
and NoteListDetailComposable()
composables. Full be aware textual content is not going to be displayed on a small or medium display screen dimension. Nonetheless, it’ll be obtainable for displaying on giant screens that present each the listing of notes and particulars of a be aware merchandise.
You’ve realized methods to construct adaptive apps whereas making certain information is offered throughout completely different gadget configurations. Subsequent, you’ll discover ways to take a look at your app compatibility throughout completely different display screen sizes and kind components.
Testing Apps for Massive Screens With Android Studio
To check your app compatibility with large-screen gadgets, Android Studio supplies the next capabilities:
- Reference gadgets: These embrace telephones, giant foldable internal show, tablets and desktops. You may create device-respective emulators in Android Studio. Then, you’ll use the emulators to check your app format throughout completely different gadgets.
- Resizable emulator: Resizeable emulator is offered in Android Studio chipmunk and better. It permits you to toggle between the 4 reference gadgets — cellphone, foldable, pill and desktop — to validate your app format at runtime.
- Format validation: Beginning Electrical Eel Canary 1, Android Studio will test for visible lint points throughout completely different display screen sizes. Whenever you open Format Validation, you’ll see all of your layouts render in a number of gadget sizes. If there’s a difficulty, it’ll present up within the Issues Panel. Visible linting will likely be obtainable for layouts written in Views or Compose.
Now, you’ll look into what to check to make sure your app compatibility in numerous display screen sizes and kind components.
Wanting Into What to Take a look at in Massive Screens
When you’ve arrange completely different gadget emulators, you’ll take a look at your app for widespread use instances for big screens. A few of the issues to check for embrace:
- Display screen sizes, gadget posture and orientation: Verify how your app responds to modifications in display screen sizes, gadget posture of a foldable and display screen orientation.
- Taskbar integration and cut up display screen mode: For Android 12L gadgets and better, guarantee your app UI isn’t blocked by the taskbar. Verify your app conduct while you enter multi-window mode utilizing the taskbar. Take a look at switching between your app and different apps utilizing the taskbar.
-
Multi-window mode: Verify your app conduct when operating in multi-window mode on giant screens when
android:resizeableActivity = false
in AndroidManifest file. Ifandroid:resizeableActivity = true
, test how your app responds when operating in multi-window mode on small-screen gadgets. - Media projection: In case your app makes use of media projection, test how your app responds whereas taking part in again, streaming or casting media on large-screen gadgets. Additionally test how the app responds to gadget posture modifications in a foldable.
- Digicam preview: For digital camera apps, test how the digital camera preview UI responds on giant screens when your app is in multi-window mode. Verify how your app responds to gadget posture modifications on a foldable gadget.
Checking Into Google Play Updates for Massive Screens
The Android group has up to date Google Play to focus on apps which might be optimized for big screens. They’ve added checks to evaluate apps in opposition to the big screens app high quality pointers listed right here. If an app isn’t optimized for big screens, customers on large-screen gadgets will likely be notified on the app’s Play Retailer itemizing web page.
They’ve additionally launched large-screen-specific app scores. Customers can price how your app works on their large-screen gadget.
Optimize your Android apps to make them simple to search out on Google Play!
The place to Go From Right here?
Obtain the finished undertaking information by clicking the Obtain Supplies button on the high or backside of the tutorial.
Congratulations! You may have efficiently made the Artful Pocket book App responsive throughout completely different gadgets. You may have realized methods to make your app adaptive to completely different display screen sizes and kind components utilizing Jetpack Compose. You’ve additionally realized methods to protect state throughout configuration modifications and Google Play updates for large-screen gadgets.
Massive screens are excellent for drag-and-drop interactions — throughout the app or between apps in multi-window mode. Try Android Drag and Drop to discover ways to add drag-and-drop capabilities to your app.
Try this Making certain Nice Enter Help for All Gadgets discuss to study supporting numerous enter strategies in all gadgets.
We hope you loved this tutorial. If in case you have any questions or feedback, please be part of the discussion board dialogue beneath!