Java Android在设置可见性时添加简单动画(view.Gone)

Java Android在设置可见性时添加简单动画(view.Gone),java,android,android-animation,Java,Android,Android Animation,我已经设计了一个简单的布局。我已经完成了没有动画的设计,但是现在我想在textview单击事件时添加动画,我不知道如何使用它。 我的xml设计看起来好还是不好? 如有任何建议,将不胜感激 我的XML <?xml version="1.0" encoding="UTF-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fil

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

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

android:animateLayoutChanges="true"
在布局中的根节点上

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

这将淡出
视图

view.animate().alpha(0.0f);
这会将其淡入:

view.animate().alpha(1.0f);
这会将
视图向下移动其高度:

view.animate().translationY(view.getHeight());
这会在将
视图移动到其他位置后将其返回到起始位置:

view.animate().translationY(0);
您还可以使用
setDuration()
设置动画的持续时间。例如,这会在2秒钟内淡出
视图

view.animate().alpha(0.0f).setDuration(2000);
您可以根据需要组合任意多个动画,例如,这将淡出
视图
,并在0.3秒内同时向下移动:

view.animate()
        .translationY(view.getHeight())
        .alpha(0.0f)
        .setDuration(300);
您还可以为动画指定一个侦听器,并对各种事件做出反应。例如动画开始、结束或重复等。通过使用抽象类
AnimatorListenerAdapter
,您不必一次实现
AnimatorListener
的所有回调,只需实现您需要的回调。这使代码更具可读性。例如,以下代码淡出
视图
在0.3秒(300毫秒)的时间内将其向下移动高度,动画完成后,其可见性设置为
视图。消失

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);
            }
        });
请检查链接。这将允许类似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());

反之亦然。

根据@Xaver Kapeller的回答,我想出了一种方法,在屏幕上出现新视图时创建滚动动画(以及隐藏视图的动画)

它来自于这种状态:

  • 钮扣
  • 最后一个按钮

  • 钮扣
  • 按钮1
  • 按钮2
  • 按钮3
  • 按钮4
  • 最后一个按钮
维切维萨

因此,当用户单击第一个按钮时,元素“button 1”、“button 2”、“button 3”和“button 4”将使用淡入淡出动画显示,元素“Last button”将向下移动直到结束。布局的高度也将改变,允许正确使用滚动视图

这是用动画显示元素的代码:

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();
}
这是隐藏动画元素的代码:

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上:

快乐编码

更新:对于任何附加到视图的侦听器,应在动画结束后将其删除。这是通过使用

view.animate().setListener(null);

尝试将此行添加到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>

……此处有其他代码

我可以通过以下方式显示/隐藏菜单:

java(扩展框架布局)


制作
可见性更改动画的最简单方法是使用
转换API
,该API可在support(androidx)软件包中获得。只需调用
TransitionManager.beginDelayedTransition
方法,然后更改视图的可见性。有几个默认的转换,如
淡入淡出
幻灯片

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
。结果:

下面是幻灯片
转换的结果:

import androidx.transition.Slide;

Transition transition = new Slide(Gravity.BOTTOM);

如果您需要一些不同的东西,那么编写自定义转换很容易。下面是我在中编写的
CircularRevealTransition
示例。它显示和隐藏带有圆形凹面动画的视图

Transition transition = new CircularRevealTransition();


android:animateLayoutChanges=“true”
选项做同样的事情,它只是用作转换

找到下面的代码,使视图在Circuler reveal中可见,如果发送true,它将不可见/消失。如果发送false,它将可见。anyView是要显示/隐藏的视图,它可以是任何视图(布局、按钮等)


基于@ashakirov answer,这里是我对使用淡入动画显示/隐藏视图的扩展

fun View.fadeVisibility(visibility: Int, duration: Long = 400) {
    val transition: Transition = Fade()
    transition.duration = duration
    transition.addTarget(this)
    TransitionManager.beginDelayedTransition(this.parent as ViewGroup, transition)
    this.visibility = visibility
}
示例使用

view.fadeVisibility(View.VISIBLE)
view.fadeVisibility(View.GONE, 2000)
我的解决方案扩展

fun View.slideVisibility(visibility: Boolean, durationTime: Long = 300) {
    val transition = Slide(Gravity.BOTTOM)
    transition.apply {
        duration = durationTime
        addTarget(this@slideVisibility)
    }
    TransitionManager.beginDelayedTransition(this.parent as ViewGroup, transition)
    this.isVisible = visibility
    }
使用:


@纳提克斯,我不认为那个超级电话是多余的。不要做肤浅的编辑,没有什么错。是好的,但反向不正确为什么?view.setVisibility(view.VISIBLE);使用alpha(1.0f),在顶部填充100…必须在设置可见性之前清除动画>>
view.clearAnimation()
view.setVisibility(view.GONE)否则布局将保持不可见且不会消失。@Eftekhari它们根本不是资源密集型的。如果你有一个最新的安卓版本,但仍然比你可能有一个低内存或坏的图形芯片旧手机滞后。我说的不是一个新的图书馆。动画师是本地人。它们是Android框架的一部分。它们已经在5年前发布,现在97.9%的设备支持它们。没有理由不使用动画师或至少
ViewCompat.ani
fun View.slideVisibility(visibility: Boolean, durationTime: Long = 300) {
    val transition = Slide(Gravity.BOTTOM)
    transition.apply {
        duration = durationTime
        addTarget(this@slideVisibility)
    }
    TransitionManager.beginDelayedTransition(this.parent as ViewGroup, transition)
    this.isVisible = visibility
    }
textView.slideVisibility(true)