日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

android dialog 隐藏状态栏_Android应用视图的管理者Window

發布時間:2024/9/18 Android 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。