Pull down scaffold: add API to display search bar at bottom

This commit is contained in:
MM20 2023-01-12 20:59:58 +01:00
parent 1c937d9700
commit 0c08c20fd8
No known key found for this signature in database
GPG Key ID: 0B61A8F2DEAFA389

View File

@ -7,15 +7,41 @@ import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.slideIn import androidx.compose.animation.slideIn
import androidx.compose.animation.slideOut import androidx.compose.animation.slideOut
import androidx.compose.foundation.LocalOverscrollConfiguration import androidx.compose.foundation.LocalOverscrollConfiguration
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxWithConstraints
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.calculateStartPadding
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.requiredHeight
import androidx.compose.foundation.layout.safeDrawing
import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.Done import androidx.compose.material.icons.rounded.Done
import androidx.compose.material3.* import androidx.compose.material3.CenterAlignedTopAppBar
import androidx.compose.runtime.* import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset import androidx.compose.ui.geometry.Offset
@ -54,6 +80,7 @@ fun PullDownScaffold(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
darkStatusBarIcons: Boolean = false, darkStatusBarIcons: Boolean = false,
darkNavBarIcons: Boolean = false, darkNavBarIcons: Boolean = false,
bottomSearchBar: Boolean = true,
) { ) {
val viewModel: LauncherScaffoldVM = viewModel() val viewModel: LauncherScaffoldVM = viewModel()
val searchVM: SearchVM = viewModel() val searchVM: SearchVM = viewModel()
@ -76,7 +103,8 @@ fun PullDownScaffold(
val isSearchAtEnd by remember { val isSearchAtEnd by remember {
derivedStateOf { derivedStateOf {
val lastItem = searchState.layoutInfo.visibleItemsInfo.lastOrNull() ?: return@derivedStateOf true val lastItem =
searchState.layoutInfo.visibleItemsInfo.lastOrNull() ?: return@derivedStateOf true
lastItem.offset + lastItem.size <= searchState.layoutInfo.viewportEndOffset - searchState.layoutInfo.afterContentPadding lastItem.offset + lastItem.size <= searchState.layoutInfo.viewportEndOffset - searchState.layoutInfo.afterContentPadding
} }
} }
@ -188,9 +216,11 @@ fun PullDownScaffold(
viewModel.closeSearch() viewModel.closeSearch()
searchVM.search("") searchVM.search("")
} }
isWidgetEditMode -> { isWidgetEditMode -> {
viewModel.setWidgetEditMode(false) viewModel.setWidgetEditMode(false)
} }
widgetsScrollState.value != 0 -> { widgetsScrollState.value != 0 -> {
scope.launch { scope.launch {
widgetsScrollState.animateScrollTo(0) widgetsScrollState.animateScrollTo(0)
@ -221,11 +251,13 @@ fun PullDownScaffold(
offsetY.value = (offsetY.value + (consumed * 0.5f)).coerceIn(-maxOffset, 0f) offsetY.value = (offsetY.value + (consumed * 0.5f)).coerceIn(-maxOffset, 0f)
consumed consumed
} }
canPullDown && available.y > 0 || offsetY.value > 0 -> { canPullDown && available.y > 0 || offsetY.value > 0 -> {
val consumed = available.y val consumed = available.y
offsetY.value = (offsetY.value + (consumed * 0.5f)).coerceIn(0f, maxOffset) offsetY.value = (offsetY.value + (consumed * 0.5f)).coerceIn(0f, maxOffset)
consumed consumed
} }
else -> 0f else -> 0f
} }
@ -300,14 +332,17 @@ fun PullDownScaffold(
end = windowInsets.calculateStartPadding(LocalLayoutDirection.current), end = windowInsets.calculateStartPadding(LocalLayoutDirection.current),
), ),
paddingValues = PaddingValues( paddingValues = PaddingValues(
top = 60.dp + webSearchPadding + windowInsets.calculateTopPadding(), top = windowInsets.calculateTopPadding() + if (!bottomSearchBar) 60.dp + webSearchPadding else 4.dp,
bottom = 4.dp + windowInsets.calculateBottomPadding() bottom = windowInsets.calculateBottomPadding() + if (bottomSearchBar) 60.dp + webSearchPadding else 4.dp
), ),
state = searchState, state = searchState,
) )
val clockPadding by animateDpAsState( val clockPadding by animateDpAsState(
if (isWidgetsAtStart && fillClockHeight) insets.calculateBottomPadding() else 0.dp if (isWidgetsAtStart && fillClockHeight)
insets.calculateBottomPadding() + if (bottomSearchBar) 64.dp else 0.dp
else 0.dp
) )
val clockHeight by remember { val clockHeight by remember {
derivedStateOf { derivedStateOf {
@ -332,7 +367,10 @@ fun PullDownScaffold(
.verticalScroll(widgetsScrollState) .verticalScroll(widgetsScrollState)
.windowInsetsPadding(WindowInsets.safeDrawing) .windowInsetsPadding(WindowInsets.safeDrawing)
.padding(8.dp) .padding(8.dp)
.padding(top = 56.dp) .padding(
top = if (bottomSearchBar) 0.dp else 56.dp,
bottom = if (bottomSearchBar) 56.dp else 0.dp,
)
) { ) {
AnimatedVisibility(!isWidgetEditMode) { AnimatedVisibility(!isWidgetEditMode) {
Box( Box(
@ -392,7 +430,7 @@ fun PullDownScaffold(
} }
val searchBarFocused by viewModel.searchBarFocused.observeAsState(false) val searchBarFocused by viewModel.searchBarFocused.observeAsState(false)
val editModeSearchBarOffset by animateDpAsState( val editModeSearchBarOffset by animateDpAsState(
if (isWidgetEditMode) -128.dp else 0.dp (if (isWidgetEditMode) 128.dp else 0.dp) * (if (bottomSearchBar) 1 else -1)
) )
val value by searchVM.searchQuery.observeAsState("") val value by searchVM.searchQuery.observeAsState("")
@ -402,12 +440,17 @@ fun PullDownScaffold(
LauncherSearchBar( LauncherSearchBar(
modifier = Modifier modifier = Modifier
.align(if (bottomSearchBar) Alignment.BottomCenter else Alignment.TopCenter)
.fillMaxWidth() .fillMaxWidth()
.wrapContentHeight() .wrapContentHeight()
.windowInsetsPadding(WindowInsets.safeDrawing) .windowInsetsPadding(WindowInsets.safeDrawing)
.padding(8.dp) .padding(8.dp)
.offset { IntOffset(0, .offset {
if (searchBarFocused) 0 else searchBarOffset.value.toInt()) } IntOffset(
0,
if (searchBarFocused) 0 else searchBarOffset.value.toInt() * (if (bottomSearchBar) -1 else 1)
)
}
.offset { .offset {
IntOffset( IntOffset(
0, 0,
@ -429,6 +472,7 @@ fun PullDownScaffold(
onValueChange = { searchVM.search(it) }, onValueChange = { searchVM.search(it) },
darkColors = LocalPreferDarkContentOverWallpaper.current && searchBarColor == Settings.SearchBarSettings.SearchBarColors.Auto || searchBarColor == Settings.SearchBarSettings.SearchBarColors.Dark, darkColors = LocalPreferDarkContentOverWallpaper.current && searchBarColor == Settings.SearchBarSettings.SearchBarColors.Auto || searchBarColor == Settings.SearchBarSettings.SearchBarColors.Dark,
style = searchBarStyle, style = searchBarStyle,
reverse = bottomSearchBar,
) )
} }