android dialog 隐藏状态栏_Android应用视图的管理者Window
點擊上方藍色文字關注我哦
Window在Android是一個窗口的概念,日常開發中我們和它接觸的不多,我們更多接觸的是View,但是View都是通過Window來呈現的,Window是View的直接管理者。而WindowManager承擔者管理Window的責任。
窗口類型
Window在Android中有三種類型:
應用Window:z-index在1~99之間,它往往對應著一個Activity。
子Window:z-index在1000~1999之間,它往往不能獨立存在,需要依附在父Window上,例如Dialog等。
系統Window:z-index在2000~2999之間,它往往需要聲明權限才能創建,例如Toast、狀態欄、系統音量條、錯誤提示框都是系統Window。
z-index是Android窗口的層級的概念,z-index越大的窗口越居于頂層,
z-index對應著WindowManager.LayoutParams里的type參數,具體說來。
應用Window
public static final int FIRST_APPLICATION_WINDOW = 1;//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;//2
子Window
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;//子窗口類型結束值
系統Window
public static final int FIRST_SYSTEM_WINDOW = 2000;//系統窗口類型初始值
public static final int TYPE_STATUS_BAR = FIRST_SYSTEM_WINDOW;//系統狀態欄窗口
public static final int TYPE_SEARCH_BAR = FIRST_SYSTEM_WINDOW+1;//搜索條窗口
public static final int TYPE_PHONE = FIRST_SYSTEM_WINDOW+2;//通話窗口
public static final int TYPE_SYSTEM_ALERT = FIRST_SYSTEM_WINDOW+3;//系統ALERT窗口
public static final int TYPE_KEYGUARD = FIRST_SYSTEM_WINDOW+4;//鎖屏窗口
public static final int TYPE_TOAST = FIRST_SYSTEM_WINDOW+5;//TOAST窗口
窗口參數
在WindowManager里定義了一個LayoutParams內部類,它描述了窗口的參數信息,主要包括:
public int x:窗口x軸坐標
public int y:窗口y軸坐標
public int type:窗口類型
public int flags:窗口屬性
public int softInputMode:輸入法鍵盤模式
關于窗口屬性,它控制著窗口的行為,舉幾個常見的:
FLAG_ALLOW_LOCK_WHILE_SCREEN_ON 只要窗口可見,就允許在開啟狀態的屏幕上鎖屏
FLAG_NOT_FOCUSABLE 窗口不能獲得輸入焦點,設置該標志的同時,FLAG_NOT_TOUCH_MODAL也會被設置
FLAG_NOT_TOUCHABLE 窗口不接收任何觸摸事件
FLAG_NOT_TOUCH_MODAL 在該窗口區域外的觸摸事件傳遞給其他的Window,而自己只會處理窗口區域內的觸摸事件
FLAG_KEEP_SCREEN_ON 只要窗口可見,屏幕就會一直亮著
FLAG_LAYOUT_NO_LIMITS 允許窗口超過屏幕之外
FLAG_FULLSCREEN 隱藏所有的屏幕裝飾窗口,比如在游戲、播放器中的全屏顯示
FLAG_SHOW_WHEN_LOCKED 窗口可以在鎖屏的窗口之上顯示
FLAG_IGNORE_CHEEK_PRESSES 當用戶的臉貼近屏幕時(比如打電話),不會去響應此事件
FLAG_TURN_SCREEN_ON 窗口顯示時將屏幕點亮
關于窗口類型,它對應著窗口的層級,上面我們也提到過了。
它的構造函數也主要是針對這幾個參數的。
public?static?class?LayoutParams?extends?ViewGroup.LayoutParams?implements?Parcelable?{????????????public?LayoutParams()?{
????????????????super(LayoutParams.MATCH_PARENT,?LayoutParams.MATCH_PARENT);
????????????????type?=?TYPE_APPLICATION;
????????????????format?=?PixelFormat.OPAQUE;
????????????}
????????????public?LayoutParams(int?_type)?{
????????????????super(LayoutParams.MATCH_PARENT,?LayoutParams.MATCH_PARENT);
????????????????type?=?_type;
????????????????format?=?PixelFormat.OPAQUE;
????????????}
????????????public?LayoutParams(int?_type,?int?_flags)?{
????????????????super(LayoutParams.MATCH_PARENT,?LayoutParams.MATCH_PARENT);
????????????????type?=?_type;
????????????????flags?=?_flags;
????????????????format?=?PixelFormat.OPAQUE;
????????????}
????????????public?LayoutParams(int?_type,?int?_flags,?int?_format)?{
????????????????super(LayoutParams.MATCH_PARENT,?LayoutParams.MATCH_PARENT);
????????????????type?=?_type;
????????????????flags?=?_flags;
????????????????format?=?_format;
????????????}
????????????public?LayoutParams(int?w,?int?h,?int?_type,?int?_flags,?int?_format)?{
????????????????super(w,?h);
????????????????type?=?_type;
????????????????flags?=?_flags;
????????????????format?=?_format;
????????????}
????????????public?LayoutParams(int?w,?int?h,?int?xpos,?int?ypos,?int?_type,int?_flags,?int?_format)?{
????????????????super(w,?h);
????????????????x?=?xpos;
????????????????y?=?ypos;
????????????????type?=?_type;
????????????????flags?=?_flags;
????????????????format?=?_format;
????????????}
?}
窗口模式
關于窗口模式我們就比較熟悉了,我們會在AndroidManifest.xml里Activity的標簽下設置android:windowSoftInputMode="adjustNothing",來控制輸入鍵盤顯示行為。
可選的有6個參數,源碼里也有6個值與之對應:
SOFT_INPUT_STATE_UNSPECIFIED:沒有指定軟鍵盤輸入區域的顯示狀態。
SOFT_INPUT_STATE_UNCHANGED:不要改變軟鍵盤輸入區域的顯示狀態。
SOFT_INPUT_STATE_HIDDEN:在合適的時候隱藏軟鍵盤輸入區域,例如,當用戶導航到當前窗口時。
SOFT_INPUT_STATE_ALWAYS_HIDDEN:當窗口獲得焦點時,總是隱藏軟鍵盤輸入區域。
SOFT_INPUT_STATE_VISIBLE:在合適的時候顯示軟鍵盤輸入區域,例如,當用戶導航到當前窗口時。
SOFT_INPUT_STATE_ALWAYS_VISIBLE:當窗口獲得焦點時,總是顯示軟鍵盤輸入區域。
當然,我們也可以通過代碼設置鍵盤模式。
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);窗口回調
Window里定義了一個Callback接口,Activity實現了Window.Callback接口,將Activity關聯給Window,Window就可以將一些事件交由Activity處理。
public?interface?Callback?{????????//鍵盤事件分發
????????public?boolean?dispatchKeyEvent(KeyEvent?event);
????????//觸摸事件分發
????????public?boolean?dispatchTouchEvent(MotionEvent?event);
????????//軌跡球事件分發
????????public?boolean?dispatchTrackballEvent(MotionEvent?event);
????????//可見性事件分發
????????public?boolean?dispatchPopulateAccessibilityEvent(AccessibilityEvent?event);
????????//創建Panel?View
????????public?View?onCreatePanelView(int?featureId);
????????//創建menu
????????public?boolean?onCreatePanelMenu(int?featureId,?Menu?menu);
????????//畫板準備好時回調
????????public?boolean?onPreparePanel(int?featureId,?View?view,?Menu?menu);
????????//menu打開時回調
????????public?boolean?onMenuOpened(int?featureId,?Menu?menu);
????????//menu?item被選擇時回調
????????public?boolean?onMenuItemSelected(int?featureId,?MenuItem?item);
????????//Window?Attributes發生變化時回調
????????public?void?onWindowAttributesChanged(WindowManager.LayoutParams?attrs);
????????//Content?View發生變化時回調
????????public?void?onContentChanged();
????????//窗口焦點發生變化時回調
????????public?void?onWindowFocusChanged(boolean?hasFocus);
????????//Window被添加到WIndowManager時回調
????????public?void?onAttachedToWindow();
????????//Window被從WIndowManager中移除時回調
????????public?void?onDetachedFromWindow();
?????????*/
????????//畫板關閉時回調
????????public?void?onPanelClosed(int?featureId,?Menu?menu);
????????//用戶開始執行搜索操作時回調
????????public?boolean?onSearchRequested();
????}
窗口實現
Window是一個抽象類,它的唯一實現類是PhoneWindow,PhoneWindow里包含了以下內容:
private DecorView mDecor:DecorView是Activity中的頂級View,它本質上是一個FrameLayout,一般說來它內部包含標題欄和內容欄(com.android.internal.R.id.content)。
ViewGroup mContentParent:窗口內容視圖,它是mDecor本身或者是它的子View。
private ImageView mLeftIconView:左上角圖標
private ImageView mRightIconView:右上角圖標
private ProgressBar mCircularProgressBar:圓形loading條
private ProgressBar mHorizontalProgressBar:水平loading條
其他的一些和轉場動畫相關的Transition與listener
看到這些,大家有沒有覺得很熟悉,這就是我們日常開發中經常見到的東西,它在PhoneWindow里被創建。另外,我們在Activity里經常調用的方法,它的實際實現也是 在PhoneWindow里,我們分別來看一看。
setContentView()
這是一個我們非常熟悉的方法,只不過我們通常是在Activity里進行調用,但是它的實際實現是在PhoneWindow里。
public?class?PhoneWindow?extends?Window?implements?MenuBuilder.Callback?{????@Override
????public?void?setContentView(int?layoutResID)?{
????????//?Note:?FEATURE_CONTENT_TRANSITIONS?may?be?set?in?the?process?of?installing?the?window
????????//?decor,?when?theme?attributes?and?the?like?are?crystalized.?Do?not?check?the?feature
????????//?before?this?happens.
????????if?(mContentParent?==?null)?{
????????????//1.?如果沒有DecorView則創建它,并將創建好的DecorView賦值給mContentParent
????????????installDecor();
????????}?else?if?(!hasFeature(FEATURE_CONTENT_TRANSITIONS))?{
????????????mContentParent.removeAllViews();
????????}
????????if?(hasFeature(FEATURE_CONTENT_TRANSITIONS))?{
????????????final?Scene?newScene?=?Scene.getSceneForLayout(mContentParent,?layoutResID,
????????????????????getContext());
????????????transitionTo(newScene);
????????}?else?{
????????????//2.?將Activity傳入的布局文件生成View并添加到mContentParent中
????????????mLayoutInflater.inflate(layoutResID,?mContentParent);
????????}
????????mContentParent.requestApplyInsets();
????????final?Callback?cb?=?getCallback();
????????if?(cb?!=?null?&&?!isDestroyed())?{
????????????//3.?回調Window.Callback里的onContentChanged()方法,這個Callback也被Activity
????????????//所持有,因此它實際回調的是Activity里的onContentChanged()方法,通知Activity
????????????//視圖已經發生改變。
????????????cb.onContentChanged();
????????}
????????mContentParentExplicitlySet?=?true;
????}????
}
這個方法主要做了兩件事情:
如果沒有DecorView則創建它,并將創建好的DecorView賦值給mContentParent
將Activity傳入的布局文件生成View并添加到mContentParent中
回調Window.Callback里的onContentChanged()方法,這個Callback也被Activity所持有,因此它實際回調的是Activity里的onContentChanged()方法,通知Activity視圖已經發生改變。
創建DecorView是通過installDecor()方法完成的,它的邏輯也非常簡單,就是創建了一個ViewGroup然后返回給了mDecor和mContentParent。
public?class?PhoneWindow?extends?Window?implements?MenuBuilder.Callback?{?public?static?final?int?ID_ANDROID_CONTENT?=?com.android.internal.R.id.content;
??private?void?installDecor()?{
?????????mForceDecorInstall?=?false;
?????????if?(mDecor?==?null)?{
?????????????//生成DecorView
?????????????mDecor?=?generateDecor(-1);
?????????????mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
?????????????mDecor.setIsRootNamespace(true);
?????????????if?(!mInvalidatePanelMenuPosted?&&?mInvalidatePanelMenuFeatures?!=?0)?{
?????????????????mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
?????????????}
?????????}?else?{
?????????????mDecor.setWindow(this);
?????????}
?????????if?(mContentParent?==?null)?{
?????????????mContentParent?=?generateLayout(mDecor);
?????????????...
?????????????}?else?{
????????????????...
?????????????}
????????????...
?????????}
?????}
?protected?ViewGroup?generateLayout(DecorView?decor)?{
????????//讀取并設置主題顏色、狀態欄顏色等信息
????????...
????????ViewGroup?contentParent?=?(ViewGroup)findViewById(ID_ANDROID_CONTENT);
????????//設置窗口參數等信息
????????...
????????return?contentParent;
????}????
}
通過以上這些流程,DecorView已經被創建并初始化完畢,Activity里的布局文件也被成功的添加到PhoneWindow的mContentParent(實際上就是DecorView,它是Activity的頂層View) 中,但是這個時候DecorView還沒有真正的被WindowManager添加到Window中,它還無法接受用戶的輸入信息和焦點事件,這個時候就相當于走到了Activity的onCreate()流程,界面還 未展示給用戶。
直到走到Activity的onResume()方法,它會調用Activity的makeVisiable()方法,DecorView才真正的被用戶所看到。
public?class?Activity?extends?ContextThemeWrapperimplements?LayoutInflater.Factory2,Window.Callback,?KeyEvent.Callback,OnCreateContextMenuListener,?ComponentCallbacks2,Window.OnWindowDismissedCallback,?WindowControllerCallback?{????void?makeVisible()?{
????????if?(!mWindowAdded)?{
????????????ViewManager?wm?=?getWindowManager();
????????????wm.addView(mDecor,?getWindow().getAttributes());
????????????mWindowAdded?=?true;
????????}
????????mDecor.setVisibility(View.VISIBLE);
????}
}
通常以上的分析,我們理解了setContentView的工作原理,另外還有addContentView、clearContentView,正如它們的名字那樣,setContentView是替換View,addContentView是添加View。實現原理相同。
推薦閱讀
Android窗口管理框架概述
Android應用視圖的載體View
關注教程
您看此文用
??·?秒,轉發只需1秒呦~
總結
以上是生活随笔為你收集整理的android dialog 隐藏状态栏_Android应用视图的管理者Window的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 苹果第四财季营收895亿美元 大中华区收
- 下一篇: input onclick点击butto