android int 首位值_Android应用视图的管理者Window
點(diǎn)擊上方藍(lán)色文字關(guān)注我哦
Window在Android是一個(gè)窗口的概念,日常開發(fā)中我們和它接觸的不多,我們更多接觸的是View,但是View都是通過Window來呈現(xiàn)的,Window是View的直接管理者。而WindowManager承擔(dān)者管理Window的責(zé)任。
窗口類型
Window在Android中有三種類型:
應(yīng)用Window:z-index在1~99之間,它往往對應(yīng)著一個(gè)Activity。
子Window:z-index在1000~1999之間,它往往不能獨(dú)立存在,需要依附在父Window上,例如Dialog等。
系統(tǒng)Window:z-index在2000~2999之間,它往往需要聲明權(quán)限才能創(chuàng)建,例如Toast、狀態(tài)欄、系統(tǒng)音量條、錯(cuò)誤提示框都是系統(tǒng)Window。
z-index是Android窗口的層級(jí)的概念,z-index越大的窗口越居于頂層,
z-index對應(yīng)著WindowManager.LayoutParams里的type參數(shù),具體說來。
應(yīng)用Window
public static final int FIRST_APPLICATION_WINDOW = 1;//1
public static final int TYPE_BASE_APPLICATION = 1;//窗口的基礎(chǔ)值,其他的窗口值要大于這個(gè)值
public static final int TYPE_APPLICATION = 2;//普通的應(yīng)用程序窗口類型
public static final int TYPE_APPLICATION_STARTING = 3;//應(yīng)用程序啟動(dòng)窗口類型,用于系統(tǒng)在應(yīng)用程序窗口啟動(dòng)前顯示的窗口。
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;//子窗口類型結(jié)束值
系統(tǒng)Window
public static final int FIRST_SYSTEM_WINDOW = 2000;//系統(tǒng)窗口類型初始值
public static final int TYPE_STATUS_BAR = FIRST_SYSTEM_WINDOW;//系統(tǒng)狀態(tài)欄窗口
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;//系統(tǒng)ALERT窗口
public static final int TYPE_KEYGUARD = FIRST_SYSTEM_WINDOW+4;//鎖屏窗口
public static final int TYPE_TOAST = FIRST_SYSTEM_WINDOW+5;//TOAST窗口
窗口參數(shù)
在WindowManager里定義了一個(gè)LayoutParams內(nèi)部類,它描述了窗口的參數(shù)信息,主要包括:
public int x:窗口x軸坐標(biāo)
public int y:窗口y軸坐標(biāo)
public int type:窗口類型
public int flags:窗口屬性
public int softInputMode:輸入法鍵盤模式
關(guān)于窗口屬性,它控制著窗口的行為,舉幾個(gè)常見的:
FLAG_ALLOW_LOCK_WHILE_SCREEN_ON 只要窗口可見,就允許在開啟狀態(tài)的屏幕上鎖屏
FLAG_NOT_FOCUSABLE 窗口不能獲得輸入焦點(diǎn),設(shè)置該標(biāo)志的同時(shí),FLAG_NOT_TOUCH_MODAL也會(huì)被設(shè)置
FLAG_NOT_TOUCHABLE 窗口不接收任何觸摸事件
FLAG_NOT_TOUCH_MODAL 在該窗口區(qū)域外的觸摸事件傳遞給其他的Window,而自己只會(huì)處理窗口區(qū)域內(nèi)的觸摸事件
FLAG_KEEP_SCREEN_ON 只要窗口可見,屏幕就會(huì)一直亮著
FLAG_LAYOUT_NO_LIMITS 允許窗口超過屏幕之外
FLAG_FULLSCREEN 隱藏所有的屏幕裝飾窗口,比如在游戲、播放器中的全屏顯示
FLAG_SHOW_WHEN_LOCKED 窗口可以在鎖屏的窗口之上顯示
FLAG_IGNORE_CHEEK_PRESSES 當(dāng)用戶的臉貼近屏幕時(shí)(比如打電話),不會(huì)去響應(yīng)此事件
FLAG_TURN_SCREEN_ON 窗口顯示時(shí)將屏幕點(diǎn)亮
關(guān)于窗口類型,它對應(yīng)著窗口的層級(jí),上面我們也提到過了。
它的構(gòu)造函數(shù)也主要是針對這幾個(gè)參數(shù)的。
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;
????????????}
?}
窗口模式
關(guān)于窗口模式我們就比較熟悉了,我們會(huì)在AndroidManifest.xml里Activity的標(biāo)簽下設(shè)置android:windowSoftInputMode="adjustNothing",來控制輸入鍵盤顯示行為。
可選的有6個(gè)參數(shù),源碼里也有6個(gè)值與之對應(yīng):
SOFT_INPUT_STATE_UNSPECIFIED:沒有指定軟鍵盤輸入?yún)^(qū)域的顯示狀態(tài)。
SOFT_INPUT_STATE_UNCHANGED:不要改變軟鍵盤輸入?yún)^(qū)域的顯示狀態(tài)。
SOFT_INPUT_STATE_HIDDEN:在合適的時(shí)候隱藏軟鍵盤輸入?yún)^(qū)域,例如,當(dāng)用戶導(dǎo)航到當(dāng)前窗口時(shí)。
SOFT_INPUT_STATE_ALWAYS_HIDDEN:當(dāng)窗口獲得焦點(diǎn)時(shí),總是隱藏軟鍵盤輸入?yún)^(qū)域。
SOFT_INPUT_STATE_VISIBLE:在合適的時(shí)候顯示軟鍵盤輸入?yún)^(qū)域,例如,當(dāng)用戶導(dǎo)航到當(dāng)前窗口時(shí)。
SOFT_INPUT_STATE_ALWAYS_VISIBLE:當(dāng)窗口獲得焦點(diǎn)時(shí),總是顯示軟鍵盤輸入?yún)^(qū)域。
當(dāng)然,我們也可以通過代碼設(shè)置鍵盤模式。
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);窗口回調(diào)
Window里定義了一個(gè)Callback接口,Activity實(shí)現(xiàn)了Window.Callback接口,將Activity關(guān)聯(lián)給Window,Window就可以將一些事件交由Activity處理。
public?interface?Callback?{????????//鍵盤事件分發(fā)
????????public?boolean?dispatchKeyEvent(KeyEvent?event);
????????//觸摸事件分發(fā)
????????public?boolean?dispatchTouchEvent(MotionEvent?event);
????????//軌跡球事件分發(fā)
????????public?boolean?dispatchTrackballEvent(MotionEvent?event);
????????//可見性事件分發(fā)
????????public?boolean?dispatchPopulateAccessibilityEvent(AccessibilityEvent?event);
????????//創(chuàng)建Panel?View
????????public?View?onCreatePanelView(int?featureId);
????????//創(chuàng)建menu
????????public?boolean?onCreatePanelMenu(int?featureId,?Menu?menu);
????????//畫板準(zhǔn)備好時(shí)回調(diào)
????????public?boolean?onPreparePanel(int?featureId,?View?view,?Menu?menu);
????????//menu打開時(shí)回調(diào)
????????public?boolean?onMenuOpened(int?featureId,?Menu?menu);
????????//menu?item被選擇時(shí)回調(diào)
????????public?boolean?onMenuItemSelected(int?featureId,?MenuItem?item);
????????//Window?Attributes發(fā)生變化時(shí)回調(diào)
????????public?void?onWindowAttributesChanged(WindowManager.LayoutParams?attrs);
????????//Content?View發(fā)生變化時(shí)回調(diào)
????????public?void?onContentChanged();
????????//窗口焦點(diǎn)發(fā)生變化時(shí)回調(diào)
????????public?void?onWindowFocusChanged(boolean?hasFocus);
????????//Window被添加到WIndowManager時(shí)回調(diào)
????????public?void?onAttachedToWindow();
????????//Window被從WIndowManager中移除時(shí)回調(diào)
????????public?void?onDetachedFromWindow();
?????????*/
????????//畫板關(guān)閉時(shí)回調(diào)
????????public?void?onPanelClosed(int?featureId,?Menu?menu);
????????//用戶開始執(zhí)行搜索操作時(shí)回調(diào)
????????public?boolean?onSearchRequested();
????}
窗口實(shí)現(xiàn)
Window是一個(gè)抽象類,它的唯一實(shí)現(xiàn)類是PhoneWindow,PhoneWindow里包含了以下內(nèi)容:
private DecorView mDecor:DecorView是Activity中的頂級(jí)View,它本質(zhì)上是一個(gè)FrameLayout,一般說來它內(nèi)部包含標(biāo)題欄和內(nèi)容欄(com.android.internal.R.id.content)。
ViewGroup mContentParent:窗口內(nèi)容視圖,它是mDecor本身或者是它的子View。
private ImageView mLeftIconView:左上角圖標(biāo)
private ImageView mRightIconView:右上角圖標(biāo)
private ProgressBar mCircularProgressBar:圓形loading條
private ProgressBar mHorizontalProgressBar:水平loading條
其他的一些和轉(zhuǎn)場動(dòng)畫相關(guān)的Transition與listener
看到這些,大家有沒有覺得很熟悉,這就是我們?nèi)粘i_發(fā)中經(jīng)常見到的東西,它在PhoneWindow里被創(chuàng)建。另外,我們在Activity里經(jīng)常調(diào)用的方法,它的實(shí)際實(shí)現(xiàn)也是 在PhoneWindow里,我們分別來看一看。
setContentView()
這是一個(gè)我們非常熟悉的方法,只不過我們通常是在Activity里進(jìn)行調(diào)用,但是它的實(shí)際實(shí)現(xiàn)是在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則創(chuàng)建它,并將創(chuàng)建好的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.?回調(diào)Window.Callback里的onContentChanged()方法,這個(gè)Callback也被Activity
????????????//所持有,因此它實(shí)際回調(diào)的是Activity里的onContentChanged()方法,通知Activity
????????????//視圖已經(jīng)發(fā)生改變。
????????????cb.onContentChanged();
????????}
????????mContentParentExplicitlySet?=?true;
????}????
}
這個(gè)方法主要做了兩件事情:
如果沒有DecorView則創(chuàng)建它,并將創(chuàng)建好的DecorView賦值給mContentParent
將Activity傳入的布局文件生成View并添加到mContentParent中
回調(diào)Window.Callback里的onContentChanged()方法,這個(gè)Callback也被Activity所持有,因此它實(shí)際回調(diào)的是Activity里的onContentChanged()方法,通知Activity視圖已經(jīng)發(fā)生改變。
創(chuàng)建DecorView是通過installDecor()方法完成的,它的邏輯也非常簡單,就是創(chuàng)建了一個(gè)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)?{
????????//讀取并設(shè)置主題顏色、狀態(tài)欄顏色等信息
????????...
????????ViewGroup?contentParent?=?(ViewGroup)findViewById(ID_ANDROID_CONTENT);
????????//設(shè)置窗口參數(shù)等信息
????????...
????????return?contentParent;
????}????
}
通過以上這些流程,DecorView已經(jīng)被創(chuàng)建并初始化完畢,Activity里的布局文件也被成功的添加到PhoneWindow的mContentParent(實(shí)際上就是DecorView,它是Activity的頂層View) 中,但是這個(gè)時(shí)候DecorView還沒有真正的被WindowManager添加到Window中,它還無法接受用戶的輸入信息和焦點(diǎn)事件,這個(gè)時(shí)候就相當(dāng)于走到了Activity的onCreate()流程,界面還 未展示給用戶。
直到走到Activity的onResume()方法,它會(huì)調(diào)用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。實(shí)現(xiàn)原理相同。
推薦閱讀
Android窗口管理框架概述
Android應(yīng)用視圖的載體View
關(guān)注教程
您看此文用
??·?秒,轉(zhuǎn)發(fā)只需1秒呦~
總結(jié)
以上是生活随笔為你收集整理的android int 首位值_Android应用视图的管理者Window的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: oracle12c没有有sqlnet文件
- 下一篇: 工作中应用计算机,浅谈计算机在我国计工作