<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                #### 1. 狀態欄窗口的創建 在7.1.2節所引用的BaseStatusBar.start()方法的代碼中調用了createAndAddWindows()方法進行狀態欄窗口的創建。很顯然,createAndAddWindow()由PhoneStatusBar或TabletStatusBar實現。以PhoneStatusBar為例,參考其代碼: **PhoneStatusBar.java-->PhoneStatusBar.createAndAddWindow()** ``` public void createAndAddWindows() { addStatusBarWindow(); // 直接調用addStatusBarWindow()方法 } ``` 在addStatusBarWindow()方法中,PhoneStatusBar將會構建狀態欄的控件樹并通過WindowManager的接口為其創建窗口。 **PhoneStatusBar.java-->PhoneStatusBar.addStatusBarWindow()** ``` private void addStatusBarWindow() { // **① 通過getStatusBarHeight()方法獲取狀態欄的高度** finalint height = getStatusBarHeight(); // **② 為狀態欄創建WindowManager.LayoutParams** finalWindowManager.LayoutParams lp = new WindowManager.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, // 狀態欄的寬度為充滿整個屏幕寬度 height, // 高度來自于getStatusBarHeight()方法 WindowManager.LayoutParams.TYPE_STATUS_BAR, // 窗口類型 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE // 狀態欄不接受按鍵事件 /* FLAG_TOUCHABLE_WHEN_WAKING這一標記將使得狀態欄接受導致設備喚醒的觸摸 事件。通常這一事件會在interceptMotionBeforeQueueing()的過程中被用于 喚醒設備(或從變暗狀態下恢復),而InputDispatcher會阻止這一事件發送給 窗口。*/ | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING // FLAG_SPLIT_TOUCH允許狀態欄支持觸摸事件序列的拆分 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH, PixelFormat.TRANSLUCENT); // 狀態欄的Surface像素格式為支持透明度 // 啟用硬件加速 lp.flags|= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED; //StatusBar的gravity是LEFT和FILL_HORIZONTAL lp.gravity = getStatusBarGravity(); lp.setTitle("StatusBar"); lp.packageName = mContext.getPackageName(); // **③ 創建狀態欄的控件樹** makeStatusBarView(); // **④ 通過WindowManager.addView()創建狀態欄的窗口** mWindowManager.addView(mStatusBarWindow, lp); } ``` 此方法提供了很多重要的信息。 首先是狀態欄的高度,由getStatusBarHeight()從資源com.android.internal.R.dimen.status\_bar\_height中獲得。這一資源定義在frameworks\\base\\core\\res\\res\\values\\dimens.xml中,默認為25dip。此資源同樣在PhoneWindowManager中被用來計算作為布局準繩的八個矩形。 然后是狀態欄窗口的LayoutParams的創建。LayoutParams描述了狀態欄是怎樣的一個窗口。TYPE\_STATUS\_BAR使得PhoneWindowManager為狀態欄的窗口分配了較大的layer值,使其可以顯示在其他應用窗口之上。FLAG\_NOT\_FOCUSABLE、FLAG\_TOUCHABLE\_WHEN\_WAKING和FLAG\_SPLIT\_TOUCH則定義了狀態欄對輸入事件的響應行為。 注意 通過創建窗口所使用的LayoutParams來推斷一個窗口的行為十分重要。在分析一個需要創建窗口的模塊的工作原理時,從窗口創建過程往往是一個不錯的切入點。 另外需要知道的是,窗口創建之后,其LayoutParams是會發生變化的。以狀態欄為例,創建窗口時其高度為25dip,flags描述其不可接收按鍵事件。不過當用戶按下狀態欄導致卷簾下拉時,PhoneStatusBar會通過WindowManager.updateViewLayout()方法修改窗口的LayoutParams的高度為MATCH\_PARENT,即充滿整個屏幕以使得卷簾可以滿屏顯示,并且移除FLAG\_NOT\_FOCUSABLE,使得PhoneStatusBar可以通過監聽BACK鍵以收回卷簾。 在makeStatusBarView()完成控件樹的創建之后,WindowManager.addView()將根據控件樹創建出狀態欄的窗口。顯而易見,狀態欄控件樹的根控件被保存在mStatusBarWindow成員中。 createStatusBarView()負責從R.layout.super\_status\_bar所描述的布局中實例化出一棵控件樹。并從這個控件樹中取出一些比較重要的控件并保存在對應的成員變量中。因此從R.layout.super\_status\_bar入手可以很容易地得知狀態欄的控件樹的結構: #### 2.狀態欄控件樹的結構 參考SystemUI下super\_status\_bar.xml所描述的布局內容,可以看到其根控件是一個名為StatusBarWindowView的控件,它繼承自FrameLayout。在其下的兩個直接子控件如下: - @layout/status\_bar所描述的布局。這是用戶平時所見的狀態欄。 - PenelHolder:這個繼承自FrameLayout的控件是狀態欄的卷簾。在其下的兩個直接子控件@layout/status\_bar\_expanded以及@layout/quick\_settings分別對應于卷簾之中的通知列表面板以及快速設定面板。 在正常情況下,StatusBarWindowView中只有@layout/status\_bar所描述的布局是可見的,并且狀態欄窗口為com.android.internal.R.dimen.status\_bar\_height所定義的高度。當StatusBarWindowView截獲了ACTION\_DOWN的觸摸事件后,會修改窗口的高度為MATCH\_PARENT,然后將PenelHolder設為可見并跟隨用戶的觸摸軌跡,由此實現了卷簾的下拉效果。 說明 PenelHolder集成自FrameLayout。那么它如何做到在@layout/status\_bar\_expanded以及@layout/quick\_settings兩個控件之間進行切換顯示呢?答案就在第6章所介紹的ViewGroup. getChildDrawingOrder()方法中。此方法的返回值影響了子控件的繪制順序,同時也影響了控件接收觸摸事件的優先級。當PenelHolder希望顯示@layout/status\_bar\_expanded面版時,它在此方法中將此面版的繪制順序放在最后,使其在繪制時能夠覆蓋@layout/quick\_settings,并且優先接受觸摸事件。反之則將@layout/quick\_settings的繪制順序放在最后即可。 因此狀態欄控件樹的第一層結構如圖7-2所示。 :-: ![](http://img.blog.csdn.net/20150814134219928?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 圖 7 - 2狀態欄控件樹的結構1 再看status\_bar.xml所描述的布局內容,其根控件是一個繼承自FrameLayout的名為StatusBarView類型的控件,makeStatusBarView()方法會將其保存為mStatusBarView。其直接子控件有三個: - @id/notification\_lights\_out,一個ImageView,并且一般情況下它是不可見的。在SystemUIVisiblity中有一個名為SYSTEM\_UI\_FLAG\_LOW\_PROFILE的標記。當一個應用程序希望讓用戶的注意力更多地集中在它所顯示的內容時,可以在其SystemUIVisibility中添加這一標記。SYSTEM\_UI\_FLAG\_LOW\_PROFILE會使得狀態欄與導航欄進入低辨識度模式。低辨識度模式下的狀態欄將不會顯示任何信息,只是在黑色背景中顯示一個灰色圓點而已。而這一個黑色圓點即是這里的id/notification\_lights\_out。 - @id/status\_bar\_contents,一個LinearLayout,狀態欄上各種信息的顯示場所。 - @id/ticker,一個LinearLayout,其中包含了一個ImageSwitcher和一個TickerView。在正常情況下@id/ticker是不可見的。當一個新的通知到來時(例如一條新的短信),狀態欄上會以動畫方式逐行顯示通知的內容,使得用戶可以在無需下拉卷簾的情況下了解新通知的內容。這一功能在狀態欄中被稱之為Ticker。而@id/ticker則是完成Ticker功能的場所。makeStatusBarView()會將@id/ticker保存為mTickerView。 至此,狀態欄控件樹的結構可以擴充為圖7-3所示。 :-: ![](http://img.blog.csdn.net/20150814134232090?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 圖 7 - 3狀態欄控件樹的結構2 再來分析@id/status\_bar\_contents所包含的內容。如前文所述,狀態欄所顯示的信息共有5種,因此@id/status\_bar\_contents中的子控件分別用來顯示這5種信息。其中通知信息顯示在@id/notification\_icon\_area里,而其他四種信息則顯示在@id/system\_icon\_area之中。 - @id/notification\_icon\_area,一個LinearLayout。包含了兩個子控件分別是類型為StatusBarIconView的@id/moreIcon以及一個類型為IconMerger的@id/notificationIcons。IconMerger繼承自LinearLayout。通知信息的圖標都會以一個StatusBarIconView的形式存儲在IconMerger之中。而IconMeger和LinearLayout的區別在于,如果它在onLayout()的過程中發現會其內部所容納的StatusBarIconView的總寬度超過了它自身的寬度,則會設置@id/moreIcon為可見,使得用戶得知有部分通知圖標因為顯示空間不夠而被隱藏。makeStausBarView()會將@id/notificationIcons保存為成員變量mNotificationIcons。因此當新的通知到來時,只要將一個StatusBarIconView放置到mNotificationIcons即可顯示此通知的圖標了。 - @id/system\_icon\_area,也是一個LinearLayout。它容納了除通知信息的圖標以外的四種信息的顯示。在其中有負責顯示時間信息的@id/clock,負責顯示電量信息的@id/battery,負責信號信息顯示的@id/signal\_cluster以及負責容納系統狀態區圖標的一個LinearLayout——@id/statusIcons。其中@id/statusIcons會被保存到成員變量mStatusIcons中,當需要顯示某一個系統狀態圖標時,將圖標放置到mStatusIcons中即可。 注意 @id/system\_icon\_area的寬度定義為WRAP\_CONTENT,而@id/notification\_icon\_area的weight被設置為1。在這種情況下,@id/system\_icon\_area將在狀態欄右側根據其所顯示的圖標個數調整其尺寸。而@id/notification\_icon\_area則會占用狀態欄左側的剩余空間。這說明了一個問題:系統圖標區將優先占用狀態欄的空間進行信息的顯示。這也是IconMerger類以及@id/moreIcon存在的原因。 于是可以將圖7-3擴展為圖7-4。 :-: ![](http://img.blog.csdn.net/20150814134243958?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 圖 7 - 4狀態欄控件樹的結構3 另外,在@layout/status\_bar\_expanded之中有一個類型為NotificationRowLayout的控件@id/latestItems,并且會被makeStatusBarView()保存到mPile成員變量中。它位于下拉卷簾中,是通知信息列表的容器。 在分析控件樹結構的過程中發現了如下幾個重要的控件: - mStatusBarWindow,整個狀態欄的根控件。它包含了兩棵子控件樹,分別是常態下的狀態欄以及下拉卷簾。 - mStatusBarView,常態下的狀態欄。它所包含的三棵子控件樹分別對應了狀態欄的三種工作狀態——低辨識度模式、Ticker以及常態。這三棵控件樹會隨著這三種工作狀態的切換交替顯示。 - mNotificationIcons,繼承自LinearLayout的IconMerger控件的實例,負責容納通知圖標。當mNotificationIcons的寬度不足以容納所有通知圖標時,會將@id/moreIcon設置為可見以告知用戶存在未顯示的通知圖標。 - mTickerView,實現了當新通知到來時的動畫效果,使得用戶可以在無需下拉卷簾的情況下了解新通知的內容。 - mStatusIcons,一個LinearLayout,它是系統狀態圖標區,負責容納系統狀態圖標。 - mPile,一個NotificationRowLayout,它作為通知列表的容器被保存在下拉卷簾中。因此當一個通知信息除了需要將其圖標添加到mNotificationIcons以外,還需要將其詳細信息(標題、描述等)添加到mPile中,使得用戶在下來卷簾中可以看到它。 對狀態欄控件樹的結構分析至此便告一段落了。接下來將從通知信息以及系統狀態圖標兩個方面介紹狀態欄的工作原理。希望讀者能夠理解本節所介紹的幾個重要控件所在的位置以及其基本功能,這將使得后續內容的學習更加輕松。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看