Skip to content

Commit

Permalink
Search improvements
Browse files Browse the repository at this point in the history
- Improve animations when opening search bar
- Temporary fix to search bar showing on tall devices; fixes #2495
- Open first item when pressing search button in IME
  • Loading branch information
SuperDragonXD committed Dec 27, 2024
1 parent ddc8641 commit 6289116
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 83 deletions.
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package app.lawnchair.lawnicons.ui.components.home

import androidx.compose.animation.core.animateDpAsState
import androidx.compose.animation.core.tween
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.offset
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
Expand Down Expand Up @@ -41,26 +44,16 @@ fun HomeTopBar(
) {
val (isSearchExpanded, isExpandedScreen, searchTerm, searchMode, searchedIconInfoModel, isIconPicker) = uiState

val offset = animateDpAsState(
targetValue = if (isSearchExpanded || isExpandedScreen) {
0.dp
} else {
(-100).dp
},
label = "move search bar",
)
searchedIconInfoModel?.let {
SearchBar(
modifier = modifier
.offset {
IntOffset(0, offset.value.roundToPx())
},
searchedIconInfoModel?.let { iconInfoModel ->
AnimatedSearchBar(
modifier = modifier,
searchTerm = searchTerm,
onClearSearch = onClearSearch,
onModeChange = onChangeMode,
onSearch = onSearchIcons,
iconInfoModel = it,
iconInfoModel = iconInfoModel,
onNavigate = onNavigate,
isSearchExpanded = isSearchExpanded,
isExpandedScreen = isExpandedScreen,
isIconPicker = isIconPicker,
searchMode = searchMode,
Expand All @@ -72,13 +65,14 @@ fun HomeTopBar(
}

@Composable
private fun SearchBar(
private fun AnimatedSearchBar(
searchMode: SearchMode,
searchTerm: String,
onSearch: (String) -> Unit,
onClearSearch: () -> Unit,
onModeChange: (SearchMode) -> Unit,
onNavigate: () -> Unit,
isSearchExpanded: Boolean,
isExpandedScreen: Boolean,
isIconPicker: Boolean,
onSendResult: (IconInfo) -> Unit,
Expand All @@ -87,18 +81,34 @@ private fun SearchBar(
modifier: Modifier = Modifier,
inputFieldModifier: Modifier = Modifier,
) {
val offset = animateDpAsState(
targetValue = (if (isSearchExpanded || isExpandedScreen) 0 else -1000).dp,
label = "move search bar",
animationSpec = tween(
durationMillis = 600,
),
)

Column(
modifier = modifier.fillMaxWidth(),
modifier = modifier
.fillMaxWidth()
.offset {
IntOffset(0, offset.value.roundToPx())
},
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
) {
val isIconInfoShown = rememberSaveable { mutableStateOf(false) }
LawniconsSearchBar(
query = searchTerm,
isQueryEmpty = searchTerm == "",
onClear = onClearSearch,
onBack = onFocusChange,
onSearch = {
isIconInfoShown.value = true
},
onQueryChange = onSearch,
iconInfoModel = iconInfoModel,
iconCount = iconInfoModel.iconCount,
onNavigate = onNavigate,
isExpandedScreen = isExpandedScreen,
isIconPicker = isIconPicker,
Expand All @@ -109,6 +119,8 @@ private fun SearchBar(
onModeChange = onModeChange,
iconInfo = iconInfoModel.iconInfo,
onSendResult = onSendResult,
showSheet = isIconInfoShown.value,
onToggleSheet = { isIconInfoShown.value = it },
)
},
inputFieldModifier = inputFieldModifier,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,27 @@ fun IconPreview(
isIconPicker: Boolean = false,
) {
val isIconInfoShown = rememberSaveable { mutableStateOf(false) }
IconPreview(
iconInfo = iconInfo,
onSendResult = onSendResult,
modifier = modifier,
iconBackground = iconBackground,
isIconPicker = isIconPicker,
showSheet = isIconInfoShown.value,
onToggleSheet = { isIconInfoShown.value = it },
)
}

@Composable
fun IconPreview(
iconInfo: IconInfo,
onSendResult: (IconInfo) -> Unit,
modifier: Modifier = Modifier,
iconBackground: Color? = null,
isIconPicker: Boolean = false,
showSheet: Boolean = false,
onToggleSheet: (Boolean) -> Unit = {},
) {
Box(
contentAlignment = Alignment.Center,
modifier = modifier
Expand All @@ -77,12 +97,12 @@ fun IconPreview(
if (isIconPicker) {
onSendResult(iconInfo)
} else {
isIconInfoShown.value = true
onToggleSheet(true)
}
},
)
.background(
color = iconBackground ?: if (isIconInfoShown.value) {
color = iconBackground ?: if (showSheet) {
MaterialTheme.colorScheme.surfaceVariant
} else {
MaterialTheme.colorScheme.iconColor
Expand All @@ -100,7 +120,7 @@ fun IconPreview(
icon,
contentDescription = null,
modifier = Modifier.fillMaxSize(0.6f),
tint = if (isIconInfoShown.value) {
tint = if (showSheet) {
MaterialTheme.colorScheme.onSurfaceVariant
} else {
MaterialTheme.colorScheme.onPrimaryContainer
Expand All @@ -111,19 +131,19 @@ fun IconPreview(
painter = painterResource(iconInfo.id),
contentDescription = null,
modifier = Modifier.fillMaxSize(0.6f),
tint = if (isIconInfoShown.value) {
tint = if (showSheet) {
MaterialTheme.colorScheme.onSurfaceVariant
} else {
MaterialTheme.colorScheme.onPrimaryContainer
},
)
}
}
AnimatedVisibility(isIconInfoShown.value) {
AnimatedVisibility(showSheet) {
IconInfoSheet(
iconInfo = iconInfo,
) {
isIconInfoShown.value = it
onToggleSheet(it)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.unit.dp
import androidx.compose.ui.zIndex
import app.lawnchair.lawnicons.R
import app.lawnchair.lawnicons.model.IconInfoModel
import app.lawnchair.lawnicons.model.SearchMode
import app.lawnchair.lawnicons.ui.components.home.NavigationIconButton
import app.lawnchair.lawnicons.ui.theme.LawniconsTheme
Expand All @@ -51,44 +50,14 @@ import app.lawnchair.lawnicons.ui.util.SampleData
import app.lawnchair.lawnicons.ui.util.thenIf
import app.lawnchair.lawnicons.ui.util.toPaddingValues

@Composable
fun LawniconsSearchBar(
query: String,
isQueryEmpty: Boolean,
onClear: () -> Unit,
onBack: () -> Unit,
onQueryChange: (String) -> Unit,
iconInfoModel: IconInfoModel,
onNavigate: () -> Unit,
modifier: Modifier = Modifier,
inputFieldModifier: Modifier = Modifier,
isExpandedScreen: Boolean = false,
isIconPicker: Boolean = false,
content: @Composable (() -> Unit),
) {
LawniconsSearchBar(
query = query,
isQueryEmpty = isQueryEmpty,
onClear = onClear,
onBack = onBack,
onQueryChange = onQueryChange,
iconCount = iconInfoModel.iconCount,
onNavigate = onNavigate,
content = content,
modifier = modifier,
inputFieldModifier = inputFieldModifier,
isExpandedScreen = isExpandedScreen,
isIconPicker = isIconPicker,
)
}

/**
* Composable function to create a search bar for the Lawnicons app.
*
* @param query The current search query entered by the user.
* @param isQueryEmpty A boolean value indicating whether the search query is empty.
* @param onClear A callback function that handles clearing the search query.
* @param onBack A callback function that handles navigating back.
* @param onSearch A callback function that handles searching based on the current search query.
* @param onQueryChange A callback function that handles changes in the search query.
* @param iconCount The number of icons available for selection.
* @param onNavigate A callback function that handles navigation to different screens based on the search query.
Expand All @@ -103,6 +72,7 @@ fun LawniconsSearchBar(
isQueryEmpty: Boolean,
onClear: () -> Unit,
onBack: () -> Unit,
onSearch: () -> Unit,
onQueryChange: (String) -> Unit,
iconCount: Int,
onNavigate: () -> Unit,
Expand Down Expand Up @@ -134,7 +104,7 @@ fun LawniconsSearchBar(
ResponsiveSearchBar(
query = query,
onQueryChange = onQueryChange,
onSearch = { active = false },
onSearch = { if (query != "") onSearch() },
active = active,
onActiveChange = {
active = it
Expand Down Expand Up @@ -296,6 +266,7 @@ private fun SearchBarPreview() {
isQueryEmpty = false,
onClear = {},
onBack = {},
onSearch = {},
onQueryChange = { newValue ->
searchTerm = newValue
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.items
import androidx.compose.foundation.lazy.grid.itemsIndexed
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
Expand All @@ -28,8 +28,6 @@ import androidx.compose.material3.ListItem
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
Expand All @@ -52,6 +50,8 @@ fun SearchContents(
iconInfo: List<IconInfo>,
modifier: Modifier = Modifier,
onSendResult: (IconInfo) -> Unit = {},
showSheet: Boolean = false,
onToggleSheet: (Boolean) -> Unit = {},
) {
Column(
modifier = modifier,
Expand Down Expand Up @@ -120,7 +120,11 @@ fun SearchContents(
) { count ->
when (count) {
1 -> {
IconInfoListItem(iconInfo)
IconInfoListItem(
iconInfo,
showSheet,
onToggleSheet,
)
}

0 -> {
Expand All @@ -147,15 +151,25 @@ fun SearchContents(
columns = GridCells.Adaptive(minSize = 80.dp),
contentPadding = PaddingValues(16.dp, 16.dp, 16.dp, 80.dp),
) {
items(
itemsIndexed(
items = iconInfo,
contentType = { "icon_preview" },
) {
IconPreview(
iconInfo = it,
onSendResult = onSendResult,
iconBackground = MaterialTheme.colorScheme.surfaceContainerLow,
)
contentType = { _, _ -> "icon_preview" },
) { index, it ->
if (index == 0 && searchTerm != "") {
IconPreview(
iconInfo = it,
onSendResult = onSendResult,
iconBackground = MaterialTheme.colorScheme.surface,
showSheet = showSheet,
onToggleSheet = onToggleSheet,
)
} else {
IconPreview(
iconInfo = it,
onSendResult = onSendResult,
iconBackground = MaterialTheme.colorScheme.surfaceContainerLow,
)
}
}
}
}
Expand All @@ -166,7 +180,11 @@ fun SearchContents(
}

@Composable
private fun IconInfoListItem(iconInfo: List<IconInfo>) {
private fun IconInfoListItem(
iconInfo: List<IconInfo>,
showSheet: Boolean,
onToggleSheet: (Boolean) -> Unit,
) {
Column(
modifier = Modifier
.fillMaxWidth()
Expand All @@ -179,8 +197,6 @@ private fun IconInfoListItem(iconInfo: List<IconInfo>) {
return@IconInfoListItem
}

val isIconInfoAppfilterShown = rememberSaveable { mutableStateOf(false) }

ListItem(
headlineContent = { Text(it.getFirstLabelAndComponent().label) },
supportingContent = { Text(it.getFirstLabelAndComponent().componentName) },
Expand All @@ -201,13 +217,13 @@ private fun IconInfoListItem(iconInfo: List<IconInfo>) {
},
modifier = Modifier
.clip(RoundedCornerShape(16.dp))
.clickable(onClick = { isIconInfoAppfilterShown.value = true }),
.clickable(onClick = { onToggleSheet(true) }),
)
AnimatedVisibility(isIconInfoAppfilterShown.value) {
AnimatedVisibility(showSheet) {
IconInfoSheet(
iconInfo = it,
) {
isIconInfoAppfilterShown.value = it
onToggleSheet(it)
}
}
}
Expand Down
Loading

0 comments on commit 6289116

Please sign in to comment.