Selector animado en Jetpack Compose | de Peter Törnhult | enero 2023

¿Está migrando a Compose pero no puede hacer que su AnimatedStateListDrawables funcione? Aquí hay una solución que funcionó bastante bien para mí 👍Al intentar migrar BottomNavigationView a la barra de navegación de Compose (Material3), me quedé atascado con errores al cargar mis íconos en Compose. En mi aplicación, creé AnimatedVectorDrawables con AnimatedStateListDrawable para animar automáticamente los iconos de las pestañas de la barra de navegación. Pasé un tiempo averiguando cómo usarlos en Compose, pero el selector AFAICT animado no es compatible con Compose 🥺Pestañas de material original con BottomNavigationView Parecía que tenía que elegir entre omitir animaciones o crear otras nuevas en Compose. Pero en lugar de eso pospuse mi decisión para poder encontrar otra solución más tarde. Después de algunas semanas, estaba cerca de completar mi migración de Compose, pero BottomNavigationView seguía siendo un bloqueador. Me gusta el hecho de que estas animaciones/transiciones se mantengan en recursos y dedicar tiempo a crear nuevas animaciones en Compose no me atraía porque ya había dedicado tiempo a crear estas animaciones. Pero resultó que había una tercera alternativa que era bastante obvia: AndroidView 😀 Al poner un ImageView dentro de un AndroidView pude cargar el selector animado sin ningún problema. Pero pegar estos íconos en NavigationBarItem aún no mostraba ninguna animación. BottomNavigationView usa la interfaz Checkable para indicar qué pestaña está activa y las transiciones de selección animadas se configuran usando el estado marcado. Así que hice que ImageView fuera verificable y pasé el estado de la pestaña seleccionada a cada AndroidView. Aquí está el resultado:Material 3 NavigationBar con AnimatedStateListDrawables@Composablefun AnimatedIcon(@DrawableRes animationIcon: Int,isSelected: Boolean,modifier: Modifier = Modifier,) {AndroidView(modifier = modifier.size(24.dp),factory = { context ->CheckableImageView(context) .apply {val drawable = ContextCompat.getDrawable(context, animationIcon)setImageDrawable(drawable)isChecked = isSelectedif (drawable is Animable) drawable.start()}},update = { view ->view.isChecked = isSelected})}clase privada CheckableImageView(contexto: Contexto, attrs: AttributeSet? = nulo) :AppCompatImageView(contexto, attrs),Checkable {private var mChecked = falseoverride fun onCreateDrawableState(extraSpace: Int): IntArray {val drawableState = super.onCreateDrawableState(extraSpace + 1)if (isChecked) {mergeDrawableStates(drawableState, CHECKED_STATE_SET)}return drawableState}override fun toggle() {isChecked = !mChecked}override fun isChecked(): Boolean = mCheckedoverride fun setChecked(checked: Boolean) {if (mChecked != chec k ed) {mChecked =checkedrefreshDrawableState()}}objeto complementario {private val CHECKED_STATE_SET = intArrayOf(android.R.attr.state_checked)}}@Composableprivate fun BottomNavigationTabs(navController: NavController,onSetTab: (BottomNavItem) -> Unit,) { val items = listOf(BottomNavItem.Home,BottomNavItem.Games,BottomNavItem.Players,BottomNavItem.Menu,)NavigationBar {val navBackStackEntry by navController.currentBackStackEntryAsState()val currentRoute = navBackStackEntry?.destination?.routeitems.forEach { item ->val isSelected = ruta actual == item.routeval title = stringResource(id = item.titleRes)NavigationBarItem(s seleccionado = isSelected,onClick = { onSetTab(item) }, alwaysShowLabel = false,label = {Text(text = title,style = MaterialTheme. tipografía labelSmall,)},icon = {AnimatedIcon(item.icon,isSelected = isSelected,)})}}} Claro, esto se siente un poco raro, pero me alegro de poder seguir usando AnimatedVectorDrawables, y tengo una barra de navegación que funciona . Si hay una forma mejor (más parecida a la composición) de usar mis selectores animados tal como están, me gustaría saberlo.

¡Gracias por leer!

Deja una respuesta

Tu dirección de correo electrónico no será publicada.