Как анимировать значок элемента меню BottomNavigationView с помощью ObjectAnimator - PullRequest
7 голосов
/ 18 января 2020

Я использую android конструкций поддержки BottomNavigationView для навигации по нижней вкладке.

 <android.support.design.widget.BottomNavigationView
        android:id="@+id/main_nav"
        android:layout_width="match_parent"
        android:layout_height="56dp"
        app:labelVisibilityMode="unlabeled"
        app:itemIconSize="40dp"
        android:layout_alignParentStart="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentBottom="true"
        app:itemBackground="@color/blue_active"
        app:menu="@menu/nav_items">


    </android.support.design.widget.BottomNavigationView>

Я пытаюсь сделать следующее:

Программно анимировать вкладку (меню ) значок с ObjectAnimator при нажатии

Это меню:

<menu xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android">

    <item
        android:id="@+id/nav_home"
        android:icon="@drawable/ic_home"
        android:title="@string/nav_home" />
    <item
        android:id="@+id/nav_games"
        android:icon="@drawable/games"
        android:title="@string/nav_games" />
    <item
        android:id="@+id/nav_profile"
        android:icon="@drawable/profile"
        android:title="@string/nav_profile" />
</menu>

Код:

 mMainNav.setOnNavigationItemSelectedListener { item ->
            when (item.itemId) {
                R.id.nav_home -> {

                   //item.icon is drawable
                   var myAnimation =  ObjectAnimator.ofFloat(item.icon,"rotation",0f,360f)
                    myAnimation.duration = 500


                    myAnimation.start()  //nothing happens
                    setFragment(HomeFragment)

                    true
                }

С этим ничего не происходит без анимации .

Что не так? Должен ли я использовать другой способ для анимации, или я просто применяю это неправильно?

Я попытался анимировать просмотр изображений с помощью значка, который можно нарисовать, а затем установить его в качестве элементов actionview, но это также не работает. (Происходит некоторая реакция, но возникает какое-то странное поведение),

 var drawable = applicationContext.getDrawable(R.drawable.ic_home)
                    var someImageView = ImageView(this)
                    someImageView.setImageDrawable(drawable)

                   var myAnimation =  ObjectAnimator.ofFloat(someImageView,"rotation",0f,100f)
                    myAnimation.duration = 2000


                    myAnimation.start()
                    item.actionView = someImageView

ссылка на награду сломан, пожалуйста, проверьте это: https://streamable.com/99pa8

Ответы [ 2 ]

3 голосов
/ 14 февраля 2020

Попробуйте приведенное ниже решение

Шаг - 1

Создание рисованного анимированного вектора с использованием ShapeShifter и импорт этого анимированного вектора можно добавить в Android проект из Android Studio и поместить его в src/res/drawable.

Шаг - 2

Создать Анимированный список состояний Рисуется для каждого значка в нижнем навигационном представлении.

anim_settings. xml

<?xml version="1.0" encoding="utf-8"?>
<animated-selector xmlns:tools="http://schemas.android.com/tools"
    xmlns:android="http://schemas.android.com/apk/res/android"
    tools:targetApi="16">

    <!-- provide a different drawable for each state-->
    <item android:id="@+id/state_on"
        android:drawable="@drawable/ic_settings_active_avd"
        android:state_checked="true"/>

    <item android:id="@+id/state_off"
        android:drawable="@drawable/ic_settings_inactive"/>

    <!-- specify transitions -->
    <transition
        android:drawable="@drawable/ic_settings_active_avd"
        android:fromId="@id/state_off"
        android:toId="@id/state_on" />

</animated-selector>

Шаг - 3

Используйте этот анимированный список состояний для рисования в виде значка.

menu_bottom_nav. xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/item_settings_fragment"
        android:icon="@drawable/anim_settings"
        android:title="@string/settings"
        app:showAsAction="always" />
...
</menu>

Шаг - 4

Установите это menu_bottom_nav. xml как меню для нижнего вида навигации.

<android.support.design.widget.BottomNavigationView
        android:id="@+id/bottomNav"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        android:showAsAction="always|withText"
        app:itemTextColor="@drawable/bottom_navigation_tab_selector"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:menu="@menu/menu_bottom_nav"
        android:background="@color/colorWhite"
        app:elevation="0dp"/>

Теперь Запустите приложение android на вашем устройства и проверьте анимацию нижней навигационной панели.

Для получения более подробной информации, пожалуйста, эту ссылку.

Я надеюсь, что это может помочь вам!

1 голос
/ 12 февраля 2020

Попробуйте это:

mMainNav.setOnNavigationItemSelectedListener { item ->
            when (item.itemId) {
                R.id.nav_home -> {
                   val anim = myAnim(view,targetHeight)
                   anim.duration = /*whatever you want*/
                   view.startAnimation(anim)
                   ObjectAnimator.ofFloat(item.icon,"rotation",0f,360f).apply{
                    duration = 500
                    start()
                    setFragment(HomeFragment)
                    }
                }

Добавьте этот внутренний класс, где вы хотите использовать анимацию

inner class myAnim(
        private val view: View,
        private val targetHeight: Int
    ) : Animation() {

        override fun applyTransformation(interpolatedTime: Float, t: Transformation?) {
            val height = (interpolatedTime * targetHeight).roundToInt()
            if (height > 1) {
                view.layoutParams.height = (interpolatedTime * targetHeight).roundToInt()
                view.requestLayout()
            }
        }

        override fun willChangeBounds(): Boolean {
            return true
            /*or false, depending on your animation*/
        }
    }
...