feat(ui): add scroll indicator to webview reader + feeds page & style tweaks

This commit is contained in:
junkfood
2026-01-26 00:23:05 +08:00
parent f9392702ab
commit cf8515c033
4 changed files with 44 additions and 16 deletions

View File

@@ -3,7 +3,11 @@ package me.ash.reader.ui.component.scrollbar
import androidx.compose.animation.core.Animatable
import androidx.compose.animation.core.spring
import androidx.compose.foundation.ScrollIndicatorState
import androidx.compose.foundation.ScrollState
import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.CornerRadius
@@ -14,16 +18,37 @@ import androidx.compose.ui.graphics.drawscope.ContentDrawScope
import androidx.compose.ui.node.DelegatableNode
import androidx.compose.ui.node.DrawModifierNode
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
private val ThumbColor
@Composable get() = MaterialTheme.colorScheme.outline.copy(alpha = .5f)
@Composable
fun Modifier.drawVerticalScrollIndicator(scrollState: ScrollState): Modifier {
return this.scrollIndicator(
VerticalScrollIndicatorFactory(thumbColor = ThumbColor),
scrollState.scrollIndicatorState!!,
Orientation.Vertical,
)
}
@Composable
fun Modifier.drawVerticalScrollIndicator(listState: LazyListState): Modifier {
return this.scrollIndicator(
VerticalScrollIndicatorFactory(thumbColor = ThumbColor),
listState.scrollIndicatorState!!,
Orientation.Vertical,
)
}
data class VerticalScrollIndicatorFactory(
val thumbThickness: Dp = 4.dp,
val padding: Dp = 2.dp,
val padding: Dp = 0.dp,
val thumbColor: Color = Color.Gray,
val thumbAlpha: Float = 0.5f,
) : ScrollIndicatorFactory {
// The node is the core of the ScrollIndicator, handling the drawing logic.
override fun createNode(
@@ -67,7 +92,12 @@ data class VerticalScrollIndicatorFactory(
val (topLeft, size) =
when (orientation) {
Orientation.Vertical -> {
val x = size.width - thumbThicknessPx - paddingPx
val x =
if (layoutDirection == LayoutDirection.Rtl) {
paddingPx
} else {
size.width - thumbThicknessPx - paddingPx
}
Offset(x, thumbPosition) to Size(thumbThicknessPx, thumbLength)
}
Orientation.Horizontal -> {
@@ -82,7 +112,7 @@ data class VerticalScrollIndicatorFactory(
color = thumbColor,
topLeft = topLeft,
size = size,
alpha = thumbAlpha * alpha.value,
alpha = alpha.value,
)
}
}

View File

@@ -73,6 +73,7 @@ import me.ash.reader.ui.component.FilterBar
import me.ash.reader.ui.component.base.DisplayText
import me.ash.reader.ui.component.base.FeedbackIconButton
import me.ash.reader.ui.component.base.RYScaffold
import me.ash.reader.ui.component.scrollbar.drawVerticalScrollIndicator
import me.ash.reader.ui.ext.collectAsStateValue
import me.ash.reader.ui.ext.currentAccountId
import me.ash.reader.ui.ext.findActivity
@@ -228,7 +229,7 @@ fun FeedsPage(
},
content = {
PullToRefreshBox(state = syncingState, isRefreshing = isSyncing, onRefresh = doSync) {
LazyColumn(modifier = Modifier.fillMaxSize(), state = listState) {
LazyColumn(modifier = Modifier.fillMaxSize().drawVerticalScrollIndicator(listState), state = listState) {
item {
DisplayText(text = feedsUiState.account?.name ?: "", desc = "") {
hapticFeedback.performHapticFeedback(HapticFeedbackType.ContextClick)

View File

@@ -94,6 +94,7 @@ import me.ash.reader.ui.component.base.FeedbackIconButton
import me.ash.reader.ui.component.base.RYExtensibleVisibility
import me.ash.reader.ui.component.base.RYScaffold
import me.ash.reader.ui.component.scrollbar.VerticalScrollIndicatorFactory
import me.ash.reader.ui.component.scrollbar.drawVerticalScrollIndicator
import me.ash.reader.ui.component.scrollbar.scrollIndicator
import me.ash.reader.ui.ext.collectAsStateValue
import me.ash.reader.ui.ext.openURL
@@ -636,7 +637,6 @@ fun FlowPage(
)
.also { currentPullToLoadState = it }
val scrollIndicatorState = listState.scrollIndicatorState
Box(modifier = Modifier.fillMaxSize()) {
LazyColumn(
modifier =
@@ -662,13 +662,7 @@ fun FlowPage(
)
.nestedScroll(scrollBehavior.nestedScrollConnection)
.fillMaxSize()
.scrollIndicator(
VerticalScrollIndicatorFactory(
thumbColor = MaterialTheme.colorScheme.primary
),
scrollIndicatorState!!,
orientation = Orientation.Vertical,
),
.drawVerticalScrollIndicator(listState),
state = listState,
) {
ArticleList(

View File

@@ -28,8 +28,8 @@ import me.ash.reader.infrastructure.preference.LocalReadingSubheadUpperCase
import me.ash.reader.infrastructure.preference.ReadingRendererPreference
import me.ash.reader.ui.component.reader.LocalTextContentWidth
import me.ash.reader.ui.component.reader.Reader
import me.ash.reader.ui.component.scrollbar.drawVerticalScrollIndicator
import me.ash.reader.ui.component.webview.RYWebView
import me.ash.reader.ui.ext.drawVerticalScrollbar
import me.ash.reader.ui.ext.extractDomain
import me.ash.reader.ui.ext.roundClick
@@ -80,7 +80,10 @@ fun Content(
ReadingRendererPreference.WebView -> {
Column(
modifier =
modifier.padding(top = contentPadding.calculateTopPadding()).fillMaxSize()
modifier
.padding(top = contentPadding.calculateTopPadding())
.fillMaxSize()
.drawVerticalScrollIndicator(scrollState)
) {
Column(
modifier = Modifier.fillMaxSize().verticalScroll(scrollState),
@@ -110,7 +113,7 @@ fun Content(
ReadingRendererPreference.NativeComponent -> {
SelectionContainer {
LazyColumn(
modifier = modifier.fillMaxSize().drawVerticalScrollbar(listState),
modifier = modifier.fillMaxSize().drawVerticalScrollIndicator(listState),
state = listState,
horizontalAlignment = Alignment.CenterHorizontally,
) {