ホームページ >ウェブフロントエンド >htmlチュートリアル >Fabとダイアログ間のトランジション効果(Fabとダイアログのモーフィングアニメーション)_html/css_WEB-ITnose

Fabとダイアログ間のトランジション効果(Fabとダイアログのモーフィングアニメーション)_html/css_WEB-ITnose

WBOY
WBOYオリジナル
2016-06-21 08:59:111342ブラウズ

最近Plaidのソースコードを読んでいて、ファブとダイアログを切り替える際のアニメーション効果が非常に快適だったので、それを研究してPlaidプロジェクトから抽出し、いくつかのコードを追加した後、さらに便利になり、理解しやすく、使いやすくなりました。効果は以下の通りです。 プロジェクトのソースコードアドレス

実装原理分析

1. 前回の「Android Heroes」の読書メモでは、アクティビティ共有要素の遷移アニメーションを行いました。実装方法

共有要素遷移アニメーション: 共有要素遷移アニメーションは、
changeBounds: ターゲット ビューのレイアウト境界の変更
changeClipBounds を含む、2 つのアクティビティ間の遷移がビューを共有する方法を決定します。 : ターゲット ビューの境界をトリミングします。
changeTransform: ターゲット ビューのスケーリングと回転角度を変更します。
changeImageTransform: ターゲット イメージのサイズとスケーリングを変更します。
使用法: アクティビティが A から B にジャンプすると仮定し、A の元の startActivity を次のコードに変更します:

//单个共享元素的调用方式startActivity(intent,ActivityOptions.makeSceneTransitionAnimation(this, view, "share").toBundle());//多个共享元素的调用方式startActivity(intent,ActivityOptions.makeSceneTransitionAnimation(this,                Pair.create(view, "share"),                Pair.create(fab, "fab")).toBundle());

次に、それを onCreate メソッドに追加します。 B 次のコード:

//声明需要开启Activity过渡动画getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);

次に、アクティビティ A と B のレイアウト ファイルの共有要素コンポーネントに android:transitionName="xxx" 属性を追加します。

2. ソース コード内のダイアログは実際にはアクティビティであり、android:windowIsTranslucent が true に設定されているため、ファブからダイアログへのアニメーション効果は実際にはアクティビティの遷移アニメーションになります。ただし、単純にActivityの共有要素遷移アニメーションを利用し、共有要素としてfabを使用すると効果が悪く、あまり快適ではありません。

3. トランジション効果をより快適にするために、ここでは 2 つのグラデーション効果を追加します。1 つはカラーであり、ファブの色からダイアログの背景色へのグラデーションです。これは丸い角の勾配です。次のコード実装を参照してください。

/** * MorphTransition扩展自ChangeBounds(共享元素的动画的一种),它在原有动画基础上添加了color和cornerRadius的动画效果,这个类实际上是整合了MorphFabToDialog和MorphDialogToFab两个类的作用 * <p/> * A transition that morphs a circle into a rectangle, changing it's background color. */public class MorphTransition extends ChangeBounds {    private static final String PROPERTY_COLOR = "color";    private static final String PROPERTY_CORNER_RADIUS = "cornerRadius";    private static final String[] TRANSITION_PROPERTIES = {            PROPERTY_COLOR,            PROPERTY_CORNER_RADIUS    };    private int startColor = Color.TRANSPARENT;    private int endColor = Color.TRANSPARENT;    private int startCornerRadius = 0;    private int endCornerRadius = 0;    private boolean isShowViewGroup = false;    public MorphTransition(int startColor, int endColor, int startCornerRadius, int endCornerRadius, boolean isShowViewGroup) {        super();        setStartColor(startColor);        setEndColor(endColor);        setStartCornerRadius(startCornerRadius);        setEndCornerRadius(endCornerRadius);        setIsShowViewGroup(isShowViewGroup);    }    public MorphTransition(Context context, AttributeSet attrs) {        super(context, attrs);    }    @Override    public String[] getTransitionProperties() {        return TRANSITION_PROPERTIES;    }    @Override    public void captureStartValues(TransitionValues transitionValues) {        super.captureStartValues(transitionValues);        final View view = transitionValues.view;        if (view.getWidth() <= 0 || view.getHeight() <= 0) {            return;        }        transitionValues.values.put(PROPERTY_COLOR, startColor);        transitionValues.values.put(PROPERTY_CORNER_RADIUS, startCornerRadius);//view.getHeight() / 2    }    @Override    public void captureEndValues(TransitionValues transitionValues) {        super.captureEndValues(transitionValues);        final View view = transitionValues.view;        if (view.getWidth() <= 0 || view.getHeight() <= 0) {            return;        }        transitionValues.values.put(PROPERTY_COLOR, endColor);//ContextCompat.getColor(view.getContext(), R.color.dialog_background_color)        transitionValues.values.put(PROPERTY_CORNER_RADIUS, endCornerRadius);    }    @Override    public Animator createAnimator(final ViewGroup sceneRoot, TransitionValues startValues, final TransitionValues endValues) {        Animator changeBounds = super.createAnimator(sceneRoot, startValues, endValues);        if (startValues == null || endValues == null || changeBounds == null) {            return null;        }        Integer startColor = (Integer) startValues.values.get(PROPERTY_COLOR);        Integer startCornerRadius = (Integer) startValues.values.get(PROPERTY_CORNER_RADIUS);        Integer endColor = (Integer) endValues.values.get(PROPERTY_COLOR);        Integer endCornerRadius = (Integer) endValues.values.get(PROPERTY_CORNER_RADIUS);        if (startColor == null || startCornerRadius == null || endColor == null || endCornerRadius == null) {            return null;        }        MorphDrawable background = new MorphDrawable(startColor, startCornerRadius);        endValues.view.setBackground(background);        Animator color = ObjectAnimator.ofArgb(background, background.COLOR, endColor);        Animator corners = ObjectAnimator.ofFloat(background, background.CORNER_RADIUS, endCornerRadius);        ////......        AnimatorSet transition = new AnimatorSet();        transition.playTogether(changeBounds, corners, color);        transition.setDuration(300);        transition.setInterpolator(AnimationUtils.loadInterpolator(sceneRoot.getContext(), android.R.interpolator.fast_out_slow_in));        return transition;    }    public void setEndColor(int endColor) {        this.endColor = endColor;    }    public void setEndCornerRadius(int endCornerRadius) {        this.endCornerRadius = endCornerRadius;    }    public void setStartColor(int startColor) {        this.startColor = startColor;    }    public void setStartCornerRadius(int startCornerRadius) {        this.startCornerRadius = startCornerRadius;    }    public void setIsShowViewGroup(boolean isShowViewGroup) {        this.isShowViewGroup = isShowViewGroup;    }}

4. 上記のコードでは MorphDrawable クラスが使用されており、Drawable を継承し、前述の 2 つの属性を追加して、デフォルトで属性アニメーションを生成します。これら 2 つのプロパティにはメソッドが追加されていないため、拡張する必要があります。属性アニメーションについては、以前の読み取りメモを参照してください。 重要なコードは次のとおりです。

/** * 形态和颜色可以发生变化的Drawable,形态变化是通过cornerRadius来实现的,颜色变化是通过paint的color来实现的 * 该类在Drawable的基础上添加了cornerRadius和color两个属性,前者是float类型,后者是int类型 * <p/> * A drawable that can morph size, shape (via it's corner radius) and color.  Specifically this is * useful for animating between a FAB and a dialog. */public class MorphDrawable extends Drawable {    private Paint paint;    private float cornerRadius;    public static final Property<MorphDrawable, Float> CORNER_RADIUS = new Property<MorphDrawable, Float>(Float.class, "cornerRadius") {        @Override        public void set(MorphDrawable morphDrawable, Float value) {            morphDrawable.setCornerRadius(value);        }        @Override        public Float get(MorphDrawable morphDrawable) {            return morphDrawable.getCornerRadius();        }    };    public static final Property<MorphDrawable, Integer> COLOR = new Property<MorphDrawable, Integer>(Integer.class, "color") {        @Override        public void set(MorphDrawable morphDrawable, Integer value) {            morphDrawable.setColor(value);        }        @Override        public Integer get(MorphDrawable morphDrawable) {            return morphDrawable.getColor();        }    };    public MorphDrawable(@ColorInt int color, float cornerRadius) {        this.cornerRadius = cornerRadius;        paint = new Paint(Paint.ANTI_ALIAS_FLAG);        paint.setColor(color);    }    public float getCornerRadius() {        return cornerRadius;    }    public void setCornerRadius(float cornerRadius) {        this.cornerRadius = cornerRadius;        invalidateSelf();    }    public int getColor() {        return paint.getColor();    }    public void setColor(int color) {        paint.setColor(color);        invalidateSelf();    }    @Override    public void draw(Canvas canvas) {        canvas.drawRoundRect(getBounds().left, getBounds().top, getBounds().right, getBounds()                .bottom, cornerRadius, cornerRadius, paint);//hujiawei    }    @Override    public void getOutline(Outline outline) {        outline.setRoundRect(getBounds(), cornerRadius);    }    @Override    public void setAlpha(int alpha) {        paint.setAlpha(alpha);        invalidateSelf();    }    @Override    public void setColorFilter(ColorFilter cf) {        paint.setColorFilter(cf);        invalidateSelf();    }    @Override    public int getOpacity() {        return paint.getAlpha();    }}

5. 前の準備が完了したら、ダイアログで開始アニメーション効果と終了アニメーション効果を設定できます。

//DialogActivity.javapublic void setupSharedEelementTransitions2() {    ArcMotion arcMotion = new ArcMotion();    arcMotion.setMinimumHorizontalAngle(50f);    arcMotion.setMinimumVerticalAngle(50f);    Interpolator easeInOut = AnimationUtils.loadInterpolator(this, android.R.interpolator.fast_out_slow_in);    //hujiawei 100是随意给的一个数字,可以修改,需要注意的是这里调用container.getHeight()结果为0    MorphTransition sharedEnter = new MorphTransition(ContextCompat.getColor(this, R.color.fab_background_color),            ContextCompat.getColor(this, R.color.dialog_background_color), 100, getResources().getDimensionPixelSize(R.dimen.dialog_corners), true);    sharedEnter.setPathMotion(arcMotion);    sharedEnter.setInterpolator(easeInOut);    MorphTransition sharedReturn = new MorphTransition(ContextCompat.getColor(this, R.color.dialog_background_color),            ContextCompat.getColor(this, R.color.fab_background_color), getResources().getDimensionPixelSize(R.dimen.dialog_corners), 100,  false);    sharedReturn.setPathMotion(arcMotion);    sharedReturn.setInterpolator(easeInOut);    if (container != null) {        sharedEnter.addTarget(container);        sharedReturn.addTarget(container);    }    getWindow().setSharedElementEnterTransition(sharedEnter);    getWindow().setSharedElementReturnTransition(sharedReturn);}

6. 上記の分析からわかるように、このタイプのアニメーションである限り、このソリューションは比較的簡単に拡張できます。開始時と終了時の対応するカラーとフィレットの値を、アクティビティの開始または劣化アニメーションに設定します。

上記は私の分析と理解です。ご質問があれば、お気軽にアドバイスをお願いします。(^ω^)�

原文: Fab and Dialog Morphing Anime

出典: http://www.jcodecraeer.com//a/anzhuokaifa/2015/1215/3776.html

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。