Implement collapsing toolbar on editor

This commit is contained in:
William Brawner 2024-05-06 00:26:33 -06:00
parent c792bd106e
commit 75e38a97dd
Signed by: wbrawner
GPG key ID: 8FF12381C6C90D35
7 changed files with 54 additions and 21 deletions

View file

@ -24,6 +24,7 @@ import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Checkbox import androidx.compose.material3.Checkbox
import androidx.compose.material3.DropdownMenu import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
@ -35,6 +36,8 @@ import androidx.compose.material3.Tab
import androidx.compose.material3.TabRow import androidx.compose.material3.TabRow
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TextButton import androidx.compose.material3.TextButton
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.TopAppBarScrollBehavior
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.State import androidx.compose.runtime.State
@ -46,6 +49,7 @@ import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalSoftwareKeyboardController import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
@ -121,6 +125,7 @@ fun MainScreen(
) )
} }
@OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
private fun MainScreen( private fun MainScreen(
fileName: String = "Untitled.md", fileName: String = "Untitled.md",
@ -189,7 +194,7 @@ private fun MainScreen(
text = { Text(it.text) } text = { Text(it.text) }
) )
} }
val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior()
MarkdownNavigationDrawer(navigate) { drawerState -> MarkdownNavigationDrawer(navigate) { drawerState ->
Scaffold( Scaffold(
topBar = { topBar = {
@ -251,7 +256,8 @@ private fun MainScreen(
} }
} }
} }
} },
scrollBehavior = scrollBehavior
) )
}, },
snackbarHost = { snackbarHost = {
@ -276,7 +282,7 @@ private fun MainScreen(
reload = reloadToggle, reload = reloadToggle,
markdown = markdown, markdown = markdown,
setMarkdown = setMarkdown, setMarkdown = setMarkdown,
enableReadability = enableReadability enableReadability = enableReadability,
) )
Spacer( Spacer(
modifier = Modifier modifier = Modifier
@ -303,7 +309,8 @@ private fun MainScreen(
setMarkdown = setMarkdown, setMarkdown = setMarkdown,
lockSwiping = lockSwiping, lockSwiping = lockSwiping,
enableReadability = enableReadability, enableReadability = enableReadability,
reloadToggle = reloadToggle reloadToggle = reloadToggle,
scrollBehavior = scrollBehavior
) )
} }
} }
@ -312,14 +319,15 @@ private fun MainScreen(
} }
@Composable @Composable
@OptIn(ExperimentalFoundationApi::class) @OptIn(ExperimentalFoundationApi::class, ExperimentalMaterial3Api::class)
private fun TabbedMarkdownEditor( private fun TabbedMarkdownEditor(
initialMarkdown: String, initialMarkdown: String,
markdown: String, markdown: String,
setMarkdown: (String) -> Unit, setMarkdown: (String) -> Unit,
lockSwiping: Boolean, lockSwiping: Boolean,
enableReadability: Boolean, enableReadability: Boolean,
reloadToggle: Int reloadToggle: Int,
scrollBehavior: TopAppBarScrollBehavior
) { ) {
val coroutineScope = rememberCoroutineScope() val coroutineScope = rememberCoroutineScope()
val pagerState = rememberPagerState { 2 } val pagerState = rememberPagerState { 2 }
@ -345,14 +353,21 @@ private fun TabbedMarkdownEditor(
} }
if (page == 0) { if (page == 0) {
MarkdownTextField( MarkdownTextField(
modifier = Modifier.fillMaxSize(), modifier = Modifier
.fillMaxSize()
.nestedScroll(scrollBehavior.nestedScrollConnection),
markdown = initialMarkdown, markdown = initialMarkdown,
setMarkdown = setMarkdown, setMarkdown = setMarkdown,
enableReadability = enableReadability, enableReadability = enableReadability,
reload = reloadToggle reload = reloadToggle,
) )
} else { } else {
MarkdownText(modifier = Modifier.fillMaxSize(), markdown) MarkdownText(
modifier = Modifier
.fillMaxSize()
.nestedScroll(scrollBehavior.nestedScrollConnection),
markdown
)
} }
} }
} }

View file

@ -2,6 +2,7 @@ package com.wbrawner.simplemarkdown.ui
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.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
@ -12,6 +13,7 @@ import androidx.compose.ui.platform.LocalContext
import androidx.navigation.NavController import androidx.navigation.NavController
import com.wbrawner.simplemarkdown.utility.readAssetToString import com.wbrawner.simplemarkdown.utility.readAssetToString
@OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun MarkdownInfoScreen( fun MarkdownInfoScreen(
title: String, title: String,

View file

@ -3,6 +3,10 @@ package com.wbrawner.simplemarkdown.ui
import android.view.ViewGroup import android.view.ViewGroup
import android.webkit.WebView import android.webkit.WebView
import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Column
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.MaterialTheme
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
@ -54,7 +58,13 @@ fun MarkdownText(modifier: Modifier = Modifier, markdown: String) {
setHtml(parsedHtml) setHtml(parsedHtml)
} }
} }
Column(
modifier = modifier
.fillMaxSize()
.verticalScroll(rememberScrollState()),
) {
HtmlText(modifier = modifier, html = html) HtmlText(modifier = modifier, html = html)
}
} }
@OptIn(ExperimentalStdlibApi::class) @OptIn(ExperimentalStdlibApi::class)

View file

@ -15,6 +15,7 @@ import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TextFieldDefaults import androidx.compose.material3.TextFieldDefaults
import androidx.compose.material3.TopAppBarScrollBehavior
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
@ -22,6 +23,7 @@ import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.SolidColor import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.TextRange import androidx.compose.ui.text.TextRange
@ -61,14 +63,6 @@ fun MarkdownTextField(
focusedIndicatorColor = Color.Transparent, focusedIndicatorColor = Color.Transparent,
unfocusedIndicatorColor = Color.Transparent unfocusedIndicatorColor = Color.Transparent
) )
Column(
modifier = modifier
.fillMaxSize()
.imePadding()
.verticalScroll(
rememberScrollState()
)
) {
val interactionSource = remember { MutableInteractionSource() } val interactionSource = remember { MutableInteractionSource() }
val textStyle = TextStyle.Default.copy( val textStyle = TextStyle.Default.copy(
fontFamily = FontFamily.Monospace, fontFamily = FontFamily.Monospace,
@ -77,7 +71,8 @@ fun MarkdownTextField(
CompositionLocalProvider(LocalTextSelectionColors provides colors.textSelectionColors) { CompositionLocalProvider(LocalTextSelectionColors provides colors.textSelectionColors) {
BasicTextField( BasicTextField(
value = textFieldValue, value = textFieldValue,
modifier = Modifier.fillMaxSize(), modifier = modifier.fillMaxSize()
.imePadding(),
onValueChange = setTextFieldAndViewModelValues, onValueChange = setTextFieldAndViewModelValues,
enabled = true, enabled = true,
readOnly = false, readOnly = false,
@ -107,7 +102,6 @@ fun MarkdownTextField(
} }
) )
} }
}
} }
private fun String.annotate(enableReadability: Boolean): AnnotatedString { private fun String.annotate(enableReadability: Boolean): AnnotatedString {

View file

@ -8,8 +8,13 @@ import androidx.compose.material3.DrawerState
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarColors
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.TopAppBarDefaults.topAppBarColors
import androidx.compose.material3.TopAppBarScrollBehavior
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.rememberCoroutineScope
@ -23,13 +28,15 @@ fun MarkdownTopAppBar(
goBack: () -> Unit, goBack: () -> Unit,
backAsUp: Boolean = true, backAsUp: Boolean = true,
drawerState: DrawerState? = null, drawerState: DrawerState? = null,
actions: (@Composable RowScope.() -> Unit)? = null actions: (@Composable RowScope.() -> Unit)? = null,
scrollBehavior: TopAppBarScrollBehavior? = null,
) { ) {
val coroutineScope = rememberCoroutineScope() val coroutineScope = rememberCoroutineScope()
TopAppBar( TopAppBar(
title = { title = {
Text(text = title, maxLines = 1, overflow = TextOverflow.Ellipsis) Text(text = title, maxLines = 1, overflow = TextOverflow.Ellipsis)
}, },
colors = topAppBarColors(scrolledContainerColor = MaterialTheme.colorScheme.surface),
navigationIcon = { navigationIcon = {
val (icon, contentDescription, onClick) = remember { val (icon, contentDescription, onClick) = remember {
if (backAsUp) { if (backAsUp) {
@ -53,5 +60,6 @@ fun MarkdownTopAppBar(
} }
}, },
actions = actions ?: {}, actions = actions ?: {},
scrollBehavior = scrollBehavior
) )
} }

View file

@ -11,6 +11,7 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.AlertDialog import androidx.compose.material3.AlertDialog
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.RadioButton import androidx.compose.material3.RadioButton
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
@ -32,6 +33,7 @@ import com.wbrawner.simplemarkdown.ui.theme.SimpleMarkdownTheme
import com.wbrawner.simplemarkdown.utility.Preference import com.wbrawner.simplemarkdown.utility.Preference
import com.wbrawner.simplemarkdown.utility.PreferenceHelper import com.wbrawner.simplemarkdown.utility.PreferenceHelper
@OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun SettingsScreen(navController: NavController, preferenceHelper: PreferenceHelper) { fun SettingsScreen(navController: NavController, preferenceHelper: PreferenceHelper) {
Scaffold(topBar = { Scaffold(topBar = {

View file

@ -18,6 +18,7 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material3.Button import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
@ -34,6 +35,7 @@ import androidx.navigation.NavController
import com.wbrawner.simplemarkdown.R import com.wbrawner.simplemarkdown.R
import com.wbrawner.simplemarkdown.utility.SupportLinks import com.wbrawner.simplemarkdown.utility.SupportLinks
@OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun SupportScreen(navController: NavController) { fun SupportScreen(navController: NavController) {
Scaffold(topBar = { Scaffold(topBar = {