android: Button to jump to bottom of log view

This adds a button that can jump to the bottom of the log view.
If the user scrolls up we now disable the auto scroll down and show the
down button. When the down button is clicked the auto scroll resumes and
the button is removed.
This commit is contained in:
Colin Edwards 2024-04-06 20:11:01 -05:00
parent 4c56e87e36
commit b0cd456753
2 changed files with 53 additions and 10 deletions

View File

@ -1,36 +1,79 @@
package org.musicpd.ui package org.musicpd.ui
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.VerticalAlignBottom
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.Icon
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.State import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@Composable @Composable
fun LogView(messages: State<List<String>>) { fun LogView(messages: List<String>) {
val state = rememberLazyListState() val lazyListState = rememberLazyListState()
Column(Modifier.fillMaxSize()) { var userScrolled = remember { mutableStateOf(false) }
LaunchedEffect(lazyListState) {
snapshotFlow { lazyListState.isScrollInProgress }
.collect {
if (it) {
userScrolled.value = true
}
}
}
Box(Modifier.fillMaxSize()) {
LazyColumn( LazyColumn(
Modifier.padding(4.dp), Modifier.padding(4.dp),
state lazyListState
) { ) {
items(messages.value) { message -> items(messages) { message ->
Text(text = message, fontFamily = FontFamily.Monospace) Text(text = message, fontFamily = FontFamily.Monospace)
} }
CoroutineScope(Dispatchers.Main).launch { CoroutineScope(Dispatchers.Main).launch {
state.scrollToItem(messages.value.count(), 0) lazyListState.scrollToItem(messages.count(), 0)
}
}
if (lazyListState.canScrollForward) {
FloatingActionButton(
onClick = {
userScrolled.value = false
CoroutineScope(Dispatchers.Main).launch {
lazyListState.scrollToItem(messages.count(), 0)
}
},
modifier = Modifier.padding(16.dp).align(Alignment.BottomEnd)
) {
Icon(Icons.Filled.VerticalAlignBottom, "Scroll to bottom icon")
} }
} }
} }
} }
@Preview
@Composable
fun LogViewPreview() {
val data = listOf("test",
"test2",
"test3")
LogView(data)
}

View File

@ -69,7 +69,7 @@ fun MPDApp(
StatusScreen(settingsViewModel) StatusScreen(settingsViewModel)
} }
composable(NavigationItem.Logs.route) { composable(NavigationItem.Logs.route) {
LogView(settingsViewModel.getLogs().collectAsStateWithLifecycle()) LogView(settingsViewModel.getLogs().collectAsStateWithLifecycle().value)
} }
composable(NavigationItem.Settings.route) { composable(NavigationItem.Settings.route) {
MPDSettings(settingsViewModel) MPDSettings(settingsViewModel)