如何使用 Android Jetpack Compose 对 SearchBox 占位符文本进行动画处理?

问题描述 投票:0回答:1

我想为我的 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...")
            }
        }
    }
    ...
)
android android-jetpack-compose android-animation searchbar
1个回答
0
投票

我已经创建了简单的 searchBox 示例。我使用了两个

AnimatedVisibility
块作为占位符,因为在所需的 gif 中,您可以看到第一个占位符隐藏后出现第二个占位符,因此
Crossfade
不是最佳选择。

基本上有:

  1. SearchBox 的初始
    slideIn
    动画
  2. fadeOut
    初始占位符的动画
  3. 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 = {

            }
        )
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.