Improve pull down scaffold performance

This commit is contained in:
MM20 2022-05-16 19:35:15 +02:00
parent f2fe8a6ce9
commit 98da9ea042
No known key found for this signature in database
GPG Key ID: 0B61A8F2DEAFA389
3 changed files with 80 additions and 72 deletions

View File

@ -235,7 +235,7 @@ fun PagerScaffold(
.padding(start = 8.dp, end = 8.dp, bottom = 8.dp) .padding(start = 8.dp, end = 8.dp, bottom = 8.dp)
.imePadding() .imePadding()
.offset(y = widgetEditModeOffset), .offset(y = widgetEditModeOffset),
level = searchBarLevel, focused = focusSearchBar, onFocusChange = { level = { searchBarLevel }, focused = focusSearchBar, onFocusChange = {
if (it) viewModel.openSearch() if (it) viewModel.openSearch()
viewModel.setSearchbarFocus(it) viewModel.setSearchbarFocus(it)
}, },

View File

@ -1,12 +1,16 @@
package de.mm20.launcher2.ui.launcher package de.mm20.launcher2.ui.launcher
import android.app.Activity import android.app.Activity
import android.util.Log
import android.view.WindowManager import android.view.WindowManager
import androidx.activity.compose.BackHandler import androidx.activity.compose.BackHandler
import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.animateDpAsState import androidx.compose.animation.core.animateDpAsState
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.ExperimentalFoundationApi
import androidx.compose.foundation.gestures.LocalOverScrollConfiguration
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
@ -25,18 +29,14 @@ import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
import androidx.compose.ui.input.nestedscroll.NestedScrollSource import androidx.compose.ui.input.nestedscroll.NestedScrollSource
import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.Velocity import androidx.compose.ui.unit.Velocity
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import com.google.accompanist.pager.ExperimentalPagerApi import com.google.accompanist.pager.ExperimentalPagerApi
import com.google.accompanist.pager.VerticalPager
import com.google.accompanist.pager.calculateCurrentOffsetForPage
import com.google.accompanist.pager.rememberPagerState import com.google.accompanist.pager.rememberPagerState
import com.google.accompanist.systemuicontroller.rememberSystemUiController import com.google.accompanist.systemuicontroller.rememberSystemUiController
import de.mm20.launcher2.ktx.isAtLeastApiLevel import de.mm20.launcher2.ktx.isAtLeastApiLevel
@ -48,9 +48,9 @@ import de.mm20.launcher2.ui.launcher.search.SearchColumn
import de.mm20.launcher2.ui.launcher.search.SearchVM import de.mm20.launcher2.ui.launcher.search.SearchVM
import de.mm20.launcher2.ui.launcher.widgets.WidgetColumn import de.mm20.launcher2.ui.launcher.widgets.WidgetColumn
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlin.math.absoluteValue import kotlin.math.roundToInt
@OptIn(ExperimentalPagerApi::class) @OptIn(ExperimentalPagerApi::class, ExperimentalFoundationApi::class)
@Composable @Composable
fun PullDownScaffold( fun PullDownScaffold(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
@ -129,7 +129,7 @@ fun PullDownScaffold(
LaunchedEffect(isSearchOpen) { LaunchedEffect(isSearchOpen) {
if (isSearchOpen) searchScrollState.scrollTo(0) if (isSearchOpen) searchScrollState.scrollTo(0)
if (!isSearchOpen) searchVM.search("") if (!isSearchOpen) searchVM.search("")
pagerState.animateScrollToPage(if (isSearchOpen) 1 else 0) //pagerState.animateScrollToPage(if (isSearchOpen) 1 else 0)
searchBarOffset.animateTo(0f) searchBarOffset.animateTo(0f)
} }
@ -198,79 +198,88 @@ fun PullDownScaffold(
} }
} }
var size by remember { mutableStateOf(IntSize.Zero) }
Box( Box(
modifier = modifier modifier = modifier
.fillMaxSize() .fillMaxSize()
.onSizeChanged { .clipToBounds()
size = it .nestedScroll(nestedScrollConnection)
}
.offset { IntOffset(0, offsetY.value.toInt()) }, .offset { IntOffset(0, offsetY.value.toInt()) },
contentAlignment = Alignment.TopCenter contentAlignment = Alignment.TopCenter
) { ) {
VerticalPager(
state = pagerState, BoxWithConstraints(
modifier = Modifier modifier = modifier
.nestedScroll(nestedScrollConnection), .fillMaxSize()
count = 2,
reverseLayout = true,
userScrollEnabled = false,
) { ) {
if (it == 1) { val height by remember {
val websearches by searchVM.websearchResults.observeAsState(emptyList()) derivedStateOf { maxHeight }
val webSearchPadding by animateDpAsState( }
if (websearches.isEmpty()) 0.dp else 48.dp Log.d("MM20", "PullDownScaffold recompose, $maxHeight")
) CompositionLocalProvider(
val offset = calculateCurrentOffsetForPage(1).absoluteValue LocalOverScrollConfiguration provides null
SearchColumn( ) {
val offset by animateFloatAsState(if (isSearchOpen) 1f else 0f)
Column(
modifier = Modifier modifier = Modifier
.graphicsLayer { .fillMaxWidth()
transformOrigin = TransformOrigin.Center .requiredHeight(height * 2)
scaleX = 1 - offset .offset {
scaleY = 1 - offset IntOffset(
alpha = 1 - offset 0,
((-0.5f + offset) * height.toPx()).roundToInt()
)
} }
.fillMaxSize() ) {
.verticalScroll(searchScrollState)
.padding(8.dp) val websearches by searchVM.websearchResults.observeAsState(emptyList())
.padding(top = 56.dp) val webSearchPadding by animateDpAsState(
.padding(top = webSearchPadding) if (websearches.isEmpty()) 0.dp else 48.dp
.imePadding() )
) SearchColumn(
modifier = Modifier
.graphicsLayer {
transformOrigin = TransformOrigin.Center
scaleX = offset
scaleY = offset
alpha = offset
}
.fillMaxWidth()
.requiredHeight(height)
.verticalScroll(searchScrollState)
.padding(8.dp)
.padding(top = 56.dp)
.padding(top = webSearchPadding)
.imePadding()
)
val editModePadding by animateDpAsState(if (isWidgetEditMode) 56.dp else 0.dp)
WidgetColumn(
modifier =
Modifier
.graphicsLayer {
transformOrigin = TransformOrigin.Center
scaleX = 1 - offset
scaleY = 1 - offset
alpha = 1 - offset
}
.fillMaxWidth()
.requiredHeight(height)
.verticalScroll(widgetsScrollState)
.padding(8.dp)
.padding(top = editModePadding),
clockHeight = { height },
editMode = isWidgetEditMode,
onEditModeChange = {
viewModel.setWidgetEditMode(it)
}
)
}
} }
if (it == 0) {
val offset = calculateCurrentOffsetForPage(0).absoluteValue
val editModePadding by animateDpAsState(if (isWidgetEditMode) 56.dp else 0.dp)
val clockHeight by remember {
derivedStateOf {
with(density) {
size.height.toDp()
}
}
}
WidgetColumn(
modifier =
Modifier
.graphicsLayer {
transformOrigin = TransformOrigin.Center
scaleX = 1 - offset
scaleY = 1 - offset
alpha = 1 - offset
}
.fillMaxSize()
.verticalScroll(widgetsScrollState)
.padding(8.dp)
.padding(top = editModePadding),
clockHeight = { clockHeight },
editMode = isWidgetEditMode,
onEditModeChange = {
viewModel.setWidgetEditMode(it)
}
)
}
} }
AnimatedVisibility(visible = isWidgetEditMode, AnimatedVisibility(visible = isWidgetEditMode,
enter = slideIn { IntOffset(0, -it.height) }, enter = slideIn { IntOffset(0, -it.height) },
exit = slideOut { IntOffset(0, -it.height) } exit = slideOut { IntOffset(0, -it.height) }
@ -304,11 +313,10 @@ fun PullDownScaffold(
) )
SearchBar( SearchBar(
level = searchBarLevel, level = { searchBarLevel },
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.wrapContentHeight() .wrapContentHeight()
.clipToBounds()
.padding(8.dp) .padding(8.dp)
.offset { IntOffset(0, searchBarOffset.value.toInt()) } .offset { IntOffset(0, searchBarOffset.value.toInt()) }
.offset(y = editModeSearchBarOffset), .offset(y = editModeSearchBarOffset),

View File

@ -57,7 +57,7 @@ import java.io.File
@Composable @Composable
fun SearchBar( fun SearchBar(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
level: SearchBarLevel, level: () -> SearchBarLevel,
focused: Boolean, focused: Boolean,
onFocusChange: (Boolean) -> Unit, onFocusChange: (Boolean) -> Unit,
reverse: Boolean = false, reverse: Boolean = false,
@ -94,7 +94,7 @@ fun SearchBar(
SearchBar( SearchBar(
modifier, modifier,
level, level(),
websearches, websearches,
value = query, value = query,
onValueChange = { onValueChange = {