序文
Android のウィンドウは次の 3 種類に分類されます。
アプリケーション ウィンドウ (例Activity
:Dialog
子ウィンドウ) PopupWindow
; システム ウィンドウ (Toast
システム ステータス バー、ナビゲーション バーなど)
アプリケーション ウィンドウの Z オーダーは最も低く、システム内で最も低い表示レベルを持ち、その後サブ ウィンドウに進み、最も高いレベルがシステム ウィンドウになります。より高いレベルのウィンドウは、より低いレベルのウィンドウを上書きします。ウィンドウを重ねて表示するには、そのウィンドウを前のウィンドウよりも高いレベルにするだけです。
3 種類のウィンドウはそれぞれに対応していますWindowToken
。各アプリケーション コンポーネント (アプリケーション コンポーネントはActivity
、など、各コンポーネントは 1 つに対応します) を WMS に適用してウィンドウを追加する必要がありますInputMethod
。WMS ( ) はウィンドウの分類に従って編成されています. 同じウィンドウは密接に関連しています。アプリケーション コンポーネントは、新しいウィンドウを作成するときに、サーフェス ウィンドウ ID タイプを提供する必要があります。システム ウィンドウはそれを暗黙的に宣言し、WMS は同時にそれを認証します。Wallpaper
WindowToken
WindowToken
WindowManagerSerivce
WindowToken
WindowToken
WindowToken
WindowToken
addWindow()
アプリケーションウィンドウの階層
アクティビティ表示
ソースコードから始めましょうActivity
:ソースコード内setContentView()
AppCompatDelegateImpl
mSubDecor
Window ではなく、DecorView
作成DecorView
後に作成された子はDecorView
、 が含まれているかどうかも含めてActionBar
、FloatingActionButton
旧バージョンDecorView
と同等ですTitleBar
。
getWindow()
Activity
は返された変数で、抽象クラスであるオブジェクトmWindow
を指します。ここで返されるのはオブジェクト (のサブクラス) です。にはオブジェクトがあり、実際にはのサブレイアウトであり、最終的に現在のレイアウトに追加されます。ウィンドウのルートビュー。Window
Window
PhoneWindow
PhoneWindow
Window
PhoneWindow
DecorView
DecorView
FrameLayout
setContentView()
DecorView
DecorView
このルートビューは最終的にどのように描画されるのでしょうか?
Window
View
直接のマネージャである抽象ウィンドウの概念を表し、 が1 つに対応しView
、Window
でView
接続されますViewRootImpl
。
Activity
レベルView
は次のとおりです。
アプリケーションウィンドウの階層タイプ
WMS がアプリケーション ウィンドウをオーバーレイすると、アプリケーション ウィンドウのレイヤー値が動的に変更されますが、レイヤー値は 99 を超えることはありません。
public static final int FIRST_APPLICATION_WINDOW = 1;
public static final int TYPE_BASE_APPLICATION = 1;
public static final int TYPE_APPLICATION = 2;
public static final int TYPE_APPLICATION_STARTING = 3;
public static final int TYPE_DRAWN_APPLICATION = 4;
public static final int LAST_APPLICATION_WINDOW = 99;
1.Activity
デフォルトのウィンドウ レベルは ですTYPE_BASE_APPLICATION
。ウィンドウにWindowManager.addView()
追加することで。DecorView
このコードは次の場所にありますActivityThread
。
2.Dialog
デフォルトのレベルは次のとおりですTYPE_APPLICATION
Dialog
:
1. ウィンドウを作成します (方法はアクティビティの作成と同じです);
2.DecorView
ダイアログ ビューを初期化して追加しますDecorView
;
3.DecorView
表示するためにウィンドウに追加します。
階層的な構築方法もあります。ウィンドウ タイプが指定されていない場合、デフォルトは です。したがって、で作成する場合、ウィンドウ タイプが指定されていない場合、デフォルトは です。で作成してポップアップすると、同じコードがエラーを報告します。正常に表示するには、システム ウィンドウ レベルより上に設定する必要があります。TYPE_APPLICATION
ActionMode
Windowmanager
LayoutParams
TYPE_APPLICATION
Dialog
Activity
TYPE_APPLICATION
Service
Dialog
Activity
WindowManager.LayoutParams.TYPE_SYSTEM_ALERT
3.TYPE_APPLICATION_STARTING
起動ウィンドウの Z-Ordered は、アプリケーション内の他のすべてのウィンドウよりも上位にある必要があります。Android 12独自の起動画面StartingWindow
を搭載SplashScreen
。これには、SystemUIWMShell
コンポーネントも含まれます。その中には、SplitScreen 分割画面モード、OneHanded 片手モード、Freeform フリー ウィンドウ モード、バブル通知ウィンドウ (Android Q)、PIP ピクチャ イン ピクチャ モード、およびその他のシステム モード ウィンドウが処理の一部です。WMShell
。
- アプリケーションで
Toast
一時的なポップアップを作成することがよくありますが、Toast
それはアプリケーション ウィンドウではなくシステム ウィンドウであり、レベルは でありTYPE_TOAST
、アプリケーション ウィンドウの範囲内ではありません。以下のシステムウィンドウで紹介されます。
サブウィンドウレベル(サブウィンドウ)
public static final int FIRST_SUB_WINDOW = 1000;
public static final int TYPE_APPLICATION_PANEL = FIRST_SUB_WINDOW;
public static final int TYPE_APPLICATION_MEDIA = FIRST_SUB_WINDOW + 1;
public static final int TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW + 2;
public static final int TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW + 3;
public static final int TYPE_APPLICATION_MEDIA_OVERLAY = FIRST_SUB_WINDOW + 4;
public static final int TYPE_APPLICATION_ABOVE_SUB_PANEL = FIRST_SUB_WINDOW + 5;
public static final int LAST_SUB_WINDOW = 1999;
子ウィンドウのタイプは、アプリケーション ウィンドウにアタッチされたウィンドウに設定する必要があります。これらのタイプのウィンドウは、それらがアタッチされているウィンドウの隣で Z オーダーのままであり、その座標はそれらがアタッチされているアプリケーション ウィンドウを基準としています。
1.TYPE_APPLICATION_PANEL
パネルのサブウィンドウの場合、PopupWindow
PopupWindow
ソース コードで指定されたウィンドウ レベルなど、ウィンドウの上部にパネルを適用します。
private int mWindowLayoutType = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
2.TYPE_APPLICATION_MEDIA
メディア (ビデオなど) を表示するウィンドウ。Android 7.1以前のSurfaceView
ソースコードにおけるデフォルトのレベル、SurfaceView
ソースコードにおけるsetZOrderOnTop()
メソッド、およびSurfaceView
設定されている表示順序です。
public void setZOrderOnTop(booleanonTop) {
if (onTop) {
mWindowType = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
// ensures the surface is placed below the IME
mLayout.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
} else {
mWindowType = WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
mLayout.flags&= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
}
}
3.TYPE_APPLICATION_MEDIA_OVERLAY
隠しタイプのため、アプリケーションから直接呼び出すことはできません。Android 7.1 より前のSurfaceView
ソース コードにも含まれています。
public void setZOrderMediaOverlay(booleanisMediaOverlay) {
mWindowType = isMediaOverlay
? WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY
: WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
}
4.TYPE_APPLICATION_SUB_PANEL
アプリケーションウィンドウのサブパネルは、ポップアップリストやポップアップエディットボックスなどTYPE_APPLICATION_PANEL
の上位層を表します。PopupWindow
Editor
5.TYPE_APPLICATION_ATTACHED_DIALOG
同様ですTYPE_APPLICATION_PANEL
が、ウィンドウのレイアウトは、コンテナの子ウィンドウとしてではなく、トップレベル ウィンドウのレイアウトとして発生します。たとえばCharacterPickerDialog
。PhoneWindow
ソースコードのopenPanel()
メソッドではこのタイプを使用していますが、Android 7.1 以降では異なります。どちらの値も 0 未満で、現在の表示ウィンドウの下層にあることを意味します: 6. 非表示の
タイプTYPE_APPLICATION_ABOVE_SUB_PANEL
はサブパネルと、アプリケーション ウィンドウの上にあるそのサブパネル。パネル ウィンドウ。これらのウィンドウは、TYPE_APPLICATION_SUB_PANEL
接続されているウィンドウおよびパネルの上に表示されます。
システムウィンドウレベル
開発中に、ウィンドウは次のように追加されることがよくあります。
mWindowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
mLayoutParams = new WindowManager.LayoutParams();
mLayoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT; mLayoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
mLayoutParams.format = PixelFormat.RGBA_8888;
mLayoutParams.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN; mLayoutParams.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
mLayoutParams.type = WindowManager.LayoutParams. TYPE_APPLICATION_OVERLAY;
mWindowManager.addView(view, mLayoutParams);
注: TYPE_APPLICATION_OVERLAY は Android 8 で追加されたタイプです
この方法で追加されたウィンドウはすべてシステム ウィンドウであり、ウィンドウのアクセス許可も必要です。
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
システム ウィンドウの階層タイプは次のとおりです。
窓の種類 | 説明する |
---|---|
FIRST_SYSTEM_WINDOW | システム ウィンドウ タイプ、開始値 2000 |
TYPE_STATUS_BAR | ステータスバー。ステータス バー ウィンドウは 1 つだけ画面の上部に配置でき、他のすべてのウィンドウは下に移動して画面の下に表示されます。フルスクリーンはパラメータで設定できます。 |
TYPE_SEARCH_BAR | 検索バー。検索バー ウィンドウは 1 つだけ、画面の上部にのみ存在できます。ステータスバーに表示 |
TYPE_PHONE | 着信などの電話ウィンドウ。アプリ ウィンドウの上、ステータス バーの後ろ。廃止されました。代わりに TYPE_APPLICATION_OVERLAY を使用してください |
TYPE_SYSTEM_ALERT | バッテリ低下警告ポップアップ ボックスなどのシステム警告ウィンドウ。廃止されました。代わりに TYPE_APPLICATION_OVERLAY を使用してください。 |
TYPE_KEYGUARD | ロック画面ウィンドウ。参照されたインターフェイスは生成されません。 |
TYPE_TOAST | トースト一時通知ウィンドウ。廃止されました。代わりに TYPE_APPLICATION_OVERLAY を使用してください。 |
TYPE_SYSTEM_OVERLAY | システム オーバーレイ ウィンドウは、他のすべてのウィンドウの上に表示する必要があります。これらのウィンドウは入力フォーカスを持つことができないため、ロック画面に干渉する可能性があります。廃止されました。代わりに TYPE_APPLICATION_OVERLAY を使用してください。 |
TYPE_PRIORITY_PHONE | ロック画面がアクティブな場合でも表示する必要があるモバイル UI を優先します。これらのウィンドウは入力フォーカスを持つことができないため、ロック画面に干渉する可能性があります。廃止されました。代わりに TYPE_APPLICATION_OVERLAY を使用してください。 |
TYPE_SYSTEM_DIALOG | ステータスバーからスライドして現れるパネル。 |
TYPE_KEYGUARD_DIALOG | 画面ロック時に表示されるダイアログ。 |
TYPE_SYSTEM_ERROR | システムエラーウィンドウ。廃止されました。代わりに TYPE_APPLICATION_OVERLAY を使用してください。 |
TYPE_INPUT_METHOD | 入力方法ウィンドウ。通常の UI の上に表示されます。アプリケーション ウィンドウのサイズを変更したりパンしたりして、ウィンドウの表示中に入力フォーカスを表示したままにすることができます。 |
TYPE_INPUT_METHOD_DIALOG | 入力方法ダイアログ ウィンドウは、現在の入力方法ウィンドウの上に表示されます。 |
TYPE_WALLPAPER | 壁紙ウィンドウ。壁紙の窓の後ろに表示したいレベルに配置します。このシステムには壁紙サービスがあり、壁紙に対応する TOKEN を使用してウィンドウを特別に調整できます。 |
TYPE_STATUS_BAR_PANEL | SystemUIDialog、SystemUI の HeadsUpView など、ステータス バーからスライドして表示されるパネル。生成されないAPPによって使用されるタイプ |
TYPE_SECURE_SYSTEM_OVERLAY | セキュリティ システム オーバーレイ ウィンドウは、他のすべてのウィンドウの上に表示する必要があります。これらのウィンドウは入力フォーカスを持つことができないため、ロック画面に干渉する可能性があります。これは、システム自体のみがこれらのオーバーレイの作成を許可されることを除いて、TYPE_SYSTEM_OVERLAY とまったく同じです。アプリケーションはセキュリティ システム オーバーレイを作成する権限を取得できません。隠しタイプ |
TYPE_DRAG | 疑似ウィンドウをドラッグ アンド ドロップします。ドラッグ レイヤは最大 1 つあり、他のすべてのウィンドウの上に配置されます。隠しタイプ |
TYPE_STATUS_BAR_SUB_PANEL | ステータス バーからスライドするパネルがすべてのユーザーのウィンドウに表示されます。これらのウィンドウは、ステータス バーおよび TYPE_STATUS_BAR_PANEL ウィンドウの上部に表示されます。たとえば、メソッドSystemUIDialog を通じてsetWindowOnTop() TYPE_STATUS_BAR_PANEL の TYPE_STATUS_BAR_SUB_PANEL 表示レベルを切り替えます。隠しタイプ |
タイプポインター | マウスカーソル。隠しタイプ |
タイプナビゲーションバー | ナビゲーションバー。隠しタイプ |
タイプ_ボリューム_オーバーレイ | ユーザーがシステムボリュームを変更するときに表示されるボリュームレベルダイアログボックス。隠しタイプ |
タイプ_ブート_プログレス | すべての上に進行状況ダイアログを起動します。隠しタイプ |
TYPE_INPUT_CONSUMER | システム UI バーが非表示のときに使用される入力イベントのウィンドウ タイプ。隠しタイプ |
TYPE_NAVIGATION_BAR_PANEL | ナビゲーション バー パネル (ナビゲーション バーがステータス バーと異なる場合)。隠しタイプ |
TYPE_DISPLAY_OVERLAY | オーバーレイウィンドウを表示します。セカンダリ ディスプレイ デバイスをシミュレートするために使用されます。隠しタイプ |
TYPE_MAGNIFICATION_OVERLAY | オーバーレイウィンドウを拡大します。アクセシビリティ拡大が有効な場合に、表示の拡大部分を強調表示するために使用されます。隠しタイプ |
TYPE_PRIVATE_PRESENTATION | プライベートトッププレゼンテーションウィンドウ。プレゼンテーションは、対応する表示パラメータ FLAG_PRIVATE に従って設定されます。 |
TYPE_VOICE_INTERACTION | 音声対話ウィンドウ。隠しタイプ |
TYPE_ACCESSIBILITY_OVERLAY | 由连接的AccessibilityService覆盖的窗口,用于拦截用户交互,而无需更改可访问性服务可以内省的窗口。特别是,可访问性服务只能内省有视力的用户可以与之交互的窗口,即他们可以触摸这些窗口或在这些窗口中键入内容。例如,如果有一个可触摸的全屏辅助功能覆盖,则辅助功能服务将对其下方的窗口进行内省,即使它们被可触摸窗口覆盖。 |
TYPE_VOICE_INTERACTION_STARTING | 语音交互层的启动窗口。 |
TYPE_DOCK_DIVIDER | 用于显示用于调整堆栈大小的句柄的窗口。此窗口由系统进程所有。隐藏的类型 |
TYPE_QS_DIALOG | 类似于 TYPE_APPLICATION_ATTACHED_DIALOG,但由快速设置平铺使用。隐藏的类型 |
TYPE_SCREENSHOT | 屏幕截图。截取之下的窗口层级。如果采用android远程的层级截图无法截取倒车相关的UI视图。隐藏接口。 |
TYPE_PRESENTATION | 外部显示器上的演示窗口。隐藏的类型 |
TYPE_APPLICATION_OVERLAY | 用程序覆盖窗口显示在所有活动窗口上方(类型介于 FIRST_APPLICATION_WINDOW和 LAST_APPLICATION_WINDOW之间),但显示在状态栏或IME等关键系统窗口下方。系统可以随时改变这些窗口的位置、大小或可见性,以减少用户的视觉混乱,并管理资源要android.Manifest.permissionSYSTEM_ALERT_WINDOW权限。系统将调整具有此窗口类型的进程的重要性,以减少低内存杀手杀死它们的机会 |
TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY | 用于在其他窗口之上添加辅助功能窗口放大倍数的窗口。这将把窗口放置在覆盖窗口中。隐藏的类型 |
TYPE_NOTIFICATION_SHADE | 锁屏时通知效果。只能有一个状态栏窗口;它被放置在屏幕的顶部,所有其他窗口都向下移动,所以它们都在屏幕的下面。隐藏的类型 |
TYPE_STATUS_BAR_ADDITIONAL | 画面の通常とは異なる部分 (つまり、画面の左側または下側) にステータス バーを表示するために使用されます。隠しタイプ |
LAST_SYSTEM_WINDOW | システムウィンドウタイプの最高レベル 2999 |
以下は Android 1 から始まるウィンドウ レベルです。初期の 10 以上から現在では 40 以上に発展し、さらに多くのウィンドウ レベルがあります。
カスタムウィンドウ階層
車載ソリューションでは反転などの特殊なインターフェースを上位のウィンドウレベルで表示する必要があり、Android本来のウィンドウレベルでは車載のニーズを満たしていないため、車載のウィンドウレベルをカスタマイズすることになります。
以下の図は、参考用のカスタム ウィンドウ階層を示しています。
システムはウィンドウ レベルをカスタマイズできます。フレームワークの変更については、別のブログ「
Android カスタム ウィンドウ レベル (車両システムの反転画像表示レベルのカスタマイズ)」を参照してください。
カスタム ウィンドウ レベルの初期レベル値も Android バージョンによって異なるため、SystemProperties.getInt("ro.custom.window", 2041)
初期値はシステム プロパティを通じて決定する必要があります。
たとえば、Android 13 プラットフォームのデフォルト属性はro.custom.window
2401 ですが、Android 9 およびその他のプラットフォームでは 2031 です。これの目的は、Android のネイティブ ウィンドウ階層と競合するため、プラットフォームに応じて初期値を調整する必要があります。
TYPE_CUSTOM_FIRST_WINDOW()
Android のネイティブ ウィンドウ レベルより上の、初期システム ウィンドウ レベルをカスタマイズするには
TYPE_TOP_BAR
以降TYPE_BOTTOM_BAR
、TYPE_CUSTOM_FIRST_WINDOW
ただし、逆インターフェースの下に表示されます。
TYPE_REVERSE_WINDOW
反転画像のウィンドウ レベル。逆をカバーするには、より高いレベルを使用するか、逆が表示された後にそれを追加する必要がありますTYPE_CUSTOM_LAST_WINDOW
。