Skip to content

Commit

Permalink
new rememberResponsiveColumnState API (#2071)
Browse files Browse the repository at this point in the history
  • Loading branch information
yschimke authored Feb 28, 2024
1 parent 74b1093 commit 4fb9c92
Show file tree
Hide file tree
Showing 165 changed files with 1,765 additions and 2 deletions.
21 changes: 21 additions & 0 deletions compose-layout/api/current.api
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,31 @@ package com.google.android.horologist.compose.layout {

public final class ScalingLazyColumnDefaults {
method @com.google.android.horologist.annotations.ExperimentalHorologistApi public com.google.android.horologist.compose.layout.ScalingLazyColumnState.Factory belowTimeText(optional com.google.android.horologist.compose.layout.ScalingLazyColumnState.RotaryMode rotaryMode, optional boolean firstItemIsFullWidth, optional androidx.compose.foundation.layout.Arrangement.Vertical verticalArrangement, optional androidx.compose.ui.Alignment.Horizontal horizontalAlignment, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional float topPaddingDp);
method @androidx.compose.runtime.Composable public kotlin.jvm.functions.Function0<androidx.compose.foundation.layout.PaddingValues> padding(optional com.google.android.horologist.compose.layout.ScalingLazyColumnDefaults.ItemType first, optional com.google.android.horologist.compose.layout.ScalingLazyColumnDefaults.ItemType last, optional float horizontalPercent);
method @com.google.android.horologist.annotations.ExperimentalHorologistApi public com.google.android.horologist.compose.layout.ScalingLazyColumnState.Factory responsive(optional boolean firstItemIsFullWidth, optional float additionalPaddingAtBottom, optional androidx.compose.foundation.layout.Arrangement.Vertical verticalArrangement, optional float horizontalPaddingPercent, optional com.google.android.horologist.compose.layout.ScalingLazyColumnState.RotaryMode? rotaryMode, optional boolean hapticsEnabled, optional boolean reverseLayout, optional boolean userScrollEnabled);
method @com.google.android.horologist.annotations.ExperimentalHorologistApi public com.google.android.horologist.compose.layout.ScalingLazyColumnState.Factory scalingLazyColumnDefaults(optional com.google.android.horologist.compose.layout.ScalingLazyColumnState.RotaryMode rotaryMode, optional int initialCenterIndex, optional int initialCenterOffset, optional androidx.compose.foundation.layout.Arrangement.Vertical verticalArrangement, optional androidx.compose.ui.Alignment.Horizontal horizontalAlignment, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional androidx.wear.compose.foundation.lazy.AutoCenteringParams? autoCentering, optional int anchorType, optional boolean hapticsEnabled, optional boolean reverseLayout);
field public static final com.google.android.horologist.compose.layout.ScalingLazyColumnDefaults INSTANCE;
}

public enum ScalingLazyColumnDefaults.ItemType {
method public final float getBottomPaddingDp();
method public final float getPaddingCorrection();
method public final float getTopPaddingDp();
method public static com.google.android.horologist.compose.layout.ScalingLazyColumnDefaults.ItemType valueOf(String value) throws java.lang.IllegalArgumentException, java.lang.NullPointerException;
method public static com.google.android.horologist.compose.layout.ScalingLazyColumnDefaults.ItemType[] values();
property public final float bottomPaddingDp;
property public final float paddingCorrection;
property public final float topPaddingDp;
enum_constant public static final com.google.android.horologist.compose.layout.ScalingLazyColumnDefaults.ItemType Card;
enum_constant public static final com.google.android.horologist.compose.layout.ScalingLazyColumnDefaults.ItemType Chip;
enum_constant public static final com.google.android.horologist.compose.layout.ScalingLazyColumnDefaults.ItemType CompactChip;
enum_constant public static final com.google.android.horologist.compose.layout.ScalingLazyColumnDefaults.ItemType Icon;
enum_constant public static final com.google.android.horologist.compose.layout.ScalingLazyColumnDefaults.ItemType MultiButton;
enum_constant public static final com.google.android.horologist.compose.layout.ScalingLazyColumnDefaults.ItemType SingleButton;
enum_constant public static final com.google.android.horologist.compose.layout.ScalingLazyColumnDefaults.ItemType Text;
enum_constant public static final com.google.android.horologist.compose.layout.ScalingLazyColumnDefaults.ItemType Unspecified;
}

@com.google.android.horologist.annotations.ExperimentalHorologistApi public final class ScalingLazyColumnState implements androidx.compose.foundation.gestures.ScrollableState {
ctor public ScalingLazyColumnState(optional com.google.android.horologist.compose.layout.ScalingLazyColumnState.ScrollPosition initialScrollPosition, optional androidx.wear.compose.foundation.lazy.AutoCenteringParams? autoCentering, optional int anchorType, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional com.google.android.horologist.compose.layout.ScalingLazyColumnState.RotaryMode? rotaryMode, optional boolean reverseLayout, optional androidx.compose.foundation.layout.Arrangement.Vertical verticalArrangement, optional androidx.compose.ui.Alignment.Horizontal horizontalAlignment, optional androidx.compose.foundation.gestures.FlingBehavior? flingBehavior, optional boolean userScrollEnabled, optional androidx.wear.compose.foundation.lazy.ScalingParams scalingParams, optional boolean hapticsEnabled);
method public float dispatchRawDelta(float delta);
Expand Down Expand Up @@ -133,6 +153,7 @@ package com.google.android.horologist.compose.layout {
public final class ScalingLazyColumnStateKt {
method @androidx.compose.runtime.Composable @com.google.android.horologist.annotations.ExperimentalHorologistApi public static void ScalingLazyColumn(com.google.android.horologist.compose.layout.ScalingLazyColumnState columnState, optional androidx.compose.ui.Modifier modifier, kotlin.jvm.functions.Function1<? super androidx.wear.compose.foundation.lazy.ScalingLazyListScope,kotlin.Unit> content);
method @androidx.compose.runtime.Composable public static com.google.android.horologist.compose.layout.ScalingLazyColumnState rememberColumnState(optional com.google.android.horologist.compose.layout.ScalingLazyColumnState.Factory factory);
method @androidx.compose.runtime.Composable public static com.google.android.horologist.compose.layout.ScalingLazyColumnState rememberResponsiveColumnState(optional kotlin.jvm.functions.Function0<? extends androidx.compose.foundation.layout.PaddingValues> contentPadding, optional androidx.compose.foundation.layout.Arrangement.Vertical verticalArrangement, optional com.google.android.horologist.compose.layout.ScalingLazyColumnState.RotaryMode? rotaryMode, optional boolean hapticsEnabled, optional boolean reverseLayout, optional boolean userScrollEnabled);
}

public final class ScreenScaffoldKt {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.times
import androidx.compose.ui.util.lerp
import androidx.wear.compose.foundation.lazy.AutoCenteringParams
import androidx.wear.compose.foundation.lazy.ScalingLazyColumnDefaults
Expand All @@ -45,6 +46,7 @@ public object ScalingLazyColumnDefaults {
* This is positioned from the top of the screen instead of the
* center.
*/
// @Deprecated("Replaced by rememberResponsiveColumnState")
@ExperimentalHorologistApi
public fun belowTimeText(
rotaryMode: RotaryMode = RotaryMode.Scroll,
Expand Down Expand Up @@ -90,6 +92,7 @@ public object ScalingLazyColumnDefaults {
* Layout the item [initialCenterIndex] at [initialCenterOffset] from the
* center of the screen.
*/
// @Deprecated("Replaced by rememberResponsiveColumnState")
@ExperimentalHorologistApi
public fun scalingLazyColumnDefaults(
rotaryMode: RotaryMode = RotaryMode.Scroll,
Expand Down Expand Up @@ -148,6 +151,7 @@ public object ScalingLazyColumnDefaults {
* @param reverseLayout whether to start at the bottom.
* @param userScrollEnabled whether to allow user to scroll.
*/
// @Deprecated("Replaced by rememberResponsiveColumnState")
@ExperimentalHorologistApi
public fun responsive(
firstItemIsFullWidth: Boolean = true,
Expand Down Expand Up @@ -253,4 +257,39 @@ public object ScalingLazyColumnDefaults {
}
}
}

internal val Padding12Pct = 0.1248f
internal val Padding16Pct = 0.1664f
internal val Padding20Pct = 0.2083f
internal val Padding21Pct = 0.2188f
internal val Padding31Pct = 0.3646f

enum class ItemType(val topPaddingDp: Float, val bottomPaddingDp: Float, val paddingCorrection: Dp = 0.dp) {
Card(Padding21Pct, Padding31Pct),
Chip(Padding21Pct, Padding31Pct),
CompactChip(topPaddingDp = Padding12Pct, bottomPaddingDp = Padding20Pct, paddingCorrection = (-8).dp),
Icon(Padding12Pct, Padding21Pct),
MultiButton(Padding21Pct, Padding20Pct),
SingleButton(Padding12Pct, Padding20Pct),
Text(Padding21Pct, Padding31Pct),
Unspecified(0f, 0f),
}

@Composable
public fun padding(
first: ItemType = ItemType.Unspecified,
last: ItemType = ItemType.Unspecified,
horizontalPercent: Float = 0.052f,
): @Composable () -> PaddingValues {
return {
val height = LocalConfiguration.current.screenWidthDp.dp
val horizontalPadding = LocalConfiguration.current.screenWidthDp.dp * horizontalPercent
PaddingValues(
top = first.topPaddingDp * height + first.paddingCorrection,
bottom = last.bottomPaddingDp * height + first.paddingCorrection,
start = horizontalPadding,
end = horizontalPadding,
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.dp
import androidx.compose.ui.util.lerp
import androidx.wear.compose.foundation.ExperimentalWearFoundationApi
import androidx.wear.compose.foundation.lazy.AutoCenteringParams
import androidx.wear.compose.foundation.lazy.ScalingLazyColumn
Expand Down Expand Up @@ -121,6 +124,7 @@ public class ScalingLazyColumnState(
}
}

// @Deprecated("Replaced by rememberResponsiveColumnState")
@Composable
public fun rememberColumnState(
factory: ScalingLazyColumnState.Factory = ScalingLazyColumnDefaults.responsive(),
Expand All @@ -134,6 +138,77 @@ public fun rememberColumnState(
return columnState
}

@Composable
public fun rememberResponsiveColumnState(
contentPadding: @Composable () -> PaddingValues = ScalingLazyColumnDefaults.padding(
first = ScalingLazyColumnDefaults.ItemType.Unspecified,
last = ScalingLazyColumnDefaults.ItemType.Unspecified,
),
verticalArrangement: Arrangement.Vertical =
Arrangement.spacedBy(
space = 4.dp,
alignment = Alignment.Top,
),
rotaryMode: RotaryMode? = RotaryMode.Scroll,
hapticsEnabled: Boolean = true,
reverseLayout: Boolean = false,
userScrollEnabled: Boolean = true,
): ScalingLazyColumnState {
val density = LocalDensity.current
val configuration = LocalConfiguration.current
val screenWidthDp = configuration.screenWidthDp.toFloat()
val screenHeightDp = configuration.screenHeightDp.toFloat()

val sizeRatio =
((screenWidthDp - 192) / (233 - 192).toFloat()).coerceIn(0f, 1.5f)
val presetRatio = 0f

val minElementHeight = lerp(0.2f, 0.157f, sizeRatio)
val maxElementHeight =
lerp(0.6f, 0.472f, sizeRatio).coerceAtLeast(minElementHeight)
val minTransitionArea = lerp(0.35f, lerp(0.35f, 0.393f, presetRatio), sizeRatio)
val maxTransitionArea = lerp(0.55f, lerp(0.55f, 0.593f, presetRatio), sizeRatio)

val scalingParams = androidx.wear.compose.foundation.lazy.ScalingLazyColumnDefaults.scalingParams(
minElementHeight = minElementHeight,
maxElementHeight = maxElementHeight,
minTransitionArea = minTransitionArea,
maxTransitionArea = maxTransitionArea,
)

val contentPaddingCalculated = contentPadding()

val screenHeightPx =
with(density) { screenHeightDp.dp.roundToPx() }
val topPaddingPx = with(density) { contentPaddingCalculated.calculateTopPadding().roundToPx() }
val topScreenOffsetPx = screenHeightPx / 2 - topPaddingPx

val initialScrollPosition = ScalingLazyColumnState.ScrollPosition(
index = 0,
offsetPx = topScreenOffsetPx,
)

val columnState = ScalingLazyColumnState(
initialScrollPosition = initialScrollPosition,
autoCentering = null,
anchorType = ScalingLazyListAnchorType.ItemStart,
rotaryMode = rotaryMode,
verticalArrangement = verticalArrangement,
horizontalAlignment = Alignment.CenterHorizontally,
contentPadding = contentPaddingCalculated,
scalingParams = scalingParams,
hapticsEnabled = hapticsEnabled,
reverseLayout = reverseLayout,
userScrollEnabled = userScrollEnabled,
)

columnState.state = rememberSaveable(saver = ScalingLazyListState.Saver) {
columnState.state
}

return columnState
}

@ExperimentalHorologistApi
@Composable
public fun ScalingLazyColumn(
Expand Down
10 changes: 10 additions & 0 deletions compose-material/api/current.api
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,12 @@ package com.google.android.horologist.compose.material {
enum_constant public static final com.google.android.horologist.compose.material.IconRtlMode Mirrored;
}

public final class ListHeaderDefaults {
method @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.PaddingValues firstItemPadding();
method @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.PaddingValues itemPadding();
field public static final com.google.android.horologist.compose.material.ListHeaderDefaults INSTANCE;
}

public final class OutlinedChipKt {
method @androidx.compose.runtime.Composable @com.google.android.horologist.annotations.ExperimentalHorologistApi public static void OutlinedChip(@StringRes int labelId, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional com.google.android.horologist.compose.material.IconRtlMode iconRtlMode, optional @StringRes Integer? secondaryLabel, optional com.google.android.horologist.images.base.paintable.Paintable? icon, optional boolean largeIcon, optional androidx.wear.compose.material.ChipColors colors, optional boolean enabled);
method @androidx.compose.runtime.Composable @com.google.android.horologist.annotations.ExperimentalHorologistApi public static void OutlinedChip(String label, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional com.google.android.horologist.compose.material.IconRtlMode iconRtlMode, optional String? secondaryLabel, optional com.google.android.horologist.images.base.paintable.Paintable? icon, optional boolean largeIcon, optional androidx.wear.compose.material.ChipColors colors, optional boolean enabled);
Expand All @@ -96,6 +102,10 @@ package com.google.android.horologist.compose.material {
method @androidx.compose.runtime.Composable @com.google.android.horologist.annotations.ExperimentalHorologistApi public static void ResponsiveDialogContent(optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? icon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? title, optional kotlin.jvm.functions.Function0<kotlin.Unit>? message, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onOk, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onCancel, optional String okButtonContentDescription, optional String cancelButtonContentDescription, optional com.google.android.horologist.compose.layout.ScalingLazyColumnState state, optional boolean showPositionIndicator, optional kotlin.jvm.functions.Function1<? super androidx.wear.compose.foundation.lazy.ScalingLazyListScope,kotlin.Unit>? content);
}

public final class ResponsiveListHeaderKt {
method @androidx.compose.runtime.Composable public static void ResponsiveListHeader(optional androidx.compose.ui.Modifier modifier, optional long backgroundColor, optional long contentColor, optional androidx.compose.foundation.layout.PaddingValues contentPadding, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
}

public final class SplitToggleChipKt {
method @androidx.compose.runtime.Composable @com.google.android.horologist.annotations.ExperimentalHorologistApi public static void SplitToggleChip(boolean checked, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit> onCheckedChanged, String label, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, com.google.android.horologist.compose.material.ToggleChipToggleControl toggleControl, optional androidx.compose.ui.Modifier modifier, optional String? secondaryLabel, optional androidx.wear.compose.material.SplitToggleChipColors colors, optional boolean enabled, optional androidx.compose.foundation.interaction.MutableInteractionSource checkedInteractionSource, optional androidx.compose.foundation.interaction.MutableInteractionSource clickInteractionSource);
}
Expand Down
Loading

0 comments on commit 4fb9c92

Please sign in to comment.