Fabとダイアログ間のトランジション効果(Fabとダイアログのモーフィングアニメーション)_html/css_WEB-ITnose
最近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

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック











公式アカウントのWebページはキャッシュを更新します。これはシンプルでシンプルで、ポットを飲むのに十分な複雑です。あなたは公式のアカウントの記事を更新するために一生懸命働きましたが、ユーザーはまだ古いバージョンを開くことができますか?この記事では、この背後にあるtwist余曲折と、この問題を優雅に解決する方法を見てみましょう。それを読んだ後、さまざまなキャッシュの問題に簡単に対処でき、ユーザーが常に新鮮なコンテンツを体験できるようになります。最初に基本について話しましょう。それを率直に言うと、アクセス速度を向上させるために、ブラウザまたはサーバーはいくつかの静的リソース(写真、CSS、JSなど)やページコンテンツを保存します。次回アクセスするときは、もう一度ダウンロードすることなく、キャッシュから直接検索できます。自然に高速です。しかし、このことは両刃の剣でもあります。新しいバージョンはオンラインです、

この記事では、ブラウザのユーザー入力を直接検証するために、必要、パターン、MIN、MAX、および長さの制限などのHTML5フォーム検証属性を使用して説明します。

記事では、HTML5クロスブラウザーの互換性を確保するためのベストプラクティスについて説明し、機能検出、プログレッシブエンハンスメント、およびテスト方法に焦点を当てています。

この記事では、CSSを使用したWebページへの効率的なPNG境界追加を示しています。 CSSはJavaScriptやライブラリと比較して優れたパフォーマンスを提供し、微妙または顕著な効果のために境界幅、スタイル、色を調整する方法を詳述していると主張しています

この記事では、HTML&lt; Datalist&GT;について説明します。オートコンプリートの提案を提供し、ユーザーエクスペリエンスの改善、エラーの削減によりフォームを強化する要素。

この記事では、html&lt; meter&gt;について説明します。要素は、範囲内でスカラーまたは分数値を表示するために使用され、Web開発におけるその一般的なアプリケーション。それは差別化&lt; Meter&gt; &lt; Progress&gt;およびex

この記事では、html5&lt; time&gt;について説明します。セマンティックデート/時刻表現の要素。 人間の読み取り可能なテキストとともに、マシンの読みやすさ(ISO 8601形式)のDateTime属性の重要性を強調し、Accessibilitを増やします

この記事では、HTML&lt; Progress&gt;について説明します。要素、その目的、スタイリング、および&lt; meter&gt;との違い要素。主な焦点は、&lt; Progress&gt;を使用することです。タスクの完了と&lt; Meter&gt; statiの場合
