Android добавляет простые анимации во время установки видимости (view.Gone)


237

Я разработал простой макет. Я закончил дизайн без анимации, но теперь я хочу добавить анимацию, когда в текстовом клике происходит событие, и я не знаю, как его использовать. Мой дизайн XML выглядит хорошо или нет? Мы ценим любые предложения.

Мой XML

<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:longClickable="false"
    android:orientation="vertical"
    android:weightSum="16" >

<LinearLayout 
    android:layout_width="fill_parent"
    android:layout_height="0dp"
    android:orientation="vertical"
    android:background="#00DDA0"
    android:layout_weight="3" >
</LinearLayout>
 <TextView
        android:id="@+id/Information1"
        android:layout_width="match_parent"
        android:layout_height="1dp" 
        android:text="Child Information" 
        android:background="#0390BE"
        android:layout_weight="0.75"
        android:textColor="#FFFFFF"
        android:layout_gravity="center|fill_horizontal"/>

 <LinearLayout
     android:id="@+id/layout1"
     android:layout_width="fill_parent"
     android:layout_height="0dp"
     android:layout_weight="8.5"
     android:background="#BBBBBB"
     android:orientation="vertical" >

     <TextView
         android:id="@+id/textView1"
         android:layout_width="match_parent"
         android:layout_height="match_parent"        
         android:text="TextView" />
 </LinearLayout>

  <TextView
        android:id="@+id/Information2"
        android:layout_width="match_parent"
        android:layout_height="0dp" 
        android:text="Parent Information" 
        android:background="#0390BE"
        android:layout_weight="0.75"
        android:textColor="#FFFFFF"
        android:layout_gravity="center|fill_horizontal"/>
  <LinearLayout 
          android:id="@+id/layout2"
    android:layout_width="fill_parent"
    android:layout_height="0dp"
    android:orientation="vertical"
    android:background="#BBBBBB"
    android:layout_weight="8.5" >
     <TextView
         android:id="@+id/textView2"
         android:layout_width="match_parent"
         android:layout_height="match_parent"        
         android:text="TextView" />
      </LinearLayout>
   <TextView
        android:id="@+id/Information3"
        android:layout_width="match_parent"
        android:layout_height="0dp" 
        android:text="Siblings" 
        android:background="#0390BE"
        android:layout_weight="0.75"
        android:textColor="#FFFFFF"
        android:layout_gravity="center|fill_horizontal"/>
   <LinearLayout 
          android:id="@+id/layout3"
    android:layout_width="fill_parent"
    android:layout_height="0dp"
    android:orientation="vertical"
    android:background="#BBBBBB"
    android:layout_weight="8.5" >
     <TextView
         android:id="@+id/textView3"
         android:layout_width="match_parent"
         android:layout_height="match_parent"        
         android:text="TextView" />
      </LinearLayout>
    <TextView
        android:id="@+id/Information4"
        android:layout_width="match_parent"
        android:layout_height="0dp" 
        android:text="Teacher Information" 
        android:background="#0390BE"
        android:layout_weight="0.75"
        android:textColor="#FFFFFF"
        android:layout_gravity="center|fill_horizontal"/>
    <LinearLayout 
          android:id="@+id/layout4"
    android:layout_width="fill_parent"
    android:layout_height="0dp"
    android:orientation="vertical"
    android:background="#BBBBBB"
    android:layout_weight="8.5" >
     <TextView
         android:id="@+id/textView4"
         android:layout_width="match_parent"
         android:layout_height="match_parent"        
         android:text="TextView" />
      </LinearLayout>
     <TextView
        android:id="@+id/Information5"
        android:layout_width="match_parent"
        android:layout_height="0dp" 
        android:text="Grade Information" 
        android:background="#0390BE"
        android:layout_weight="0.75"
        android:textColor="#FFFFFF"
        android:layout_gravity="center|fill_horizontal"/>
     <LinearLayout 
          android:id="@+id/layout5"
    android:layout_width="fill_parent"
    android:layout_height="0dp"
    android:orientation="vertical"
    android:background="#BBBBBB"
    android:layout_weight="8.5" >
     <TextView
         android:id="@+id/textView5"
         android:layout_width="match_parent"
         android:layout_height="match_parent"        
         android:text="TextView" />
      </LinearLayout>
      <TextView
        android:id="@+id/Information6"
        android:layout_width="match_parent"
        android:layout_height="0dp" 
        android:text="Health Information" 
        android:background="#0390BE"
        android:layout_weight="0.75"
        android:textColor="#FFFFFF"
        android:layout_gravity="center|fill_horizontal"/>
      <LinearLayout 
          android:id="@+id/layout6"
    android:layout_width="fill_parent"
    android:layout_height="0dp"
    android:orientation="vertical"
    android:background="#BBBBBB"
    android:layout_weight="8.5" >
    <TextView
         android:id="@+id/textView5"
         android:layout_width="match_parent"
         android:layout_height="match_parent"        
         android:text="TextView" 
         android:layout_weight="8.5" />
      </LinearLayout>

</LinearLayout>

Моя ява

public class Certify_Info extends Activity {

    private static TextView tv2,tv3,tv5,tv6,tv4,tv1;
    private static LinearLayout l1,l2,l3,l4,l5,l6;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_certify__info);

        tv1=(TextView) findViewById(R.id.Information1);
        tv2=(TextView) findViewById(R.id.Information2);
        tv3=(TextView) findViewById(R.id.Information3);
        tv4=(TextView) findViewById(R.id.Information4);
        tv5=(TextView) findViewById(R.id.Information5);
        tv6=(TextView) findViewById(R.id.Information6); 

        l1=(LinearLayout) findViewById(R.id.layout1);
        l2=(LinearLayout) findViewById(R.id.layout2);
        l3=(LinearLayout) findViewById(R.id.layout3);
        l4=(LinearLayout) findViewById(R.id.layout4);
        l5=(LinearLayout) findViewById(R.id.layout5);
        l6=(LinearLayout) findViewById(R.id.layout6); 

        l2.setVisibility(View.GONE);
        l3.setVisibility(View.GONE); 
        l4.setVisibility(View.GONE); 
        l5.setVisibility(View.GONE);
        l6.setVisibility(View.GONE);

        tv1.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                l2.setVisibility(View.GONE);
                l3.setVisibility(View.GONE); 
                l4.setVisibility(View.GONE); 
                l5.setVisibility(View.GONE);
                l6.setVisibility(View.GONE);
                l1.setVisibility(View.VISIBLE);
            }
        });
        tv2.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                l1.setVisibility(View.GONE);
                l3.setVisibility(View.GONE); 
                l4.setVisibility(View.GONE); 
                l5.setVisibility(View.GONE);
                l6.setVisibility(View.GONE);
                l2.setVisibility(View.VISIBLE);
            }
        });
        tv3.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                l1.setVisibility(View.GONE);
                l2.setVisibility(View.GONE);
                l4.setVisibility(View.GONE); 
                l5.setVisibility(View.GONE);
                l6.setVisibility(View.GONE);
                l3.setVisibility(View.VISIBLE);

            }
        });
        tv4.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                l1.setVisibility(View.GONE);
                l2.setVisibility(View.GONE);
                l3.setVisibility(View.GONE); 
                l4.setVisibility(View.GONE); 
                l5.setVisibility(View.GONE);
                l6.setVisibility(View.GONE);
                l4.setVisibility(View.VISIBLE); 
            }
        });
        tv5.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                l1.setVisibility(View.GONE);
                l2.setVisibility(View.GONE);
                l3.setVisibility(View.GONE); 
                l4.setVisibility(View.GONE); 
                l6.setVisibility(View.GONE);
                l5.setVisibility(View.VISIBLE); 
            }
        });
        tv6.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                l1.setVisibility(View.GONE);
                l2.setVisibility(View.GONE);
                l3.setVisibility(View.GONE); 
                l4.setVisibility(View.GONE); 
                l5.setVisibility(View.GONE);
                l6.setVisibility(View.VISIBLE);
            }
        });

    }
}

Ответы:


706

Вы можете сделать две вещи, чтобы добавить анимацию, во-первых, вы можете позволить Android анимировать изменения макета для вас. Таким образом, каждый раз, когда вы изменяете что-то в макете, например, изменяете видимость или положение вида, android автоматически создает анимацию затухания / перехода. Чтобы использовать этот набор

android:animateLayoutChanges="true"

на корневом узле в вашем макете.

Второй вариант - добавить анимацию вручную. Для этого я предлагаю вам использовать новый API анимации, представленный в Android 3.0 (Honeycomb). Я могу привести несколько примеров:

Это затухает View:

view.animate().alpha(0.0f);

Это возвращает его обратно в:

view.animate().alpha(1.0f);

Это сдвигает Viewвниз по высоте:

view.animate().translationY(view.getHeight());

Это возвращает в Viewисходное положение после того, как оно было перемещено куда-то еще:

view.animate().translationY(0);

Вы также можете использовать, setDuration()чтобы установить продолжительность анимации. Например, это исчезает в Viewтечение 2 секунд:

view.animate().alpha(0.0f).setDuration(2000);

И вы можете комбинировать столько анимаций, сколько захотите, например, это затухает Viewи одновременно перемещает его вниз за период 0,3 секунды:

view.animate()
        .translationY(view.getHeight())
        .alpha(0.0f)
        .setDuration(300);

И вы также можете назначить слушателя анимации и реагировать на все виды событий. Например, когда начинается анимация, когда она заканчивается или повторяется и т. Д. Используя абстрактный класс, AnimatorListenerAdapterвам не нужно реализовывать сразу все обратные вызовы, AnimatorListenerа только те, которые вам нужны. Это делает код более читабельным. Например, следующий код постепенно затухает и Viewперемещает его вниз на высоту в течение периода 0,3 секунды (300 миллисекунд), а когда анимация завершена, ее видимость устанавливается на View.GONE.

view.animate()
        .translationY(view.getHeight())
        .alpha(0.0f)
        .setDuration(300)
        .setListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                view.setVisibility(View.GONE);
            }
        });

6
@Natix Я бы не назвал этот супер-вызов избыточным. Не делайте поверхностных правок, в этом нет ничего плохого.
Ксавер Капеллер

5
Это хорошо, но обратное не работает правильно, почему? view.setVisibility (View.VISIBLE); С альфа (1.0f), появляются с верхним
слоем

15
Необходимо очистить анимацию перед установкой видимости >> view.clearAnimation(); view.setVisibility(View.GONE);иначе макет останется невидимым и не пропадет.
Эфтехари

2
@Eftekhari Они совсем не ресурсоемкие. И если у вас установлена ​​последняя версия Android, но вы все равно испытываете отставание, чем ваш старый телефон с нехваткой памяти или с плохим графическим чипом. И я не говорю о новой библиотеке. Аниматоры родные. Они являются частью Android Framework. Они были выпущены 5 лет назад, и сегодня их поддерживают 97,9% всех устройств. Нет никаких причин не использовать Animators или, по крайней мере, ViewCompat.animate()который является частью библиотеки поддержки и использует Animators в более новых версиях и View Animations на Android 3.0 и ниже.
Ксавер Капеллер

1
Но когда 97,9% всех устройств являются Android 4.0 и выше, для них не так уж много пользы ViewCompat.animate().
Ксавер Капеллер

70

Самый простой способ оживить Visibilityизменения - это использовать их Transition APIв пакете поддержки (androidx). Просто вызовите TransitionManager.beginDelayedTransitionметод и измените видимость представления. Есть несколько переходов по умолчанию , как Fade, Slide.

import androidx.transition.TransitionManager;
import androidx.transition.Transition;
import androidx.transition.Fade;

private void toggle() {
    Transition transition = new Fade();
    transition.setDuration(600);
    transition.addTarget(R.id.image);

    TransitionManager.beginDelayedTransition(parent, transition);
    image.setVisibility(show ? View.VISIBLE : View.GONE);
}

Где parentродитель ViewGroupанимированного представления. Результат:

введите описание изображения здесь

Вот результат с Slideпереходом:

import androidx.transition.Slide;

Transition transition = new Slide(Gravity.BOTTOM);

введите описание изображения здесь

Пользовательский переход легко написать, если вам нужно что-то другое. Вот пример, с CircularRevealTransitionкоторым я написал в другом ответе . Он показывает и скрывает вид с помощью анимации CircularReveal.

Transition transition = new CircularRevealTransition();

введите описание изображения здесь

android:animateLayoutChanges="true"опция делает то же самое, она просто использует AutoTransition в качестве перехода.


@ TouhidulIslam нет. Эти классы доступны в пакете androidx. Все обратно совместимо
ашакиров

2
Как насчет расширения / свертывания группы представлений?
TheRealChx101

Вы можете сделать несколько beginDelayedTransitionс?
Jeongbebs

26

Пожалуйста, проверьте эту ссылку. Который позволит анимации, такие как L2R, R2L, T2B, B2T анимации.

Этот код показывает анимацию слева направо

TranslateAnimation animate = new TranslateAnimation(0,view.getWidth(),0,0);
animate.setDuration(500);
animate.setFillAfter(true);
view.startAnimation(animate);
view.setVisibility(View.GONE);

если вы хотите сделать это из R2L, используйте

TranslateAnimation animate = new TranslateAnimation(0,-view.getWidth(),0,0);

сверху вниз, как

TranslateAnimation animate = new TranslateAnimation(0,0,0,view.getHeight());

и наоборот ...


8
Это смещает вид из исходного положения.
Relm

24

Попробуйте добавить эту строку в родительский макет xml

 android:animateLayoutChanges="true"

Ваш макет будет выглядеть так

<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:animateLayoutChanges="true"
    android:longClickable="false"
    android:orientation="vertical"
    android:weightSum="16">

    .......other code here

    </LinearLayout>

это сработало для меня. Моя установка использует макет ограничения в качестве корневого представления. Когда представление установлено на View.VISIBLE, отображается анимация
EdgeDev

очень простое и элегантное решение
Naveed Ahmad

11

Основываясь на ответе @Xaver Kapeller, я нашел способ создания анимации прокрутки при появлении на экране новых видов (а также анимации, чтобы скрыть их).

Это выходит из этого состояния:

  • кнопка
  • Последняя кнопка

в

  • кнопка
  • Кнопка 1
  • Кнопка 2
  • Кнопка 3
  • Кнопка 4
  • Последняя кнопка

и наоборот.

Таким образом, когда пользователь нажимает первую кнопку, элементы «Кнопка 1», «Кнопка 2», «Кнопка 3» и «Кнопка 4» будут отображаться с использованием анимации затухания, а элемент «Последняя кнопка» будет перемещаться вниз до конца. Высота макета также изменится, что позволит правильно использовать вид прокрутки.

Это код для отображения элементов с анимацией:

private void showElements() {
    // Precondition
    if (areElementsVisible()) {
        Log.w(TAG, "The view is already visible. Nothing to do here");
        return;
    }

    // Animate the hidden linear layout as visible and set
    // the alpha as 0.0. Otherwise the animation won't be shown
    mHiddenLinearLayout.setVisibility(View.VISIBLE);
    mHiddenLinearLayout.setAlpha(0.0f);
    mHiddenLinearLayout
            .animate()
            .setDuration(ANIMATION_TRANSITION_TIME)
            .alpha(1.0f)
            .setListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    super.onAnimationEnd(animation);
                    updateShowElementsButton();
                    mHiddenLinearLayout.animate().setListener(null);
                }
            })
    ;

    mLastButton
            .animate()
            .setDuration(ANIMATION_TRANSITION_TIME)
            .translationY(mHiddenLinearLayoutHeight);

    // Update the high of all the elements relativeLayout
    LayoutParams layoutParams = mAllElementsRelativeLayout.getLayoutParams();

    // TODO: Add vertical margins
    layoutParams.height = mLastButton.getHeight() + mHiddenLinearLayoutHeight;
}

и это код, чтобы скрыть элементы анимации:

private void hideElements() {
    // Precondition
    if (!areElementsVisible()) {
        Log.w(TAG, "The view is already non-visible. Nothing to do here");
        return;
    }

    // Animate the hidden linear layout as visible and set
    mHiddenLinearLayout
            .animate()
            .setDuration(ANIMATION_TRANSITION_TIME)
            .alpha(0.0f)
            .setListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    Log.v(TAG, "Animation ended. Set the view as gone");
                    super.onAnimationEnd(animation);
                    mHiddenLinearLayout.setVisibility(View.GONE);
                    // Hack: Remove the listener. So it won't be executed when
                    // any other animation on this view is executed
                    mHiddenLinearLayout.animate().setListener(null);
                    updateShowElementsButton();
                }
            })
    ;

    mLastButton
            .animate()
            .setDuration(ANIMATION_TRANSITION_TIME)
            .translationY(0);

    // Update the high of all the elements relativeLayout
    LayoutParams layoutParams = mAllElementsRelativeLayout.getLayoutParams();

    // TODO: Add vertical margins
    layoutParams.height = mLastButton.getHeight();
}

Обратите внимание, что существует простой способ взломать метод, чтобы скрыть анимацию. На слушателе анимации mHiddenLinearLayout мне пришлось удалить самого слушателя, используя:

mHiddenLinearLayout.animate().setListener(null);

Это связано с тем, что, как только слушатель анимации присоединяется к представлению, в следующий раз, когда любая анимация будет выполняться в этом представлении, слушатель также будет выполняться. Это может быть ошибка в слушателе анимации.

Исходный код проекта находится на GitHub: https://github.com/jiahaoliuliu/ViewsAnimated

Удачного кодирования!

Обновление : для любого слушателя, прикрепленного к представлениям, его следует удалить после окончания анимации. Это делается с помощью

view.animate().setListener(null);

Это лучший ответ
Naveen Kumar M

1
view.animate().setListener(null);Заявление спасло мой день. Это определенно кажется ошибкой.
Михал Вициан

@MichalVician Рад, что сделал!
Цзяхао

8

Я смог показать / скрыть меню следующим образом:

MenuView.java (расширяет FrameLayout)

private final int ANIMATION_DURATION = 500;

public void showMenu()
{
    setVisibility(View.VISIBLE);
    animate()
            .alpha(1f)
            .setDuration(ANIMATION_DURATION)
            .setListener(null);
}

private void hideMenu()
{
    animate()
            .alpha(0f)
            .setDuration(ANIMATION_DURATION)
            .setListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    setVisibility(View.GONE);
                }
            });
}

Источник

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.