- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
最佳答案
这是一个复杂但完整的 SearchView 从头实现。结果将如下图所示,如果您不希望在 SearchView 未获得焦点时显示初始 Composable,则可以自定义或删除 InitialResults
或 Suggestions
和空
完整的实现在 github repository 中可用.
1- 创建搜索状态
/**
* Enum class with different values to set search state based on text, focus, initial state and
* results from search.
*
* **InitialResults** represents the initial state before search is initiated. This represents
* the whole screen
*
*/
enum class SearchDisplay {
InitialResults, Suggestions, Results, NoResults
}
2- 然后创建定义搜索逻辑的类
@Stable
class SearchState(
query: TextFieldValue,
focused: Boolean,
searching: Boolean,
suggestions: List<SuggestionModel>,
searchResults: List<TutorialSectionModel>
) {
var query by mutableStateOf(query)
var focused by mutableStateOf(focused)
var searching by mutableStateOf(searching)
var suggestions by mutableStateOf(suggestions)
var searchResults by mutableStateOf(searchResults)
val searchDisplay: SearchDisplay
get() = when {
!focused && query.text.isEmpty() -> SearchDisplay.InitialResults
focused && query.text.isEmpty() -> SearchDisplay.Suggestions
searchResults.isEmpty() -> SearchDisplay.NoResults
else -> SearchDisplay.Results
}
override fun toString(): String {
return "🚀 State query: $query, focused: $focused, searching: $searching " +
"suggestions: ${suggestions.size}, " +
"searchResults: ${searchResults.size}, " +
" searchDisplay: $searchDisplay"
}
}
3- 记住状态不是在每个组合中更新,而是仅当我们的搜索状态发生变化时才更新
@Composable
fun rememberSearchState(
query: TextFieldValue = TextFieldValue(""),
focused: Boolean = false,
searching: Boolean = false,
suggestions: List<SuggestionModel> = emptyList(),
searchResults: List<TutorialSectionModel> = emptyList()
): SearchState {
return remember {
SearchState(
query = query,
focused = focused,
searching = searching,
suggestions = suggestions,
searchResults = searchResults
)
}
}
TutorialSectionModel
是我使用的模型,它可以是通用类型 T 或您希望显示的特定类型
4- 创建在未专注
时显示的提示
@Composable
private fun SearchHint(modifier: Modifier = Modifier) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.fillMaxSize()
.then(modifier)
) {
Text(
color = Color(0xff757575),
text = "Search a Tag or Description",
)
}
}
我没有使用图标
,但如果您愿意,可以添加一个
5- 创建一个 SearchTextfield
可以有取消按钮,CircularProgressIndicator 显示加载和 BasicTextField
输入
/**
* This is a stateless TextField for searching with a Hint when query is empty,
* and clear and loading [IconButton]s to clear query or show progress indicator when
* a query is in progress.
*/
@Composable
fun SearchTextField(
query: TextFieldValue,
onQueryChange: (TextFieldValue) -> Unit,
onSearchFocusChange: (Boolean) -> Unit,
onClearQuery: () -> Unit,
searching: Boolean,
focused: Boolean,
modifier: Modifier = Modifier
) {
val focusRequester = remember { FocusRequester() }
Surface(
modifier = modifier
.then(
Modifier
.height(56.dp)
.padding(
top = 8.dp,
bottom = 8.dp,
start = if (!focused) 16.dp else 0.dp,
end = 16.dp
)
),
color = Color(0xffF5F5F5),
shape = RoundedCornerShape(percent = 50),
) {
CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.medium) {
Box(
contentAlignment = Alignment.CenterStart,
modifier = modifier
) {
if (query.text.isEmpty()) {
SearchHint(modifier.padding(start = 24.dp, end = 8.dp))
}
Row(verticalAlignment = Alignment.CenterVertically) {
BasicTextField(
value = query,
onValueChange = onQueryChange,
modifier = Modifier
.fillMaxHeight()
.weight(1f)
.onFocusChanged {
onSearchFocusChange(it.isFocused)
}
.focusRequester(focusRequester)
.padding(top = 9.dp, bottom = 8.dp, start = 24.dp, end = 8.dp),
singleLine = true
)
when {
searching -> {
CircularProgressIndicator(
modifier = Modifier
.padding(horizontal = 6.dp)
.size(36.dp)
)
}
query.text.isNotEmpty() -> {
IconButton(onClick = onClearQuery) {
Icon(imageVector = Icons.Filled.Cancel, contentDescription = null)
}
}
}
}
}
}
}
}
您可以删除 CircularProgressBar
或将 Icon 添加到包含 BasicTextField
的 Row
6- SearchBar
上面有 SearchTextField
和用于返回功能的后退箭头。 AnimatedVisibility
确保当我们在 SearchTextField
中聚焦 BasicTextField 时箭头是动画的,它也可以与 Icon 一起用作放大镜。
@ExperimentalAnimationApi
@OptIn(ExperimentalComposeUiApi::class)
@Composable
fun SearchBar(
query: TextFieldValue,
onQueryChange: (TextFieldValue) -> Unit,
onSearchFocusChange: (Boolean) -> Unit,
onClearQuery: () -> Unit,
onBack: ()-> Unit,
searching: Boolean,
focused: Boolean,
modifier: Modifier = Modifier
) {
val focusManager = LocalFocusManager.current
val keyboardController = LocalSoftwareKeyboardController.current
Row(
modifier = modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically
) {
AnimatedVisibility(visible = focused) {
// Back button
IconButton(
modifier = Modifier.padding(start =2.dp),
onClick = {
focusManager.clearFocus()
keyboardController?.hide()
onBack()
}) {
Icon(imageVector = Icons.Default.ArrowBack, contentDescription = null)
}
}
SearchTextField(
query,
onQueryChange,
onSearchFocusChange,
onClearQuery,
searching,
focused,
modifier.weight(1f)
)
}
}
7- 要使用 SearchBar,请创建一个 rememberSearchState 并将状态更新为此处使用列是因为屏幕的其余部分是根据 SearchState
LaunchedEffect 或在ViewModel 中设置mutableState 可用于设置查询结果或搜索
状态字段以显示加载
@Composable
fun HomeScreen(
modifier: Modifier = Modifier,
viewModel: HomeViewModel,
navigateToTutorial: (String) -> Unit,
state: SearchState = rememberSearchState()
) {
Column(
modifier = modifier.fillMaxSize()
) {
SearchBar(
query = state.query,
onQueryChange = { state.query = it },
onSearchFocusChange = { state.focused = it },
onClearQuery = { state.query = TextFieldValue("") },
onBack = { state.query = TextFieldValue("") },
searching = state.searching,
focused = state.focused,
modifier = modifier
)
LaunchedEffect(state.query.text) {
state.searching = true
delay(100)
state.searchResults = viewModel.getTutorials(state.query.text)
state.searching = false
}
when (state.searchDisplay) {
SearchDisplay.InitialResults -> {
}
SearchDisplay.NoResults -> {
}
SearchDisplay.Suggestions -> {
}
SearchDisplay.Results -> {
}
}
}
}
关于android - Jetpack Compose 用户界面 : How to create SearchView?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58840019/
有没有一种简单的方法可以在 compose 中删除开关的内部填充? 我尝试在其修饰符中提供 0.dp,但它并没有摆脱内部填充 Switch( modifier = Modifier
我正在使用底部导航栏,每个菜单都会将用户导航到特定的可组合屏幕。我使用导航库来管理它们之间的导航。 我为所有可组合项使用一个通用的 ViewModel。我在其中一个可组合项中使用惰性列,当我通过单击底
我在撰写屏幕中有一个 TextField 和一个 ModalDrawer。我想在用户打开抽屉时关闭软键盘,但我一直无法弄清楚如何。在 ModalDrawer afaik 中没有触发 onOpened
我一直在搜索文档,但找不到确认。有谁知道navigation和 compose来自 Android Jetpack 的组件彼此兼容吗? 我知道Jetpack Compose尚未准备好生产,仅处于开发人
我正在尝试将我的应用程序更新为新的撰写版本,但它给了我一个我不知道如何修复的错误。当我运行时,错误仍然存在于我的运行中。我的旧项目正常工作,但我想要的是更改版本,如果有人可以帮助我,我将不胜感激
我有这样的用户界面: val scrollState = rememberScrollState() Column( modifier = Modifier
有没有办法在 Compose 中的列表(列/行)更改上获得动画效果,看起来类似于带有 setItemAnimator 的 recyclerview 动画? 最佳答案 目前没有办法用 LazyColum
我想隐藏状态栏,我已经使用伴奏库做到了这一点: val systemUiController = rememberSystemUiController() systemUiController.isS
我想隐藏状态栏,我已经使用伴奏库做到了这一点: val systemUiController = rememberSystemUiController() systemUiController.isS
使用 Android View,我可以像这样将焦点移动到 View: fun View.requestAccessibilityFocus() { requestFocus() sen
我正在尝试在我的 Android 应用程序中使用 Jetpack Compose 播放视频。要使用 ExoPlayer 进行流式传输,但我真的不明白如何实现全屏按钮,有什么建议吗? @Composab
通常可以使用修饰符将不同的形状分配给可组合项,但在此可组合项中没有这样做。 我希望图像中标记的部分是一个圆圈 你可以在下面看到我写的代码 @Composable fun StandardCheckbo
Jetpack compose 提供了很多 Material 组件,如 TextField 等。 然而,要构建类似文件编辑器的东西,可以使用什么样的组件来支持多行文本任意长的文本操作,如选择文本、剪切
我们可以使用 Scaffold 在 JetpackCompose 中使用抽屉导航如下 Scaffold( drawerContent = { Text(text ="Drawer") } )
对不起,我几乎不会说英语。 机器翻译: 如何为 Jetpack Compose 设置阴影颜色? 我可以设置阴影,但它们很难看。 Jetpack Compose 代码: Surface( mod
我正在开发一个小型 jetpack-compose 演示聊天应用程序。所以我需要在底部有一个带有 TextField 和一个要发送的按钮的栏,就像在 WhatsApp 中一样......我认为最好使用
我正在 Jetpack Compose Desktop 中创建一个应用程序,它将接受用户输入,在用户重新打开应用程序后,输入值应该在那里。我的意思是,在用户重新打开应用程序后,用户给定的数据应该在那里
描述 在 SnackbarHostState 上调用 showSnackbar 并传递 duration 参数不会关闭 Snackbar。协程似乎无限期暂停。 重现步骤: val snackbarHo
谁能建议如何在 Jetpack Compose Navigation 的不同部分共享 ViewModel? 根据文档,viewModels 通常应该在使用事件范围的不同组合函数中共享,但如果在导航内部
我想在相机预览上方创建一个半透明图层,如下所示: 我在我的应用程序中完成了相机预览,我想要的只是在预览上有一个半透明的图层,带有剪裁的卡片形状,如图所示(带有圆角)。 所以:全屏相机预览,上面有一个全
我是一名优秀的程序员,十分优秀!