【Android 個人理解(三)】從源碼剖析如何實現實現全屏效果

實現全屏的代碼:

// 全屏顯示
requestWindowFeature(Window.FEATURE_NO_TITLE);	
//turning off the title at the top of the screen. 
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
//the status bar will be hidden when an app window with this flag set is on the top layer. 

很明顯,第一句是關閉標題欄,第二句是關閉狀態欄。

但是,這個不夠深入,我們從源碼挨個分析。

一、requestWindowFeature()的源碼:

/**
     * Enable extended window features.  This is a convenience for calling
     * {@link android.view.Window#requestFeature getWindow().requestFeature()}.
     * 
     * @param featureId The desired feature as defined in
     *                  {@link android.view.Window}.
     * @return Returns true if the requested feature is supported and now
     *         enabled.
     * 
     * @see android.view.Window#requestFeature
     */
    public final boolean requestWindowFeature(int featureId) {
        return getWindow().requestFeature(featureId);
    }

由上我們知道,這個方法的作用直接等價於 getWindow().requestFeature(),是後者的方便調用的方式。其中的參數是Window類下的標記窗口特點的int標記,返回布爾值,如果爲true時,說明參數傳遞的特點是支持的,被實現的。

由此我們來看Window類下定義的窗口特點的種類:

/**
 * Abstract base class for a top-level window look and behavior policy.  An
 * instance of this class should be used as the top-level view added to the
 * window manager. It provides standard UI policies such as a background, title
 * area, default key processing, etc.
 *
 * <p>The only existing implementation of this abstract class is
 * android.policy.PhoneWindow, which you should instantiate when needing a
 * Window.  Eventually that class will be refactored and a factory method
 * added for creating Window instances without knowing about a particular
 * implementation.
 */
public abstract class Window {
    /** Flag for the "options panel" feature.  This is enabled by default. */
    public static final int FEATURE_OPTIONS_PANEL = 0;
    /** Flag for the "no title" feature, turning off the title at the top
     *  of the screen. */
    public static final int FEATURE_NO_TITLE = 1;
    /** Flag for the progress indicator feature */
    public static final int FEATURE_PROGRESS = 2;
    /** Flag for having an icon on the left side of the title bar */
    public static final int FEATURE_LEFT_ICON = 3;
    /** Flag for having an icon on the right side of the title bar */
    public static final int FEATURE_RIGHT_ICON = 4;
    /** Flag for indeterminate progress */
    public static final int FEATURE_INDETERMINATE_PROGRESS = 5;
    /** Flag for the context menu.  This is enabled by default. */
    public static final int FEATURE_CONTEXT_MENU = 6;
    /** Flag for custom title. You cannot combine this feature with other title features. */
    public static final int FEATURE_CUSTOM_TITLE = 7;
    /**
     * Flag for enabling the Action Bar.
     * This is enabled by default for some devices. The Action Bar
     * replaces the title bar and provides an alternate location
     * for an on-screen menu button on some devices.
     */
    public static final int FEATURE_ACTION_BAR = 8;
    /**
     * Flag for requesting an Action Bar that overlays window content.
     * Normally an Action Bar will sit in the space above window content, but if this
     * feature is requested along with {@link #FEATURE_ACTION_BAR} it will be layered over
     * the window content itself. This is useful if you would like your app to have more control
     * over how the Action Bar is displayed, such as letting application content scroll beneath
     * an Action Bar with a transparent background or otherwise displaying a transparent/translucent
     * Action Bar over application content.
     */
    public static final int FEATURE_ACTION_BAR_OVERLAY = 9;
    /**
     * Flag for specifying the behavior of action modes when an Action Bar is not present.
     * If overlay is enabled, the action mode UI will be allowed to cover existing window content.
     */
    public static final int FEATURE_ACTION_MODE_OVERLAY = 10;
    /** Flag for setting the progress bar's visibility to VISIBLE */
    public static final int PROGRESS_VISIBILITY_ON = -1;
    /** Flag for setting the progress bar's visibility to GONE */
    public static final int PROGRESS_VISIBILITY_OFF = -2;
    /** Flag for setting the progress bar's indeterminate mode on */
    public static final int PROGRESS_INDETERMINATE_ON = -3;
    /** Flag for setting the progress bar's indeterminate mode off */
    public static final int PROGRESS_INDETERMINATE_OFF = -4;
    /** Starting value for the (primary) progress */
    public static final int PROGRESS_START = 0;
    /** Ending value for the (primary) progress */
    public static final int PROGRESS_END = 10000;
    /** Lowest possible value for the secondary progress */
    public static final int PROGRESS_SECONDARY_START = 20000;
    /** Highest possible value for the secondary progress */
    public static final int PROGRESS_SECONDARY_END = 30000;
    
    /** The default features enabled */
    @SuppressWarnings({"PointlessBitwiseExpression"})
    protected static final int DEFAULT_FEATURES = (1 << FEATURE_OPTIONS_PANEL) |
            (1 << FEATURE_CONTEXT_MENU);

    /**
     * The ID that the main layout in the XML layout file should have.
     */
    public static final int ID_ANDROID_CONTENT = com.android.internal.R.id.content;
以上是Window類所有的公開的成員變量。

先說明Window類的概括:頂級窗口的外觀和行爲的抽象基類這個類的實例常常作爲頂層視圖添加到窗口管理器。它提供了標準UI方法,比如背景,標題區域等。
注意:唯一實現這個抽象類的類是android.policy.PhoneWindow,而且這個類也會被重寫和通過工廠模式來創造新的實例。一般我們直接調用getWindow獲得實例。

關於Window的實例,也屬於View對象,只是這個對象在最底層,超越了我們應用的界限,我們可以通過工具看在內存中某個應用的視圖樹進一步理解。事實上,整個Android系統也可以看作由許多應用組成。這裏不再對Window進行深究。

然後說明和全屏顯示相關的標記:

/** Flag for the "no title" feature, turning off the title at the top
     *  of the screen. */
    public static final int FEATURE_NO_TITLE = 1;

(PS:本來想介紹大部分的的,實在有點多!)

然後是requestFeature(),從字面意思上就知道獲得頂級窗口的外觀的特點。當然requestWindowFeature()同前。

二、setFlags(int flags, int mask)的源碼:

/**
     * Set the flags of the window, as per the
     * {@link WindowManager.LayoutParams WindowManager.LayoutParams}
     * flags.
     * 
     * <p>Note that some flags must be set before the window decoration is
     * created (by the first call to
     * {@link #setContentView(View, android.view.ViewGroup.LayoutParams)} or
     * {@link #getDecorView()}:
     * {@link WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN} and
     * {@link WindowManager.LayoutParams#FLAG_LAYOUT_INSET_DECOR}.  These
     * will be set for you based on the {@link android.R.attr#windowIsFloating}
     * attribute.
     *
     * @param flags The new window flags (see WindowManager.LayoutParams).
     * @param mask Which of the window flag bits to modify.
     */
    public void setFlags(int flags, int mask) {
        final WindowManager.LayoutParams attrs = getAttributes();
        attrs.flags = (attrs.flags&~mask) | (flags&mask);
        mForcedWindowFlags |= mask;
        if (mCallback != null) {
            mCallback.onWindowAttributesChanged(attrs);
        }
    }

也是flag即標誌,但爲什麼不是和上一句相同,因爲換了對象了。前面是Window類的,後者是WindowManager.LayoutParams的。WindowManager好理解,就是窗口管理器,管Window對象的,那麼LayoutParams:

             LayoutParams are used by views to tell their parents how they want to be laid out.

就是說,這個被用來告訴他們的父對象如何排布他們。比如告訴linnerLayout View如何在自己上面放置gallery對象,這裏告訴窗口管理器如何排布窗口是全屏還是可以溢出的等等。

注意:這個方法因爲設置的是頂級窗口的屬性,所以需要在一些其他設置佈局的方法前面調用,比如setContentView()。

兩個參數的意思:第一個是設置成什麼樣,第二個是設置哪裏(byte型)。

而flags具體與哪些,有分別代表什麼樣的窗口布置特點。在WindowManager類下的LayoutParams裏,這裏拿出和FLAG_FULLSCREEN有關的的源碼:

/** Window flag: allow window to extend outside of the screen. */
        public static final int FLAG_LAYOUT_NO_LIMITS   = 0x00000200;
        
        /** Window flag: Hide all screen decorations (e.g. status bar) while
         * this window is displayed.  This allows the window to use the entire
         * display space for itself -- the status bar will be hidden when
         * an app window with this flag set is on the top layer. */
        public static final int FLAG_FULLSCREEN      = 0x00000400;
        
        /** Window flag: Override {@link #FLAG_FULLSCREEN and force the
         *  screen decorations (such as status bar) to be shown. */
        public static final int FLAG_FORCE_NOT_FULLSCREEN   = 0x00000800;
        

一目瞭然,再具體的可以看setFlag()方法和requestFeature()的具體實現,來做進一步瞭解。

謝謝~



發佈了61 篇原創文章 · 獲贊 3 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章