記事ディレクトリ
描画プロセスを見る
描画の前に、システムは PhoneWindow、DecorView、ViewRootImpl を作成するための描画の準備を行います。この処理はアクティビティの onCreate() 内にあります。
Viewの描画処理はViewRootImplオブジェクトのperformTraversals()から始まります。
/**
* 源码分析:ViewRootImpl.performTraversals()
*/
private void performTraversals() {
// 1. 执行measure流程
// 内部会调用performMeasure()
measureHierarchy(host, lp, res,desiredWindowWidth, desiredWindowHeight);
// 2. 执行layout流程
performLayout(lp, mWidth, mHeight);
// 3. 执行draw流程
performDraw();
}
ビューの描画プロセスは、トップレベルのビュー (DecorView) の ViewGroup から開始され、ViewGroup からサブ View までのマッピングをレイヤごとにたどります (測定、レイアウト、描画)。
-
ルートビューから開始して深さ優先検索が各サブビューを横断して測定を実行します
-
ルート ビューから開始して深さ優先検索が各子ビューを横断してレイアウトを実行します。
-
ルート ビューから開始して、深さ優先検索が各子ビューを横断して描画を実行します。
測定
測定の機能は、ビューの幅/高さを測定することです。
場合によっては、ビューのサイズが動的コンテンツ、レスポンシブ デザイン、レイアウトの制約、またはアニメーション効果の影響を受ける場合、最終的な幅または高さを決定するために複数の測定が必要になることがあります。そのため、測定プロセスで取得された幅/高さは正確ではない可能性があります。建议在layout过程中的onLayout去获取最终的宽 / 高。
単一ビューの測定プロセス:
- measure(): 基本的な測定ロジックの判定
- onMeasure(): 2 つのステップに分かれています
- getDefaultSize(): ビューの幅/高さの測定仕様に従って、ビューの幅と高さを計算します。
- setMeasure(): 測定されたサブビューの幅/高さを保存します
ViewGroup の測定プロセス:
注意:ViewGroup的measure过程中,等待所有的子view都measure完毕,合并所有子view的尺寸才可以得到ViewGroup父视图的测量值。
レイアウト
レイアウト プロセスの機能は、ビューの位置、つまり
ビューの 4 つの頂点位置 (左、上、右、下) を計算することです。
描く
Draw プロセスの機能は View ビューを描画することであり、
単一の View はそれ自体 (背景、コンテンツを含む) と装飾を描画するだけで済みます。
注: ここでの装飾とは、インジケーター、スクロールバー、および前景を指します。
ViewGroup の描画には次のものが含まれます。
- 自分で描いたもの(背景と内容あり)
- サブビューを走査し、1 つずつ描画します (背景、コンテンツ、装飾)
- ViewGroupの描画装飾
カスタム ビューを実装する手順
ステップ 1: 測定、レイアウト、描画プロセスを実装する
- View ワークフロー (計測処理、レイアウト処理、描画処理) からカスタム View を実装する場合、カスタム View の種類 (単一ビュー / ViewGroup) に応じて、異なるメソッドをカスタマイズして実装する必要があります。
- 主に、次のような onMeasure()、onLayout()、onDraw() です。
カスタムメジャー
ViewGroup.LayoutParams
ViewGroup のサブクラス (RelativeLayout、LinearLayout) には、対応する ViewGroup.LayoutParams サブクラスがあります。
その役割は、ビューの高さや幅などのレイアウト パラメーターを指定することです。具体的には、対応する XML ファイル内の
次のパラメータによって指定されます。
android:layout_height="wrap_content" //自适应大小
android:layout_height="match_parent" //与父视图等高
android:layout_height="fill_parent" //与父视图等高
android:layout_height="100dip" //精确设置高度值为 100dip
スペックの測定
MeasureSpec: 測定モード(mode)と測定サイズ(size)の合計32ビット(int型)で構成され、モードが2ビット、サイズが下位30ビットを占めるポリシールール。
3 つの測定モードがあります。
- UNSPECIFIED: 親ビューは、ListView、ScrollView などの子ビューを制約しませんが、通常、カスタム ビューではこれを必要としません。
- 正確: 親ビューは子ビューの正確なサイズを指定しており、子ビューのサイズはこのサイズでなければなりません。たとえば、match_parent、または 100dp という特定の値を指定すると、このモードでは、ビューの測定プロセスはビューのレイアウト パラメータを無視します (
LayoutParams
) - AT_MOST: 親ビューは子ビューの最大サイズを指定し、子ビューはそれ自体とすべての子ビューがこのサイズ内に収まることを確認する必要があります。たとえば、wrap_content、適応サイズ、特定のサイズは要件に応じて設定されます。このモードでは、親コントロールは子ビューのサイズを決定できず、子コントロール自体のニーズに従ってサイズを設計および計算することしかできません。
MeasureSpec の具体的な使用法:
MeasureSpec クラスは、測定モード (mode) と測定サイズ (size) を変数でカプセル化します。バイナリを使用することで、測定モード (mode) と測定サイズ (size) は int 値にパッケージ化されます。パッケージ化とアンパックの方法が提供されます。このアプローチは、オブジェクトのメモリ割り当てを削減し、アクセス効率を向上させることです。具体的な使い方は以下の通りです。
// 1. 获取测量模式(Mode)
int specMode = MeasureSpec.getMode(measureSpec)
// 2. 获取测量大小(Size)
int specSize = MeasureSpec.getSize(measureSpec)
// 3. 通过Mode 和 Size 生成新的SpecMode
int measureSpec=MeasureSpec.makeMeasureSpec(size, mode);
カスタムレイアウト
レイアウトの役割は、ビューの 4 つの頂点位置 (左、上、右、下) を計算することです。
カスタム属性
- カスタム属性 XML ファイルをvaluesディレクトリに作成します。
- カスタム XML ファイルをロードし、カスタム ビューのコンストラクターでプロパティ値を解析します
- レイアウト ファイルでのカスタム属性の使用
描画ツール
ペイント
ペイント: ブラシ。その機能は、描画されたコンテンツの特定の効果 (色、サイズなど) を決定することであり、ブラシはコンテンツを描画するときに必要になります。
具体的な用途
ステップ:
- ペイントオブジェクトを作成する
- ブラシ、つまり色やサイズなどのコンテンツを描画するときの効果を設定します
- ブラシを初期化します (ビューでコンストラクターを選択してみてください)
パス
キャンバス
キャンバス:キャンバスは描画する際のルールであり、描画内容はキャンバスの規定に従って画面上に描画されます。