mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-24 02:39:55 +01:00
Add breakpoint helper and expand device previews.
Co-authored-by: jeffrey-signal <jeffrey@signal.org>
This commit is contained in:
committed by
Greyson Parrelli
parent
a7bb2831f8
commit
264447a6d9
@@ -21,6 +21,9 @@ val WindowSizeClass.isWidthCompact
|
||||
val WindowSizeClass.isHeightCompact
|
||||
get() = !isHeightAtLeastBreakpoint(WindowSizeClass.HEIGHT_DP_MEDIUM_LOWER_BOUND)
|
||||
|
||||
val WindowSizeClass.isWidthExpanded
|
||||
get() = isWidthAtLeastBreakpoint(WindowSizeClass.WIDTH_DP_EXPANDED_LOWER_BOUND)
|
||||
|
||||
fun Resources.getWindowSizeClass(): WindowSizeClass {
|
||||
return WindowSizeClass.BREAKPOINTS_V1.computeWindowSizeClass(
|
||||
widthDp = displayMetrics.widthPixels / displayMetrics.density,
|
||||
@@ -28,6 +31,53 @@ fun Resources.getWindowSizeClass(): WindowSizeClass {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the device's form factor (PHONE, FOLDABLE, or TABLET) based on the current
|
||||
* [Resources] and window size class.
|
||||
*
|
||||
* This function uses several heuristics:
|
||||
* - Returns [WindowBreakpoint.SMALL] if the width or height is compact.
|
||||
* - Returns [WindowBreakpoint.LARGE] if the height is at least the expanded lower bound.
|
||||
* - Returns [WindowBreakpoint.MEDIUM] if the width is at least the medium lower bound.
|
||||
* - Otherwise, falls back to aspect ratio heuristics: wider (≥ 1.6) is [WindowBreakpoint.LARGE], else [WindowBreakpoint.MEDIUM].
|
||||
*
|
||||
* @return the inferred [WindowBreakpoint] for the current device.
|
||||
*/
|
||||
fun Resources.getWindowBreakpoint(): WindowBreakpoint {
|
||||
val windowSizeClass = getWindowSizeClass()
|
||||
|
||||
if (windowSizeClass.isWidthCompact || windowSizeClass.isHeightCompact) {
|
||||
return WindowBreakpoint.SMALL
|
||||
}
|
||||
|
||||
if (windowSizeClass.isHeightAtLeastBreakpoint(WindowSizeClass.HEIGHT_DP_EXPANDED_LOWER_BOUND)) {
|
||||
return WindowBreakpoint.LARGE
|
||||
}
|
||||
|
||||
val numerator = maxOf(displayMetrics.widthPixels, displayMetrics.heightPixels)
|
||||
val denominator = minOf(displayMetrics.widthPixels, displayMetrics.heightPixels)
|
||||
val aspectRatio = numerator.toFloat() / denominator
|
||||
|
||||
return if (aspectRatio >= 1.6f) {
|
||||
WindowBreakpoint.LARGE
|
||||
} else {
|
||||
WindowBreakpoint.MEDIUM
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates the general form factor of the device for responsive UI purposes.
|
||||
*
|
||||
* - [SMALL]: A window similar to a phone-sized device, typically with a compact width or height.
|
||||
* - [MEDIUM]: A window similar to a foldable or medium-size device, or a device which doesn't obviously fit into phone or tablet by heuristics.
|
||||
* - [LARGE]: A window similar to a large-screen tablet device, typically with an expanded height or wide aspect ratio.
|
||||
*/
|
||||
enum class WindowBreakpoint {
|
||||
SMALL,
|
||||
MEDIUM,
|
||||
LARGE
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the UI should display in split-pane mode based on available screen space.
|
||||
*/
|
||||
@@ -40,7 +90,7 @@ fun WindowSizeClass.isSplitPane(
|
||||
}
|
||||
|
||||
return isAtLeastBreakpoint(
|
||||
widthDpBreakpoint = WindowSizeClass.WIDTH_DP_EXPANDED_LOWER_BOUND,
|
||||
widthDpBreakpoint = WindowSizeClass.WIDTH_DP_MEDIUM_LOWER_BOUND,
|
||||
heightDpBreakpoint = WindowSizeClass.HEIGHT_DP_MEDIUM_LOWER_BOUND
|
||||
)
|
||||
}
|
||||
|
||||
@@ -19,27 +19,109 @@ annotation class NightPreview()
|
||||
annotation class DayNightPreviews
|
||||
|
||||
@Preview(name = "phone portrait (day)", uiMode = Configuration.UI_MODE_NIGHT_NO, device = "spec:width=360dp,height=640dp,orientation=portrait")
|
||||
@Preview(name = "phone portrait (night)", uiMode = Configuration.UI_MODE_NIGHT_YES, device = "spec:width=360dp,height=640dp,orientation=portrait")
|
||||
annotation class PhonePortraitDayPreview
|
||||
|
||||
@Preview(name = "phone landscape (day)", uiMode = Configuration.UI_MODE_NIGHT_NO, device = "spec:width=640dp,height=360dp,orientation=landscape")
|
||||
annotation class PhoneLandscapeDayPreview
|
||||
|
||||
@PhonePortraitDayPreview
|
||||
@PhoneLandscapeDayPreview
|
||||
annotation class PhoneDayPreviews
|
||||
|
||||
@Preview(name = "phone portrait (night)", uiMode = Configuration.UI_MODE_NIGHT_YES, device = "spec:width=360dp,height=640dp,orientation=portrait")
|
||||
annotation class PhonePortraitNightPreview
|
||||
|
||||
@Preview(name = "phone landscape (night)", uiMode = Configuration.UI_MODE_NIGHT_YES, device = "spec:width=640dp,height=360dp,orientation=landscape")
|
||||
annotation class PhoneLandscapeNightPreview
|
||||
|
||||
@PhonePortraitNightPreview
|
||||
@PhoneLandscapeNightPreview
|
||||
annotation class PhoneNightPreviews
|
||||
|
||||
@PhoneDayPreviews
|
||||
@PhoneLandscapeNightPreview
|
||||
annotation class PhonePreviews
|
||||
|
||||
@Preview(name = "foldable portrait (day)", uiMode = Configuration.UI_MODE_NIGHT_NO, device = "spec:width=600dp,height=1024dp,orientation=portrait")
|
||||
@Preview(name = "foldable landscape (night)", uiMode = Configuration.UI_MODE_NIGHT_YES, device = "spec:width=1024dp,height=600dp,orientation=landscape")
|
||||
@Preview(name = "small foldable portrait (day)", uiMode = Configuration.UI_MODE_NIGHT_NO, device = "spec:width=620dp,height=720dp,orientation=portrait")
|
||||
annotation class SmallFoldablePortraitDayPreview
|
||||
|
||||
@Preview(name = "small foldable landscape (day)", uiMode = Configuration.UI_MODE_NIGHT_NO, device = "spec:width=720dp,height=620dp,orientation=landscape")
|
||||
annotation class SmallFoldableLandscapeDayPreview
|
||||
|
||||
@SmallFoldablePortraitDayPreview
|
||||
@SmallFoldableLandscapeDayPreview
|
||||
annotation class SmallFoldableDayPreviews
|
||||
|
||||
@Preview(name = "small foldable portrait (night)", uiMode = Configuration.UI_MODE_NIGHT_YES, device = "spec:width=620dp,height=720dp,orientation=portrait")
|
||||
annotation class SmallFoldablePortraitNightPreview
|
||||
|
||||
@Preview(name = "small foldable landscape (night)", uiMode = Configuration.UI_MODE_NIGHT_YES, device = "spec:width=720dp,height=620dp,orientation=landscape")
|
||||
annotation class SmallFoldableLandscapeNightPreview
|
||||
|
||||
@SmallFoldablePortraitNightPreview
|
||||
@SmallFoldableLandscapeNightPreview
|
||||
annotation class SmallFoldableNightPreviews
|
||||
|
||||
@SmallFoldableDayPreviews
|
||||
@SmallFoldableLandscapeNightPreview
|
||||
annotation class SmallFoldablePreviews
|
||||
|
||||
@Preview(name = "foldable portrait (day)", uiMode = Configuration.UI_MODE_NIGHT_NO, device = "spec:width=850dp,height=881dp,orientation=portrait")
|
||||
annotation class FoldablePortraitDayPreview
|
||||
|
||||
@Preview(name = "foldable landscape (day)", uiMode = Configuration.UI_MODE_NIGHT_NO, device = "spec:width=881dp,height=850dp,orientation=landscape")
|
||||
annotation class FoldableLandscapeDayPreview
|
||||
|
||||
@FoldablePortraitDayPreview
|
||||
@FoldableLandscapeDayPreview
|
||||
annotation class FoldableDayPreviews
|
||||
|
||||
@Preview(name = "foldable portrait (night)", uiMode = Configuration.UI_MODE_NIGHT_YES, device = "spec:width=850dp,height=881dp,orientation=portrait")
|
||||
annotation class FoldablePortraitNightPreview
|
||||
|
||||
@Preview(name = "foldable landscape (night)", uiMode = Configuration.UI_MODE_NIGHT_YES, device = "spec:width=881dp,height=850dp,orientation=landscape")
|
||||
annotation class FoldableLandscapeNightPreview
|
||||
|
||||
@FoldablePortraitNightPreview
|
||||
@FoldableLandscapeNightPreview
|
||||
annotation class FoldableNightPreviews
|
||||
|
||||
@FoldableDayPreviews
|
||||
@FoldableLandscapeNightPreview
|
||||
annotation class FoldablePreviews
|
||||
|
||||
@Preview(name = "tablet portrait (night)", uiMode = Configuration.UI_MODE_NIGHT_YES, device = "spec:width=840dp,height=1280dp,orientation=portrait")
|
||||
@Preview(name = "tablet portrait (day)", uiMode = Configuration.UI_MODE_NIGHT_NO, device = "spec:width=840dp,height=1280dp,orientation=portrait")
|
||||
annotation class TabletPortraitDayPreview
|
||||
|
||||
@Preview(name = "tablet landscape (day)", uiMode = Configuration.UI_MODE_NIGHT_NO, device = "spec:width=1280dp,height=840dp,orientation=landscape")
|
||||
annotation class TabletLandscapeDayPreview
|
||||
|
||||
@TabletPortraitDayPreview
|
||||
@TabletLandscapeDayPreview
|
||||
annotation class TabletDayPreviews
|
||||
|
||||
@Preview(name = "tablet portrait (night)", uiMode = Configuration.UI_MODE_NIGHT_YES, device = "spec:width=1280dp,height=840dp,orientation=portrait")
|
||||
annotation class TabletPortraitNightPreview
|
||||
|
||||
@Preview(name = "tablet landscape (night)", uiMode = Configuration.UI_MODE_NIGHT_YES, device = "spec:width=840dp,height=1280dp,orientation=landscape")
|
||||
annotation class TabletLandscapeNightPreview
|
||||
|
||||
@TabletPortraitNightPreview
|
||||
@TabletLandscapeNightPreview
|
||||
annotation class TabletNightPreviews
|
||||
|
||||
@TabletDayPreviews
|
||||
@TabletLandscapeNightPreview
|
||||
annotation class TabletPreviews
|
||||
|
||||
@Preview(name = "phone portrait (night)", uiMode = Configuration.UI_MODE_NIGHT_YES, device = "spec:width=360dp,height=640dp,orientation=portrait")
|
||||
@Preview(name = "phone landscape (night)", uiMode = Configuration.UI_MODE_NIGHT_YES, device = "spec:width=640dp,height=360dp,orientation=landscape")
|
||||
@Preview(name = "foldable portrait (night)", uiMode = Configuration.UI_MODE_NIGHT_YES, device = "spec:width=600dp,height=1024dp,orientation=portrait")
|
||||
@Preview(name = "foldable landscape (night)", uiMode = Configuration.UI_MODE_NIGHT_YES, device = "spec:width=1024dp,height=600dp,orientation=landscape")
|
||||
@Preview(name = "tablet portrait (night)", uiMode = Configuration.UI_MODE_NIGHT_YES, device = "spec:width=840dp,height=1280dp,orientation=portrait")
|
||||
@Preview(name = "tablet landscape (night)", uiMode = Configuration.UI_MODE_NIGHT_YES, device = "spec:width=1280dp,height=840dp,orientation=landscape")
|
||||
@PhoneNightPreviews
|
||||
@SmallFoldableNightPreviews
|
||||
@FoldableNightPreviews
|
||||
@TabletNightPreviews
|
||||
annotation class AllNightPreviews
|
||||
|
||||
@PhonePreviews
|
||||
@SmallFoldablePreviews
|
||||
@FoldablePreviews
|
||||
@TabletPreviews
|
||||
annotation class AllDevicePreviews
|
||||
|
||||
Reference in New Issue
Block a user