1. ホーム
  2. android

[解決済み] アンドロイド アニメーションの拡大・縮小

2022-03-20 19:27:33

質問

例えば、縦長の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では、これはjQueryの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の速度に設定されています。