我有一个线性布局,我想显示或隐藏与动画,推动布局向上或向下每当我改变其可见性。

我在那里看过一些样品,但没有一个适合我的需要。

我已经为动画创建了两个xml文件,但我不知道当我改变线性布局的可见性时如何启动它们。


当前回答

通过Kotlin扩展,你可以这样使用:

enum class SlideDirection{
    UP,
    DOWN,
    LEFT,
    RIGHT
}

enum class SlideType{
    SHOW,
    HIDE
}

fun View.slideAnimation(direction: SlideDirection, type: SlideType, duration: Long = 250){
    val fromX: Float
    val toX: Float
    val fromY: Float
    val toY: Float
    val array = IntArray(2)
    getLocationInWindow(array)
    if((type == SlideType.HIDE && (direction == SlideDirection.RIGHT || direction == SlideDirection.DOWN)) ||
        (type == SlideType.SHOW && (direction == SlideDirection.LEFT || direction == SlideDirection.UP))   ){
        val displayMetrics = DisplayMetrics()
        val windowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
        windowManager.defaultDisplay.getMetrics(displayMetrics)
        val deviceWidth = displayMetrics.widthPixels
        val deviceHeight = displayMetrics.heightPixels
        array[0] = deviceWidth
        array[1] = deviceHeight
    }
    when (direction) {
        SlideDirection.UP -> {
            fromX = 0f
            toX = 0f
            fromY = if(type == SlideType.HIDE) 0f else (array[1] + height).toFloat()
            toY = if(type == SlideType.HIDE) -1f * (array[1] + height)  else 0f
        }
        SlideDirection.DOWN -> {
            fromX = 0f
            toX = 0f
            fromY = if(type == SlideType.HIDE) 0f else -1f * (array[1] + height)
            toY = if(type == SlideType.HIDE) 1f * (array[1] + height)  else 0f
        }
        SlideDirection.LEFT -> {
            fromX = if(type == SlideType.HIDE) 0f else 1f * (array[0] + width)
            toX = if(type == SlideType.HIDE) -1f * (array[0] + width) else 0f
            fromY = 0f
            toY = 0f
        }
        SlideDirection.RIGHT -> {
            fromX = if(type == SlideType.HIDE) 0f else -1f * (array[0] + width)
            toX = if(type == SlideType.HIDE) 1f * (array[0] + width) else 0f
            fromY = 0f
            toY = 0f
        }
    }
    val animate = TranslateAnimation(
        fromX,
        toX,
        fromY,
        toY
    )
    animate.duration = duration
    animate.setAnimationListener(object: Animation.AnimationListener{
        override fun onAnimationRepeat(animation: Animation?) {

        }

        override fun onAnimationEnd(animation: Animation?) {
            if(type == SlideType.HIDE){
                visibility = View.INVISIBLE
            }
        }

        override fun onAnimationStart(animation: Animation?) {
            visibility = View.VISIBLE
        }

    })
    startAnimation(animate)
}

扩展示例:

view.slideAnimation(SlideDirection.UP, SlideType.HIDE)//to make it disappear through top of the screen
view.slideAnimation(SlideDirection.DOWN, SlideType.SHOW)//to make it reappear from top of the screen

view.slideAnimation(SlideDirection.DOWN, SlideType.HIDE)//to make it disappear through bottom of the screen
view.slideAnimation(SlideDirection.UP, SlideType.SHOW)//to make it reappear from bottom of the screen

其他回答

你可以使用简单的三行代码来显示动画…

//getting the hiding view by animation

 mbinding.butn.setOnClickListener {

                val SlideOutLeft = AnimationUtils.loadAnimation(this, R.anim.slide_out_left)
                simplelayout.visibility = View.INVISIBLE
                simplelayout.startAnimation(SlideOutLeft)


                val SlideInRight = AnimationUtils.loadAnimation(applicationContext, R.anim.slide_in_right)
                animation1.visibility = View.VISIBLE
                animation1.startAnimation(SlideInRight)

            }
            //again unhide the view animation
            mbinding.buttn.setOnClickListener {


               val SlideInLeft=AnimationUtils.loadAnimation(this,R.anim.slide_in_left)
                //set the layout
               simplelayout.visibility=View.VISIBLE
               simplelayout.startAnimation(SlideInLeft)

               val SlideOutRight=AnimationUtils.loadAnimation(this,R.anim.slide_out_right)
               animation1.visibility=View.INVISIBLE
               animation1.startAnimation(SlideOutRight)

            }

现在可见性改变动画应该通过过渡API来完成,该API在支持(androidx)包中可用。只需调用TransitionManager。beginDelayedTransition方法使用Slide过渡,然后改变视图的可见性。

import androidx.transition.Slide;
import androidx.transition.Transition;
import androidx.transition.TransitionManager;

private void toggle(boolean show) {
    View redLayout = findViewById(R.id.redLayout);
    ViewGroup parent = findViewById(R.id.parent);

    Transition transition = new Slide(Gravity.BOTTOM);
    transition.setDuration(600);
    transition.addTarget(R.id.redLayout);

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

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/parent"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:id="@+id/btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="play" />

    <LinearLayout
        android:id="@+id/redLayout"
        android:layout_width="match_parent"
        android:layout_height="400dp"
        android:background="#5f00"
        android:layout_alignParentBottom="true" />
</RelativeLayout>

用另一个默认和自定义转换示例检查这个答案。

使用这个类:

public class ExpandCollapseExtention {

 public static void expand(View view) {
    view.setVisibility(View.VISIBLE);

    final int widthSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
    final int heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
    view.measure(widthSpec, heightSpec);

    ValueAnimator mAnimator = slideAnimator(view, 0, view.getMeasuredHeight());
    mAnimator.start();
}


public static void collapse(final View view) {
    int finalHeight = view.getHeight();

    ValueAnimator mAnimator = slideAnimator(view, finalHeight, 0);

    mAnimator.addListener(new Animator.AnimatorListener() {

        @Override
        public void onAnimationEnd(Animator animator) {               
            view.setVisibility(View.GONE);
        }


        @Override
        public void onAnimationStart(Animator animation) {

        }


        @Override
        public void onAnimationCancel(Animator animation) {

        }


        @Override
        public void onAnimationRepeat(Animator animation) {

        }
    });
    mAnimator.start();
}


private static ValueAnimator slideAnimator(final View v, int start, int end) {

    ValueAnimator animator = ValueAnimator.ofInt(start, end);

    animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

        @Override
        public void onAnimationUpdate(ValueAnimator valueAnimator) {

            int value = (Integer) valueAnimator.getAnimatedValue();
            ViewGroup.LayoutParams layoutParams = v.getLayoutParams();
            layoutParams.height = value;
            v.setLayoutParams(layoutParams);
        }
    });
    return animator;
}
}

这里有另一种方法来处理多个按钮(在这个例子中是ImageView)

MainActivity.java

findViewById(R.id.arrowIV).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                if (strokeWidthIV.getAlpha() == 0f) {
                    findViewById(R.id.arrowIV).animate().rotationBy(180);

                    strokeWidthIV.animate().translationXBy(-120 * 4).alpha(1f);
                    findViewById(R.id.colorChooseIV).animate().translationXBy(-120 * 3).alpha(1f);
                    findViewById(R.id.saveIV).animate().translationXBy(-120 * 2).alpha(1f);
                    findViewById(R.id.clearAllIV).animate().translationXBy(-120).alpha(1f);
                } else {
                    findViewById(R.id.arrowIV).animate().rotationBy(180);

                    strokeWidthIV.animate().translationXBy(120 * 4).alpha(0f);
                    findViewById(R.id.colorChooseIV).animate().translationXBy(120 * 3).alpha(0f);
                    findViewById(R.id.saveIV).animate().translationXBy(120 * 2).alpha(0f);
                    findViewById(R.id.clearAllIV).animate().translationXBy(120).alpha(0f);
                }
            }
        });

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:app="http://schemas.android.com/apk/res-auto"
 xmlns:tools="http://schemas.android.com/tools"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 tools:context=".activity.MainActivity">

 <ImageView
     android:id="@+id/strokeWidthIV"
     android:layout_width="48dp"
     android:layout_height="48dp"
     android:layout_margin="8dp"
     android:alpha="0"
     android:contentDescription="Clear All"
     android:padding="4dp"
     android:scaleType="fitXY"
     android:src="@drawable/ic_edit"
     app:layout_constraintEnd_toEndOf="parent"
     app:layout_constraintTop_toTopOf="parent"
     tools:ignore="HardcodedText" />

 <ImageView
     android:id="@+id/colorChooseIV"
     android:layout_width="48dp"
     android:layout_height="48dp"
     android:layout_margin="8dp"
     android:alpha="0"
     android:contentDescription="Clear All"
     android:padding="4dp"
     android:scaleType="fitXY"
     android:src="@drawable/ic_palette"
     app:layout_constraintEnd_toEndOf="parent"
     app:layout_constraintTop_toTopOf="parent"
     tools:ignore="HardcodedText" />

 <ImageView
     android:id="@+id/saveIV"
     android:layout_width="48dp"
     android:layout_height="48dp"
     android:layout_margin="8dp"
     android:alpha="0"
     android:contentDescription="Clear All"
     android:padding="4dp"
     android:scaleType="fitXY"
     android:src="@drawable/ic_save"
     app:layout_constraintEnd_toEndOf="parent"
     app:layout_constraintTop_toTopOf="parent"
     tools:ignore="HardcodedText" />

 <ImageView
     android:id="@+id/clearAllIV"
     android:layout_width="48dp"
     android:layout_height="48dp"
     android:layout_margin="8dp"
     android:alpha="0"
     android:contentDescription="Clear All"
     android:padding="4dp"
     android:scaleType="fitXY"
     android:src="@drawable/ic_clear_all"
     app:layout_constraintEnd_toEndOf="parent"
     app:layout_constraintTop_toTopOf="parent"
     tools:ignore="HardcodedText" />

 <ImageView
     android:id="@+id/arrowIV"
     android:layout_width="48dp"
     android:layout_height="48dp"
     android:layout_margin="8dp"
     android:contentDescription="Arrow"
     android:padding="4dp"
     android:scaleType="fitXY"
     android:src="@drawable/ic_arrow"
     app:layout_constraintEnd_toEndOf="parent"
     app:layout_constraintTop_toTopOf="parent"
     tools:ignore="HardcodedText" />
</androidx.constraintlayout.widget.ConstraintLayout>

随着Android 3.0 (Honeycomb)引入的新动画API,创建这样的动画非常简单。

将视图向下滑动一段距离:

view.animate().translationY(distance);

你可以稍后将视图滑回原来的位置,如下所示:

view.animate().translationY(0);

您还可以轻松地组合多个动画。下面的动画会将一个视图按高度向下滑动,同时淡入:

// Prepare the View for the animation
view.setVisibility(View.VISIBLE);
view.setAlpha(0.0f);

// Start the animation
view.animate()
    .translationY(view.getHeight())
    .alpha(1.0f)
    .setListener(null);

然后,您可以将视图淡出,并将其滑回原始位置。我们还设置了一个AnimatorListener,这样我们可以在动画完成后将视图的可见性设置为GONE:

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