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

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

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


当前回答

使用这个类:

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

其他回答

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

科特林

根据Suragch的回答,下面是一种使用View扩展的优雅方式:

fun View.slideUp(duration: Int = 500) {
    visibility = View.VISIBLE
    val animate = TranslateAnimation(0f, 0f, this.height.toFloat(), 0f)
    animate.duration = duration.toLong()
    animate.fillAfter = true
    this.startAnimation(animate)
}

fun View.slideDown(duration: Int = 500) {
    visibility = View.VISIBLE
    val animate = TranslateAnimation(0f, 0f, 0f, this.height.toFloat())
    animate.duration = duration.toLong()
    animate.fillAfter = true
    this.startAnimation(animate)
}

然后无论你想在哪里使用它,你只需要myview。slideup()或myview。slidedown ()

从ashakirov的回答为Kotlin用户

 val transition: Transition = Slide(Gravity.BOTTOM)
                transition.duration = 600
                transition.addTarget(you_parent_layout_id)
TransitionManager.beginDelayedTransition(rootLayoutId, transition)
                yourViewIdToHide.visibility = if (yourViewIdToHide.isShown) View.GONE else View.VISIBLE

通过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

使用ObjectAnimator

private fun slideDown(view: View) {
    val height = view.height
    ObjectAnimator.ofFloat(view, View.TRANSLATION_Y, 0f, height.toFloat()).apply {
        duration = 1000
        start()
    }
}

private fun slideUp(view: View) {
    val height = view.height
    ObjectAnimator.ofFloat(view, View.TRANSLATION_Y, height.toFloat(), 0f)).apply {
        duration = 1000
        start()
    }
}