Android: 展開/折りたたみアニメーション 質問する

Android: 展開/折りたたみアニメーション 質問する

次のような垂直の linearLayout があるとします。

[v1]
[v2]

デフォルトでは、v1 の visibily = GONE になっています。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;
    }
};

しかし、この解決策では、アニメーションの開始時に点滅が発生します。これは、アニメーションが適用される前に v1 がフルサイズで表示されることが原因だと思います。

JavaScript では、これは 1 行の jQuery です。Android でこれを行う簡単な方法はありますか?

ベストアンサー1

この質問が人気を集めているのがわかったので、実際の解決策を投稿します。主な利点は、アニメーションを適用するために拡張された高さを知る必要がなく、ビューが拡張されると、コンテンツが変更されると高さが調整されることです。私にとってはうまく機能します。

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 がコメントで述べたように、アニメーションの持続時間 (つまり速度) を変更することで、よりスムーズなアニメーションを実現できます。現在は 1dp/ms の速度に設定されています。

おすすめ記事