Android在setvisibility(view.Gone)的同时添加简单的动画


237

我已经设计了一个简单的布局。我已经完成了没有动画的设计,但是现在我想在textview click事件时添加动画,但我不知道如何使用它。我的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>

我的java

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);
            }
        });

    }
}

Answers:


705

您可以做两件事来添加动画,首先可以让android为您设置布局动画。这样,每次您更改布局中的某些内容(如更改视图可见性或视图位置)时,android都会自动创建淡入淡出/过渡动画。要使用那套

android:animateLayoutChanges="true"

在布局的根节点上。

您的第二个选择是手动添加动画。为此,我建议您使用Android 3.0(Honeycomb)中引入的新动画API。我可以举几个例子:

这淡出了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);

而且,您可以根据需要组合任意数量的动画,例如,它会淡出a 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我不会称其为超级通话是多余的。不要对没有任何错误做肤浅的编辑。
Xaver Kapeller '16

5
好的,但是逆不能正确地工作吗?view.setVisibility(View.VISIBLE); 使用alpha(1.0f),出现100个填充顶部...
交付

15
必须先清除动画,然后再设置可见性>> view.clearAnimation(); view.setVisibility(View.GONE);否则布局将保持不可见并且不会消失。
Eftekhari

2
@Eftekhari他们一点也不占用资源。而且,如果您拥有最新的Android版本,但仍会遇到滞后的情况,那可能比您的旧手机内存不足或图形芯片坏了。我不是在谈论新图书馆。动画师是本地人。它们是Android框架的一部分。它们已于5年前发布,今天,所有设备中有97.9%支持它们。没有理由不使用Animators或至少ViewCompat.animate()是支持库的一部分,并且不使用较新版本的Animators和不使用Android 3.0及更低版本的View Animations。
Xaver Kapeller '16

1
但是,当所有设备的97.9%是Android 4.0及更高版本时,就没有太多用例了ViewCompat.animate()
Xaver Kapeller '16

69

动画化Visibility更改的最简单方法是使用Transition API支持(androidx)软件包中可用的方法。只需调用TransitionManager.beginDelayedTransition方法,然后更改视图的可见性。有喜欢的几个默认的转变FadeSlide

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包中使用。一切都是向后兼容的
ashakirov

2
如何扩展/折叠视图组?
TheRealChx101 '19

你可以做多个beginDelayedTransitions吗?
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 '18

非常简单而优雅的解决方案
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);声明救了我的一天。这肯定是一个错误。
Michal Vician

@MichalVician很高兴!
jiahao

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);
                }
            });
}

资源

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.