From 0642d745a98ec375a8a234f188ccd978407d0459 Mon Sep 17 00:00:00 2001 From: Xinto Date: Mon, 25 Dec 2023 18:56:14 +0400 Subject: [PATCH 1/3] simplify layouts --- .../materii/pullrefresh/demo/MainActivity.kt | 8 +- .../demo/sample/DragRefreshSample.kt | 19 ++-- .../demo/sample/PullRefreshSample.kt | 37 ++++---- gradle/libs.versions.toml | 12 +-- .../materii/pullrefresh/DragRefreshLayout.kt | 88 ++++++++++++++++++- .../pullrefresh/PullRefreshIndicator.kt | 36 +++++++- .../materii/pullrefresh/PullRefreshLayout.kt | 56 ++++++++++++ .../PullRequestIndicatorTransform.kt | 1 + 8 files changed, 218 insertions(+), 39 deletions(-) create mode 100644 pullrefresh/src/commonMain/kotlin/dev/materii/pullrefresh/PullRefreshLayout.kt diff --git a/demo/src/main/java/dev/materii/pullrefresh/demo/MainActivity.kt b/demo/src/main/java/dev/materii/pullrefresh/demo/MainActivity.kt index 05a8de6..1dcbba6 100644 --- a/demo/src/main/java/dev/materii/pullrefresh/demo/MainActivity.kt +++ b/demo/src/main/java/dev/materii/pullrefresh/demo/MainActivity.kt @@ -90,8 +90,7 @@ class MainActivity : ComponentActivity() { } ) }, - modifier = Modifier - .pullRefresh(pullRefreshState, inverse = flipped) + modifier = Modifier.fillMaxSize() ) { Column( modifier = Modifier.padding(it) @@ -130,12 +129,13 @@ class MainActivity : ComponentActivity() { 0 -> PullRefreshSample( flipped = flipped, pullRefreshState = pullRefreshState, - isRefreshing = isRefreshing + modifier = Modifier.fillMaxSize(), ) 1 -> DragRefreshSample( flipped = flipped, - pullRefreshState = pullRefreshState + pullRefreshState = pullRefreshState, + modifier = Modifier.fillMaxSize(), ) } } diff --git a/demo/src/main/java/dev/materii/pullrefresh/demo/sample/DragRefreshSample.kt b/demo/src/main/java/dev/materii/pullrefresh/demo/sample/DragRefreshSample.kt index bdd6284..a497ef2 100644 --- a/demo/src/main/java/dev/materii/pullrefresh/demo/sample/DragRefreshSample.kt +++ b/demo/src/main/java/dev/materii/pullrefresh/demo/sample/DragRefreshSample.kt @@ -4,11 +4,13 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import dev.materii.pullrefresh.DragRefreshLayout +import dev.materii.pullrefresh.DragRefreshIndicator import dev.materii.pullrefresh.PullRefreshState @Composable @@ -18,16 +20,21 @@ fun DragRefreshSample( modifier: Modifier = Modifier ) { DragRefreshLayout( + modifier = modifier, state = pullRefreshState, - flipped = flipped, - modifier = modifier - .fillMaxSize() + indicator = { + DragRefreshIndicator( + state = pullRefreshState, + flipped = flipped, + color = MaterialTheme.colorScheme.primary + ) + } ) { Box( - contentAlignment = Alignment.Center, - modifier = modifier + modifier = Modifier .fillMaxSize() - .verticalScroll(rememberScrollState()) + .verticalScroll(rememberScrollState()), + contentAlignment = Alignment.Center ) { Text(text = "Pull ${if (flipped) "up" else "down"} to refresh") } diff --git a/demo/src/main/java/dev/materii/pullrefresh/demo/sample/PullRefreshSample.kt b/demo/src/main/java/dev/materii/pullrefresh/demo/sample/PullRefreshSample.kt index 230ae00..3b902c1 100644 --- a/demo/src/main/java/dev/materii/pullrefresh/demo/sample/PullRefreshSample.kt +++ b/demo/src/main/java/dev/materii/pullrefresh/demo/sample/PullRefreshSample.kt @@ -11,6 +11,7 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp +import dev.materii.pullrefresh.PullRefreshLayout import dev.materii.pullrefresh.PullRefreshIndicator import dev.materii.pullrefresh.PullRefreshState @@ -18,27 +19,27 @@ import dev.materii.pullrefresh.PullRefreshState fun PullRefreshSample( flipped: Boolean, pullRefreshState: PullRefreshState, - isRefreshing: Boolean, modifier: Modifier = Modifier ) { - Box( - contentAlignment = Alignment.Center, - modifier = modifier - .fillMaxSize() - .verticalScroll(rememberScrollState()) + PullRefreshLayout( + modifier = modifier, + state = pullRefreshState, + indicator = { + PullRefreshIndicator( + state = pullRefreshState, + flipped = flipped, + backgroundColor = MaterialTheme.colorScheme.surfaceColorAtElevation(3.dp), + contentColor = MaterialTheme.colorScheme.primary + ) + } ) { - Text(text = "Pull ${if (flipped) "up" else "down"} to refresh") - - PullRefreshIndicator( - refreshing = isRefreshing, - state = pullRefreshState, - flipped = flipped, - backgroundColor = MaterialTheme.colorScheme.surfaceColorAtElevation(3.dp), - contentColor = MaterialTheme.colorScheme.primary, + Box( modifier = Modifier - .align( - if (flipped) Alignment.BottomCenter else Alignment.TopCenter - ) - ) + .fillMaxSize() + .verticalScroll(rememberScrollState()), + contentAlignment = Alignment.Center + ) { + Text(text = "Pull ${if (flipped) "up" else "down"} to refresh") + } } } \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index c9a96d3..fb10ee4 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,15 +1,15 @@ [versions] -agp = "8.1.3" -kotlin = "1.9.20" -compose-multiplatform = "1.5.10" -compose-compiler = "1.5.4" +agp = "8.2.0" +kotlin = "1.9.21" +compose-multiplatform = "1.5.11" +compose-compiler = "1.5.7" core-ktx = "1.12.0" [libraries] core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "core-ktx" } lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version = "2.6.2" } -activity-compose = { group = "androidx.activity", name = "activity-compose", version = "1.8.0" } -material3 = { group = "androidx.compose.material3", name = "material3", version = "1.2.0-alpha09" } +activity-compose = { group = "androidx.activity", name = "activity-compose", version = "1.8.2" } +material3 = { group = "androidx.compose.material3", name = "material3", version = "1.2.0-alpha09" } #TODO later versions depend on beta foundation, resulting in incompatibility material-icons-extended = { group = "androidx.compose.material", name = "material-icons-extended", version = "1.5.4" } [plugins] diff --git a/pullrefresh/src/commonMain/kotlin/dev/materii/pullrefresh/DragRefreshLayout.kt b/pullrefresh/src/commonMain/kotlin/dev/materii/pullrefresh/DragRefreshLayout.kt index 3af2554..3b5a1eb 100644 --- a/pullrefresh/src/commonMain/kotlin/dev/materii/pullrefresh/DragRefreshLayout.kt +++ b/pullrefresh/src/commonMain/kotlin/dev/materii/pullrefresh/DragRefreshLayout.kt @@ -6,6 +6,9 @@ import androidx.compose.foundation.layout.BoxScope import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.runtime.Composable +import androidx.compose.runtime.derivedStateOf +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip @@ -25,6 +28,20 @@ import androidx.compose.ui.platform.LocalDensity * @param indicator The indicator hidden beneath the [content], normally an arrow facing in the drag direction * @param content Content to be dragged */ +@Deprecated( + message = "Use the overload without `contentAlignment` instead", + replaceWith = ReplaceWith( + "DragRefreshBox(\n" + + "state = state,\n" + + "modifier = modifier,\n" + + "flipped = flipped,\n" + + "backdrop = indicatorBackground,\n" + + "indicator = indicator,\n" + + "content = content,\n" + + ")" + ), + level = DeprecationLevel.HIDDEN +) @Composable fun DragRefreshLayout( state: PullRefreshState, @@ -37,7 +54,6 @@ fun DragRefreshLayout( state = state, color = Color.White, flipped = flipped, - modifier = Modifier.align(Alignment.Center) ) }, content: @Composable () -> Unit @@ -56,7 +72,7 @@ fun DragRefreshLayout( .fillMaxWidth() .clip(RectangleShape) .align( - if (flipped) Alignment.BottomStart else Alignment.TopStart + if (flipped) Alignment.BottomCenter else Alignment.TopCenter ) ) { indicator() @@ -76,3 +92,71 @@ fun DragRefreshLayout( } } +/** + * Layout for drag to refresh, dragging moves the [content] to reveal the [indicator] beneath + * + * @param state [PullRefreshState] used to updated the [content]'s position + * @param modifier [Modifier] for the layout + * @param flipped If true reveals the indicator on the bottom instead of the top + * @param backdropColor Color to use for the revealed background, a darker version of the [content]'s background is recommended + * @param indicator The indicator hidden beneath the [content], normally an arrow facing in the drag direction + * @param content Content to be dragged + */ +@Composable +fun DragRefreshLayout( + state: PullRefreshState, + modifier: Modifier = Modifier, + flipped: Boolean = false, + enabled: Boolean = true, + indicator: @Composable () -> Unit = { + DragRefreshIndicator( + state = state, + flipped = flipped + ) + }, + backdropColor: Color = Color.Black.copy(alpha = 0.3f), + content: @Composable () -> Unit +) { + Box( + modifier = Modifier + .pullRefresh( + state = state, + inverse = flipped, + enabled = enabled, + ) + .then(modifier) + ) { + val density = LocalDensity.current + val indicatorHeight by remember(density) { + derivedStateOf { + with(density) { + state.position.toDp() + } + } + } + val indicatorAlignment = remember(flipped) { + if (flipped) Alignment.BottomCenter else Alignment.TopCenter + } + Box( + modifier = Modifier + .background(backdropColor) + .height(indicatorHeight) + .fillMaxWidth() + .align(indicatorAlignment), + contentAlignment = Alignment.Center, + ) { + indicator() + } + + Box( + modifier = Modifier + .graphicsLayer { + translationY = if (flipped) -state.position else state.position + clip = true + shape = RectangleShape + }, + ) { + content() + } + } +} \ No newline at end of file diff --git a/pullrefresh/src/commonMain/kotlin/dev/materii/pullrefresh/PullRefreshIndicator.kt b/pullrefresh/src/commonMain/kotlin/dev/materii/pullrefresh/PullRefreshIndicator.kt index ed089eb..5703218 100644 --- a/pullrefresh/src/commonMain/kotlin/dev/materii/pullrefresh/PullRefreshIndicator.kt +++ b/pullrefresh/src/commonMain/kotlin/dev/materii/pullrefresh/PullRefreshIndicator.kt @@ -62,6 +62,19 @@ import kotlin.math.pow * @param flipped Whether the indicator is drawn emanating from the bottom instead. * This should be used with the `inverse` param of `pullRefresh`. */ +@Deprecated( + message = "Use the overload without `refreshing` instead", + replaceWith = ReplaceWith( + "PullRefreshIndicator(" + + "state = state,\n" + + "modifier = modifier,\n" + + "backgroundColor = backgroundColor,\n" + + "contentColor = contentColor,\n" + + "scale = scale,\n" + + "flipped = flipped," + + ")" + ) +) @Composable fun PullRefreshIndicator( refreshing: Boolean, @@ -71,9 +84,26 @@ fun PullRefreshIndicator( contentColor: Color = Color.Blue, scale: Boolean = false, flipped: Boolean = false, +) = PullRefreshIndicator( + state = state, + modifier = modifier, + backgroundColor = backgroundColor, + contentColor = contentColor, + scale = scale, + flipped = flipped +) + +@Composable +fun PullRefreshIndicator( + state: PullRefreshState, + modifier: Modifier = Modifier, + backgroundColor: Color = Color.White, + contentColor: Color = Color.Blue, + scale: Boolean = false, + flipped: Boolean = false, ) { - val showElevation by remember(refreshing, state) { - derivedStateOf { refreshing || state.position > 0.5f } + val showElevation by remember(state) { + derivedStateOf { state.refreshing || state.position > 0.5f } } Box( @@ -84,7 +114,7 @@ fun PullRefreshIndicator( .background(color = backgroundColor, shape = SpinnerShape) ) { Crossfade( - targetState = refreshing, + targetState = state.refreshing, animationSpec = tween(durationMillis = CrossfadeDurationMs), label = "Refresh" ) { refreshing -> diff --git a/pullrefresh/src/commonMain/kotlin/dev/materii/pullrefresh/PullRefreshLayout.kt b/pullrefresh/src/commonMain/kotlin/dev/materii/pullrefresh/PullRefreshLayout.kt new file mode 100644 index 0000000..7f11553 --- /dev/null +++ b/pullrefresh/src/commonMain/kotlin/dev/materii/pullrefresh/PullRefreshLayout.kt @@ -0,0 +1,56 @@ +package dev.materii.pullrefresh + +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier + +/** + * Layout for pull to refresh + * + * @param state [PullRefreshState] + * @param modifier [Modifier] for the layout + * @param flipped If true reveals the indicator on the bottom instead of the top + * @param indicator [PullRefreshIndicator] + * @param content The content of the box + */ +@Composable +fun PullRefreshLayout( + state: PullRefreshState, + modifier: Modifier = Modifier, + flipped: Boolean = false, + enabled: Boolean = true, + indicator: @Composable () -> Unit = { + PullRefreshIndicator( + state = state, + flipped = flipped + ) + }, + content: @Composable () -> Unit +) { + Box( + modifier = Modifier + .pullRefresh( + state = state, + inverse = flipped, + enabled = enabled + ) + .then(modifier) + ) { + val indicatorAlignment = remember(flipped) { + if (flipped) Alignment.BottomCenter else Alignment.TopCenter + } + Box( + modifier = Modifier + .fillMaxWidth() + .align(indicatorAlignment), + contentAlignment = Alignment.Center + ) { + indicator() + } + + content() + } +} \ No newline at end of file diff --git a/pullrefresh/src/commonMain/kotlin/dev/materii/pullrefresh/PullRequestIndicatorTransform.kt b/pullrefresh/src/commonMain/kotlin/dev/materii/pullrefresh/PullRequestIndicatorTransform.kt index 0d58be9..e48f19b 100644 --- a/pullrefresh/src/commonMain/kotlin/dev/materii/pullrefresh/PullRequestIndicatorTransform.kt +++ b/pullrefresh/src/commonMain/kotlin/dev/materii/pullrefresh/PullRequestIndicatorTransform.kt @@ -41,6 +41,7 @@ fun Modifier.pullRefreshIndicatorTransform( name = "pullRefreshIndicatorTransform" properties["state"] = state properties["scale"] = scale + properties["flipped"] = flipped } ) { Modifier From 2447cad0e278889055dd97a917647b8d4c119748 Mon Sep 17 00:00:00 2001 From: Xinto Date: Mon, 25 Dec 2023 21:35:41 +0400 Subject: [PATCH 2/3] don't remember alignment --- .../kotlin/dev/materii/pullrefresh/DragRefreshLayout.kt | 4 +--- .../kotlin/dev/materii/pullrefresh/PullRefreshLayout.kt | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/pullrefresh/src/commonMain/kotlin/dev/materii/pullrefresh/DragRefreshLayout.kt b/pullrefresh/src/commonMain/kotlin/dev/materii/pullrefresh/DragRefreshLayout.kt index 3b5a1eb..2e46b51 100644 --- a/pullrefresh/src/commonMain/kotlin/dev/materii/pullrefresh/DragRefreshLayout.kt +++ b/pullrefresh/src/commonMain/kotlin/dev/materii/pullrefresh/DragRefreshLayout.kt @@ -134,9 +134,7 @@ fun DragRefreshLayout( } } } - val indicatorAlignment = remember(flipped) { - if (flipped) Alignment.BottomCenter else Alignment.TopCenter - } + val indicatorAlignment = if (flipped) Alignment.BottomCenter else Alignment.TopCenter Box( modifier = Modifier .background(backdropColor) diff --git a/pullrefresh/src/commonMain/kotlin/dev/materii/pullrefresh/PullRefreshLayout.kt b/pullrefresh/src/commonMain/kotlin/dev/materii/pullrefresh/PullRefreshLayout.kt index 7f11553..0d891a5 100644 --- a/pullrefresh/src/commonMain/kotlin/dev/materii/pullrefresh/PullRefreshLayout.kt +++ b/pullrefresh/src/commonMain/kotlin/dev/materii/pullrefresh/PullRefreshLayout.kt @@ -39,9 +39,7 @@ fun PullRefreshLayout( ) .then(modifier) ) { - val indicatorAlignment = remember(flipped) { - if (flipped) Alignment.BottomCenter else Alignment.TopCenter - } + val indicatorAlignment = if (flipped) Alignment.BottomCenter else Alignment.TopCenter Box( modifier = Modifier .fillMaxWidth() From 2780ab9532269557bd1a62cbf58166c99d89c37b Mon Sep 17 00:00:00 2001 From: Wing <44992537+wingio@users.noreply.github.com> Date: Mon, 29 Jan 2024 17:01:31 -0500 Subject: [PATCH 3/3] Add missing parameter in samples and update README --- README.md | 56 ++++++------------- .../demo/sample/DragRefreshSample.kt | 1 + .../demo/sample/PullRefreshSample.kt | 1 + 3 files changed, 19 insertions(+), 39 deletions(-) diff --git a/README.md b/README.md index 5448653..ab4dd49 100644 --- a/README.md +++ b/README.md @@ -36,27 +36,17 @@ materii-pullrefresh = { group = "dev.materii.pullrefresh", name = "pullrefresh", ```kt @Composable fun Test() { - var isRefreshing by remember { - mutableStateOf(false) - } - var pullRefreshState = rememberPullRefreshState(refreshing = isRefreshing, onRefresh = { /* Refresh some data here */ }) - - Scaffold( - modifier = Modifier.pullRefresh(pullRefreshState) - ) { - Box( - contentAlignment = Alignment.Center, - modifier = Modifier - .padding(it) - .fillMaxSize() - .verticalScroll(rememberScrollState()) + var isRefreshing by remember { + mutableStateOf(false) + } + var pullRefreshState = rememberPullRefreshState(refreshing = isRefreshing, onRefresh = { /* Refresh some data here */ }) + + PullRefreshLayout( + modifier = modifier, + state = pullRefreshState ) { - PullRefreshIndicator( - refreshing = isRefreshing, - state = pullRefreshState, - modifier = Modifier.align(Alignment.TopCenter) - ) - } + Text("Some content") + } } ``` @@ -70,28 +60,16 @@ fun Test() { ```kt @Composable fun Test() { - var isRefreshing by remember { - mutableStateOf(false) - } - var pullRefreshState = rememberPullRefreshState(refreshing = isRefreshing, onRefresh = { /* Refresh some data here */ }) - - Scaffold( - modifier = Modifier.pullRefresh(pullRefreshState) - ) { + var isRefreshing by remember { + mutableStateOf(false) + } + var pullRefreshState = rememberPullRefreshState(refreshing = isRefreshing, onRefresh = { /* Refresh some data here */ }) + DragRefreshLayout( - state = pullRefreshState - modifier = modifier - .padding(it) - .fillMaxSize() + modifier = modifier, + state = pullRefreshState ) { - Box( - contentAlignment = Alignment.Center, - modifier = Modifier - .fillMaxSize() - .verticalScroll(rememberScrollState()) - ) { Text("Some content") - } } } ``` diff --git a/demo/src/main/java/dev/materii/pullrefresh/demo/sample/DragRefreshSample.kt b/demo/src/main/java/dev/materii/pullrefresh/demo/sample/DragRefreshSample.kt index a497ef2..fe6edc4 100644 --- a/demo/src/main/java/dev/materii/pullrefresh/demo/sample/DragRefreshSample.kt +++ b/demo/src/main/java/dev/materii/pullrefresh/demo/sample/DragRefreshSample.kt @@ -22,6 +22,7 @@ fun DragRefreshSample( DragRefreshLayout( modifier = modifier, state = pullRefreshState, + flipped = flipped, indicator = { DragRefreshIndicator( state = pullRefreshState, diff --git a/demo/src/main/java/dev/materii/pullrefresh/demo/sample/PullRefreshSample.kt b/demo/src/main/java/dev/materii/pullrefresh/demo/sample/PullRefreshSample.kt index 3b902c1..d3d8d18 100644 --- a/demo/src/main/java/dev/materii/pullrefresh/demo/sample/PullRefreshSample.kt +++ b/demo/src/main/java/dev/materii/pullrefresh/demo/sample/PullRefreshSample.kt @@ -24,6 +24,7 @@ fun PullRefreshSample( PullRefreshLayout( modifier = modifier, state = pullRefreshState, + flipped = flipped, indicator = { PullRefreshIndicator( state = pullRefreshState,