Skip to content

Instantly share code, notes, and snippets.

@Karn
Created March 16, 2023 05:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Karn/3b744431514dbac0aeadd89a8f4b07da to your computer and use it in GitHub Desktop.
Save Karn/3b744431514dbac0aeadd89a8f4b07da to your computer and use it in GitHub Desktop.
Scroll Aware Lazy Column
import androidx.compose.foundation.Indication
import androidx.compose.foundation.LocalIndication
import androidx.compose.foundation.clickable
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.runtime.remember
import androidx.compose.runtime.staticCompositionLocalOf
import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.semantics.Role
val LocalLazyListScrollState = staticCompositionLocalOf { LazyListScrollStateProvider(null) }
class LazyListScrollStateProvider(private val listState: LazyListState?) {
val isScrolling: Boolean
get() = listState?.isScrollInProgress ?: false
}
fun Modifier.scrollAwareClickable(
enabled: Boolean = true,
onClickLabel: String? = null,
role: Role? = null,
onClick: () -> Unit
) = composed {
val scrollState = LocalLazyListScrollState.current
if (!scrollState.isScrolling) {
this.scrollAwareClickable(
enabled = enabled,
onClickLabel = onClickLabel,
onClick = onClick,
role = role,
indication = LocalIndication.current,
interactionSource = remember { MutableInteractionSource() }
)
} else {
this
}
}
fun Modifier.scrollAwareClickable(
interactionSource: MutableInteractionSource,
indication: Indication?,
enabled: Boolean = true,
onClickLabel: String? = null,
role: Role? = null,
onClick: () -> Unit
): Modifier = composed {
val scrollState = LocalLazyListScrollState.current
if (!scrollState.isScrolling) {
this.clickable(
interactionSource = interactionSource,
indication = indication,
enabled = enabled,
onClickLabel = onClickLabel,
role = role,
onClick = onClick
)
} else {
this
}
}
fun Modifier.scrollAwareCombinedClickable(
enabled: Boolean = true,
onClickLabel: String? = null,
role: Role? = null,
onLongClickLabel: String? = null,
onLongClick: (() -> Unit)? = null,
onDoubleClick: (() -> Unit)? = null,
onClick: () -> Unit
) = composed {
val scrollState = LocalLazyListScrollState.current
if (!scrollState.isScrolling) {
this.combinedClickable(
enabled = enabled,
onClickLabel = onClickLabel,
role = role,
onLongClickLabel = onLongClickLabel,
onLongClick = onLongClick,
onDoubleClick = onDoubleClick,
onClick = onClick
)
} else {
this
}
}
/**
* A wrapped LazyColumn that provides a [LazyListScrollStateProvider] to its children.
*/
@Composable
fun ScrollAwareLazyColumn(
modifier: Modifier = Modifier,
state: LazyListState = rememberLazyListState(),
contentPadding: PaddingValues = PaddingValues(0.dp),
reverseLayout: Boolean = false,
verticalArrangement: Arrangement.Vertical =
if (!reverseLayout) Arrangement.Top else Arrangement.Bottom,
horizontalAlignment: Alignment.Horizontal = Alignment.Start,
flingBehavior: FlingBehavior = ScrollableDefaults.flingBehavior(),
userScrollEnabled: Boolean = true,
content: LazyListScope.() -> Unit
) {
CompositionLocalProvider(LocalLazyListScrollState provides LazyListScrollStateProvider(state)) {
LazyColumn(
modifier = modifier,
state = state,
contentPadding = contentPadding,
reverseLayout = reverseLayout,
verticalArrangement = verticalArrangement,
horizontalAlignment = horizontalAlignment,
flingBehavior = flingBehavior,
userScrollEnabled = userScrollEnabled,
content = content
)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment