我想为我的 SearchBar Composable 的占位符设置动画,就像 Google Play 商店搜索栏占位符一样。 我尝试了一下,但似乎没有 Google Play 商店那么微妙。
这就是我想要实现的目标,
这就是我到目前为止所做的,
这是我的代码,
var showInitialPlaceholder by remember { mutableStateOf(true) }
LaunchedEffect(Unit) {
delay(1000)
showInitialPlaceholder = false
}
SearchBar(
...
placeholder = {
Crossfade(targetState = showInitialPlaceholder) { isInitial ->
if (isInitial) {
Text("Google Play")
} else {
Text("Search...")
}
}
}
...
)
我已经创建了简单的 searchBox 示例。我使用了两个
AnimatedVisibility
块作为占位符,因为在所需的 gif 中,您可以看到第一个占位符隐藏后出现第二个占位符,因此 Crossfade
不是最佳选择。
基本上有:
slideIn
动画fadeOut
初始占位符的动画fadeIn
最终占位符的动画不幸的是,当涉及到这些小细节时,我的眼睛不太好,所以我在打开窗口动画比例的情况下对其进行了调试并也实现了它。也许尝试调整动画持续时间、延迟并选择所需的缓动。 试试这个,看看它对你有什么作用,希望它至少有一点帮助。
@Composable
fun AnimatedSearchBox(modifier: Modifier = Modifier) {
val context = LocalContext.current
//scale for debugging with window scale option
val animScale = remember {
Settings.Global.getFloat(
context.contentResolver,
Settings.Global.ANIMATOR_DURATION_SCALE, 1.0f
)
}
//Searchbar slide animation
var isSearchBarVisible by remember { mutableStateOf(false) }
//Initial "Google Play" visibility
var isInitialVisible by remember { mutableStateOf(true) }
//Placeholder visibility
var isSecondPhaseVisible by remember { mutableStateOf(false) }
//Searchbar properties
var isActive by remember { mutableStateOf(false) }
var query by remember { mutableStateOf("") }
LaunchedEffect(Unit) {
//Initial delay for searchbar slide animation
delay((animScale * 1000).toLong())
isSearchBarVisible = true
//Delay before hiding initial placeholder
delay((1000 * animScale.toLong()))
isInitialVisible = false
//Delay before showing placeholder, must be lower than initial placeholder animation duration
//To make it more smooth
delay(timeMillis = (250 * animScale).toLong())
isSecondPhaseVisible = true
}
AnimatedVisibility(
visible = isSearchBarVisible,
enter = fadeIn() + slideInVertically { it },
) {
SearchBar(
modifier = modifier,
query = query,
onQueryChange = { query = it },
active = isActive,
placeholder = {
AnimatedVisibility(
visible = isInitialVisible,
exit = fadeOut(
animationSpec = tween(
durationMillis = 400,
easing = EaseInOutExpo
)
)
) {
Text("Google Play")
}
AnimatedVisibility(
visible = isSecondPhaseVisible,
enter = fadeIn(
animationSpec = tween(
durationMillis = 200,
easing = EaseInOutExpo
)
)
) {
Text("Search...")
}
},
onActiveChange = {
isActive = it
},
onSearch = {},
leadingIcon = {
Icon(
painter = painterResource(id = R.drawable.outline_search_24),
contentDescription = null
)
},
trailingIcon = {
Icon(
painter = painterResource(id = R.drawable.baseline_checklist_rtl_24),
contentDescription = null
)
},
content = {
}
)
}
}