假设我有一个垂直的线性布局:

[v1]
[v2]

默认情况下,v1已visibily=消失.我想用一个展开动画来展示v1,同时按下v2.

我试过这样的方法:

Animation a = new Animation()
{
    int initialHeight;

    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        final int newHeight = (int)(initialHeight * interpolatedTime);
        v.getLayoutParams().height = newHeight;
        v.requestLayout();
    }

    @Override
    public void initialize(int width, int height, int parentWidth, int parentHeight) {
        super.initialize(width, height, parentWidth, parentHeight);
        initialHeight = height;
    }

    @Override
    public boolean willChangeBounds() {
        return true;
    }
};

但有了这个解决方案,动画开始时我会 blink .我认为这是由于v1在应用动画之前显示完整大小造成的.

使用javascript,这是jQuery的一行!安卓有什么简单的方法可以做到这一点吗?

推荐答案

我看到这个问题变得流行起来,所以我贴出了我的实际解决方案.其主要优点是,您不必知道展开的高度即可应用动画,并且一旦展开视图,它就会在内容更改时调整高度.它对我很管用.

public static void expand(final View v) {
    int matchParentMeasureSpec = View.MeasureSpec.makeMeasureSpec(((View) v.getParent()).getWidth(), View.MeasureSpec.EXACTLY);
    int wrapContentMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
    v.measure(matchParentMeasureSpec, wrapContentMeasureSpec);
    final int targetHeight = v.getMeasuredHeight();

    // Older versions of android (pre API 21) cancel animations for views with a height of 0.
    v.getLayoutParams().height = 1;
    v.setVisibility(View.VISIBLE);
    Animation a = new Animation()
    {
        @Override
        protected void applyTransformation(float interpolatedTime, Transformation t) {
            v.getLayoutParams().height = interpolatedTime == 1
                    ? LayoutParams.WRAP_CONTENT
                    : (int)(targetHeight * interpolatedTime);
            v.requestLayout();
        }

        @Override
        public boolean willChangeBounds() {
            return true;
        }
    };

    // Expansion speed of 1dp/ms
    a.setDuration((int)(targetHeight / v.getContext().getResources().getDisplayMetrics().density));
    v.startAnimation(a);
}

public static void collapse(final View v) {
    final int initialHeight = v.getMeasuredHeight();

    Animation a = new Animation()
    {
        @Override
        protected void applyTransformation(float interpolatedTime, Transformation t) {
            if(interpolatedTime == 1){
                v.setVisibility(View.GONE);
            }else{
                v.getLayoutParams().height = initialHeight - (int)(initialHeight * interpolatedTime);
                v.requestLayout();
            }
        }

        @Override
        public boolean willChangeBounds() {
            return true;
        }
    };

    // Collapse speed of 1dp/ms
    a.setDuration((int)(initialHeight / v.getContext().getResources().getDisplayMetrics().density));
    v.startAnimation(a);
}

正如@Jefferson在 comments 中提到的,通过更改动画的持续时间(以及速度),可以获得更平滑的动画.目前,其速度设定为1dp/ms

Android相关问答推荐

使用StateFlow从房间到UiState的流程列表

如何将Hilt添加到Android Studio中的Kotlin项目中?

如何在Android Emulator上从物理设备接收TCP消息

RemoteActivityHelper.startRemoteActivity不适用于Android Wear OS 4模拟器

从单元测试访问RES/RAW文件

我想使用代码自动重命名我的Android存储中的文件夹

为什么它显示我的空白屏幕?

如何防止在Android Studio中设置kotlin断点时优化变量

android回收器查看点击事件无响应

在段的中心绘制饼图(甜甜圈图)的图例

如何在 React Native 中调试网络响应

Jetpack Compose 动画的行为是什么?

如何使用 Jetpack Compose 制作两个圆圈

在compose中,为什么修改List元素的属性,LazyColumn不刷新

Jetpack Compose 重组竞争条件

我的 react native 项目的发布签名 apk 没有在设备中打开,而且它创建的尺寸非常小

如何从 Jetpack Compose 中的 Radio 组中获取价值

如何在 kotlin 的 android room DB 中设置一对多关系

为什么我不能在屏幕外拿任何物体

如何使在库范围之外无法访问的接口的具体实现.?