《Android開發(fā)藝術(shù)探索》學(xué)習(xí)筆記-Window

WindowManager

獲取方式:

context.getSystemService(Context.WINDOW_SERVICE)

自由添加一個window層的控件:

val layoutParams = WindowManager.LayoutParams(
            ViewGroup.LayoutParams.WRAP_CONTENT,
            ViewGroup.LayoutParams.WRAP_CONTENT, TYPE_APPLICATION_OVERLAY, 0,
            PixelFormat.TRANSPARENT
        )
        layoutParams.flags =
            WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or
                    WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or
                    WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
        layoutParams.gravity = Gravity.LEFT or Gravity.TOP
        layoutParams.x = 100
        layoutParams.x = 300

        val view = TextView(context)
        view.text = "WindowManager test"
        val windowManager: WindowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
        windowManager.addView(view,layoutParams)

window實(shí)際是以View的形式存在的捏顺,WindowManager添加View時會創(chuàng)建對應(yīng)的window被View依附

  • WindowManager繼承自ViewManager
public interface ViewManager
{
    public void addView(View view, ViewGroup.LayoutParams params);
    public void updateViewLayout(View view, ViewGroup.LayoutParams params);
    public void removeView(View view);
}

是一組抽象方法,ViewGroup也實(shí)現(xiàn)自這個接口

  • WindowManager的實(shí)現(xiàn)類是WindowManagerImpl
  • WindowManagerImpl的方法實(shí)現(xiàn)實(shí)際上是操作WindowManagerGlobal纬黎,WindowManagerGlobal是單例
  • addView時幅骄,創(chuàng)建對應(yīng)的ViewRootImpl,WindowManagerImpl中維護(hù):
    mViews存放View對象本今;
    mRoots存放View對應(yīng)的ViewRootImpl對象拆座;
    addView的mParentWindow來源于createLocalWindowManager,通過createLocalWindowManager設(shè)置parentWindow(后面會說到設(shè)置所有依附于Activity的window的parentWindow都是Activity的window)冠息,Activity中獲取的WindowManage都是綁定了PhoneWindow的
  if (wm == null) {
            wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
        }
        mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);

mParams存放添加這個View時的WindowManager.LayoutParams

  • 最后交給了ViewRootImpl.setView方法去添加
  • setView方法去添加
 requestLayout();
 ...
  res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
                            getHostVisibility(), mDisplay.getDisplayId(), mTmpFrame,
                            mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
                            mAttachInfo.mOutsets, mAttachInfo.mDisplayCutout, mInputChannel,
                            mTempInsets);
                    setFrame(mTmpFrame);

IWindowSession mWindowSession的實(shí)現(xiàn)是Session類挪凑,這里是個IPC,是通過WindowManagerService的openSession創(chuàng)建出來的,最后將任務(wù)交給了WindowManagerService的addWindow方法

  • mWindow是ViewRootImpl構(gòu)造方法創(chuàng)建的逛艰,是個IWindow.Stub躏碳,也是用了IPC

Activity的Window

在Activity的attach方法中創(chuàng)建:

 mWindow = new PhoneWindow(this, window, activityConfigCallback);
 mWindow.setWindowControllerCallback(this);

所以Activity中的window就是PhoneWindow,并且設(shè)置了WindowControllerCallback就是Activity自己散怖,Activity中的一些回調(diào)就來自這個window

Activity的setContentView方法

調(diào)用了window的setContentView

 getWindow().setContentView(layoutResID);

然后看PhoneWindow:

   public void setContentView(int layoutResID) {
        if (mContentParent == null) {
            installDecor();
        } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            mContentParent.removeAllViews();
        }

       菇绵。。镇眷。
       mLayoutInflater.inflate(layoutResID, mContentParent);
        咬最。。偏灿。
    }
  1. 首先檢查是否有mContentParent(setContentView方法可能會重復(fù)調(diào)用覆蓋原有布局丹诀,所以這里需要判斷)钝的,沒有則:通過installDecor()先創(chuàng)建DecorView(#generateDecor()翁垂,同時會綁定當(dāng)前Window),然后根據(jù)主題設(shè)置加載布局作為DecorView的子View(#generateLayout())硝桩,比如有標(biāo)題欄則可能是個LinearLayout沿猜,將這個子View中id為content的View賦值給mContentParent。
  2. 最后將setContentView設(shè)置的View加載到mContentParent下面去
  3. 現(xiàn)在布局就加載到Window里DecorView下面mContentParent中去了碗脊,根據(jù)上面WindowManager的知識啼肩,最后需要WindowManager.addView才能完成View的添加
  4. 最后在Activity的makeVisible()方法中完成這件事
  void makeVisible() {
        if (!mWindowAdded) {
            ViewManager wm = getWindowManager();
            wm.addView(mDecor, getWindow().getAttributes());
            mWindowAdded = true;
        }
        mDecor.setVisibility(View.VISIBLE);
    }

Dialog中的Window

總體和Activity相似。有一點(diǎn)不同就是openOptionsMenu()添加的window的parentWindow是Dialog的這個window(下面一條會說明parentWindow一般都是Activity的window),這樣當(dāng)彈窗消息時祈坠,依附彈窗的菜單方便一起管理

Context.getSystemService(Context.WINDOW_SERVICE)

我們添加的子window都是需要依附一個Activity害碾,除非是系統(tǒng)級的,所以我們通過Context.getSystemService(Context.WINDOW_SERVICE)拿到的WindowManager本質(zhì)上都是從Activity的getSystemService獲取到的赦拘,Activity的mWindowManager是通過內(nèi)部的mWindow獲取到的慌随,也就是createLocalWindowManager綁定了當(dāng)前Activity持有的Window的,所以后續(xù)創(chuàng)建的window都是依附于當(dāng)前Activity的Window的子window躺同,即獲取到的WindowManager的parentWindow都是Activty的這個window

待解決的問題

Activity里面創(chuàng)建的window以及Dialog中創(chuàng)建出來的window如何被加載的阁猜,即在WindowManager.addView的哪個過程被用到,區(qū)別于我們在一開始的例子:parentWindow上添加window的時候都是直接addView而用不自己創(chuàng)建window

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蹋艺,一起剝皮案震驚了整個濱河市剃袍,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌捎谨,老刑警劉巖民效,帶你破解...
    沈念sama閱讀 222,729評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異侍芝,居然都是意外死亡研铆,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評論 3 399
  • 文/潘曉璐 我一進(jìn)店門州叠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來棵红,“玉大人,你說我怎么就攤上這事咧栗∧嫣穑” “怎么了?”我有些...
    開封第一講書人閱讀 169,461評論 0 362
  • 文/不壞的土叔 我叫張陵致板,是天一觀的道長交煞。 經(jīng)常有香客問我,道長斟或,這世上最難降的妖魔是什么素征? 我笑而不...
    開封第一講書人閱讀 60,135評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮萝挤,結(jié)果婚禮上御毅,老公的妹妹穿的比我還像新娘。我一直安慰自己怜珍,他們只是感情好端蛆,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,130評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著酥泛,像睡著了一般今豆。 火紅的嫁衣襯著肌膚如雪嫌拣。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,736評論 1 312
  • 那天呆躲,我揣著相機(jī)與錄音异逐,去河邊找鬼。 笑死插掂,一個胖子當(dāng)著我的面吹牛应役,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播燥筷,決...
    沈念sama閱讀 41,179評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼箩祥,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了肆氓?” 一聲冷哼從身側(cè)響起袍祖,我...
    開封第一講書人閱讀 40,124評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎谢揪,沒想到半個月后蕉陋,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,657評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡拨扶,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,723評論 3 342
  • 正文 我和宋清朗相戀三年凳鬓,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片患民。...
    茶點(diǎn)故事閱讀 40,872評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡缩举,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出匹颤,到底是詐尸還是另有隱情仅孩,我是刑警寧澤,帶...
    沈念sama閱讀 36,533評論 5 351
  • 正文 年R本政府宣布印蓖,位于F島的核電站辽慕,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏赦肃。R本人自食惡果不足惜溅蛉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,213評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望他宛。 院中可真熱鬧船侧,春花似錦、人聲如沸堕汞。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,700評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽讯检。三九已至琐鲁,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間人灼,已是汗流浹背围段。 一陣腳步聲響...
    開封第一講書人閱讀 33,819評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留投放,地道東北人奈泪。 一個月前我還...
    沈念sama閱讀 49,304評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像灸芳,于是被迫代替她去往敵國和親涝桅。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,876評論 2 361

推薦閱讀更多精彩內(nèi)容