ระบบการจัดการ SystemUIOverlayWindow

ระบบการจัดการ SystemUIOverlayWindow ทำให้คุณแสดงและ จัดการมุมมองใน SystemUIOverlayWindow ปัจจุบันหน้าต่างนี้ใช้สำหรับการดู ซึ่งรวมถึงตัวสลับผู้ใช้แบบเต็มหน้าจอ แผงการแจ้งเตือน และการล็อกปุ่ม หน้านี้จะไม่มีลักษณะดังนี้

  • สร้างข้อจำกัดเกี่ยวกับสิ่งที่ OEM สามารถเพิ่มในหน้าต่างได้
  • บังคับให้คุณใช้บทคัดย่อที่อธิบายไว้ในหน้านี้

ภาพรวม

คุณสามารถใช้ระบบการจัดการ SystemUIOverlayWindow เพื่อแสดงมุมมอง เช่น ประกาศทางกฎหมาย, ตัวสลับผู้ใช้แบบเต็มหน้าจอ, กล้องมองหลัง, การควบคุมระบบปรับอากาศ (HVAC) และการล็อกปุ่มกด ช่วงเวลานี้ อยู่นอกพื้นที่ของแอป ทำให้คุณสามารถควบคุมการเรียงลำดับ Z ของมุมมองได้ ทริกเกอร์เปิดเผย/จำกัด และการปรับแต่งโดยรวม ซึ่งรวมถึงตำแหน่งการดู ขนาด ความโปร่งใส และสี ในขณะเดียวกัน คุณไม่จำเป็นต้องกังวลเกี่ยวกับสถานะของแถบระบบหรือ ออบเจ็กต์ UI ของระบบที่ต้องซ่อนหรือแสดงเมื่อซ่อนหรือแสดงมุมมองที่เกี่ยวข้อง

ในการใช้ประโยชน์จาก SystemUIOverlayWindow คุณต้องสร้างตัวควบคุมการดูสำหรับมุมมองของคุณ สื่อกลาง ระบบจะส่งสื่อกลางไปยังตัวควบคุมสถานะส่วนกลางของหน้าต่าง สื่อกลางมุมมองเหล่านี้:

  • พิกัดระหว่างตัวควบคุมมุมมอง
  • ตรรกะทางธุรกิจภายในบริษัทสำหรับตัวควบคุมการดู

ดูผู้ควบคุมข้อมูล (ประสานงานโดยผู้ไกล่เกลี่ยการดู)

  • มุมมองของตัวเอง
  • สร้างตัวตั้งค่าซึ่ง OverlayViewsMediator สามารถแนบตรรกะทางธุรกิจได้
  • สร้างภาพเคลื่อนไหวที่เผยให้เห็นและซ่อนเร้นของมุมมองเหล่านั้น

SystemUIOverlayWindowบัญชีดูแลจัดการ ซึ่งเป็นคอมโพเนนต์ SystemUI ทำหน้าที่เป็นจุดแรกเข้าไปยัง เริ่มต้นและลงทะเบียนสื่อกลางด้วยตัวควบคุมสถานะส่วนกลาง ขณะที่ตัวควบคุมสถานะส่วนกลาง เชื่อมโยงกับตัวควบคุมมุมมองในลักษณะที่สื่อกลางสามารถเรียกใช้ตัวควบคุมการดูได้โดยตรง เพื่อแสดงและซ่อนมุมมองในหน้าต่าง

OverlayViewController

OverlayViewController รับผิดชอบข้อมูลพร็อพเพอร์ตี้ที่แสดงใน SystemUIOverlayWindow และควบคุมลักษณะการแสดงผล แสดงและซ่อนแล้ว และยังทำให้สามารถแนบ Listener ที่จำเป็นเพื่อให้ลิงก์ได้ กับตรรกะทางธุรกิจ

ลายเซ็นเมธอดที่สำคัญ

/**
 * Owns a {@link View} that is present in SystemUIOverlayWindow.
 */
public class OverlayViewController {

    /**
     * Shows content of {@link OverlayViewController}.
     *
     * Should be used to show view externally and in particular by {@link OverlayViewMediator}.
     */
    public final void start();

    /**
     * Hides content of {@link OverlayViewController}.
     *
     * Should be used to hide view externally and in particular by {@link OverlayViewMediator}.
     */
    public final void stop();

    /**
     * Inflate layout owned by controller.
     */
    public final void inflate(ViewGroup baseLayout);

    /**
     * Called once inflate finishes.
     */
    protected void onFinishInflate();

    /**
     * Returns {@code true} if layout owned by controller has been inflated.
     */
    public final boolean isInflated();

    /**
     * Subclasses should override this method to implement reveal animations and implement logic
     * specific to when the layout owned by the controller is shown.
     *
     * Should only be overridden by Superclass but not called by any {@link OverlayViewMediator}.
     */
    protected void showInternal();

    /**
     * Subclasses should override this method to implement conceal animations and implement logic
     * specific to when the layout owned by the controller is hidden.
     *
     * Should only be overridden by Superclass but not called by any {@link OverlayViewMediator}.
     */
    protected void hideInternal();

    /**
     * Provides access to layout owned by controller.
     */
    protected final View getLayout();

    /** Returns the {@link OverlayViewGlobalStateController}. */
    protected final OverlayViewGlobalStateController getOverlayViewGlobalStateController();

    /** Returns whether the view controlled by this controller is visible. */
    public final boolean isVisible();

    /**
     * Returns the ID of the focus area that should receive focus when this view is the
     * topmost view or {@link View#NO_ID} if there is no focus area.
     */
    @IdRes
    protected int getFocusAreaViewId();

    /** Returns whether the view controlled by this controller has rotary focus. */
    protected final boolean hasRotaryFocus();

    /**
     * Sets whether this view allows rotary focus. This should be set to {@code true} for the
     * topmost layer in the overlay window and {@code false} for the others.
     */
    public void setAllowRotaryFocus(boolean allowRotaryFocus);

    /**
     * Refreshes the rotary focus in this view if we are in rotary mode. If the view already has
     * rotary focus, it leaves the focus alone. Returns {@code true} if a new view was focused.
     */
    public boolean refreshRotaryFocusIfNeeded();

    /**
     * Returns {@code true} if heads up notifications should be displayed over this view.
     */
    protected boolean shouldShowHUN();

    /**
     * Returns {@code true} if navigation bar insets should be displayed over this view. Has no
     * effect if {@link #shouldFocusWindow} returns {@code false}.
     */
    protected boolean shouldShowNavigationBarInsets();

    /**
     * Returns {@code true} if status bar insets should be displayed over this view. Has no
     * effect if {@link #shouldFocusWindow} returns {@code false}.
     */
    protected boolean shouldShowStatusBarInsets();

    /**
     * Returns {@code true} if this view should be hidden during the occluded state.
     */
    protected boolean shouldShowWhenOccluded();

    /**
     * Returns {@code true} if the window should be focued when this view is visible. Note that
     * returning {@code false} here means that {@link #shouldShowStatusBarInsets} and
     * {@link #shouldShowNavigationBarInsets} will have no effect.
     */
    protected boolean shouldFocusWindow();

    /**
     * Returns {@code true} if the window should use stable insets. Using stable insets means that
     * even when system bars are temporarily not visible, inset from the system bars will still be
     * applied.
     *
     * NOTE: When system bars are hidden in transient mode, insets from them will not be applied
     * even when the system bars become visible. Setting the return value to {@true} here can
     * prevent the OverlayView from overlapping with the system bars when that happens.
     */
    protected boolean shouldUseStableInsets();

    /**
     * Returns the insets types to fit to the sysui overlay window when this
     * {@link OverlayViewController} is in the foreground.
     */
    @WindowInsets.Type.InsetsType
    protected int getInsetTypesToFit();

    /**
     * Optionally returns the sides of enabled system bar insets to fit to the sysui overlay window
     * when this {@link OverlayViewController} is in the foreground.
     *
     * For example, if the bottom and left system bars are enabled and this method returns
     * WindowInsets.Side.LEFT, then the inset from the bottom system bar will be ignored.
     *
     * NOTE: By default, this method returns {@link #INVALID_INSET_SIDE}, so insets to fit are
     * defined by {@link #getInsetTypesToFit()}, and not by this method, unless it is overridden
     * by subclasses.
     *
     * NOTE: {@link #NO_INSET_SIDE} signifies no insets from any system bars will be honored. Each
     * {@link OverlayViewController} can first take this value and add sides of the system bar
     * insets to honor to it.
     *
     * NOTE: If getInsetSidesToFit is overridden to return {@link WindowInsets.Side}, it always
     * takes precedence over {@link #getInsetTypesToFit()}. That is, the return value of {@link
     * #getInsetTypesToFit()} will be ignored.
     */
    @WindowInsets.Side.InsetsSide
    protected int getInsetSidesToFit();
}

OverlayPanelViewController

ตัวควบคุม OverlayPanelViewController ขยาย OverlayViewController และเพิ่มความสามารถในการลากภาพเคลื่อนไหวไปยังคลาสซูเปอร์คลาส

OverlayViewMediator

OverlayViewMediator ใช้ตรรกะทางธุรกิจที่เปิดเผยหรือซ่อนไว้ อินสแตนซ์ OverlayViewController หลายอินสแตนซ์ ดังนั้นในลักษณะดังกล่าวจะจัดการ การประสานงานระหว่างตัวควบคุมมุมมอง

/**
 * Controls when to show and hide {@link OverlayViewController}(s).
 */
public interface OverlayViewMediator {

    /**
     * Register listeners that could use ContentVisibilityAdjuster to show/hide content.
     *
     * Note that we do not unregister listeners because SystemUI components are expected to live
     * for the lifecycle of the device.
     */
    void registerListeners();

    /**
     * Allows for post-inflation callbacks and listeners to be set inside required {@link
     * OverlayViewController}(s).
     */
    void setupOverlayContentViewControllers();
}

SystemUIOverlayWindowManager

SystemUIOverlayWindowManager มีหน้าที่เป็นออบเจ็กต์ SystemUI ที่ให้บริการจุดแรกเข้าสำหรับ SystemUIOverlayWindow ระบบจัดการเพื่อเริ่มต้นและลงทะเบียน OverlayViewMediator อินสแตนซ์ที่มี OverlayViewGlobalStateController

วันที่ แสดงโฟลว์การดู
รูปที่ 1 SystemUIOverlayWindowManager

มุมมองโฆษณาซ้อนทับ GlobalStateController

OverlayViewGlobalStateController รับสายจาก OverlayViewController อินสแตนซ์เพื่อเปิดเผยหรือปิดบังตัวเอง ดังนั้นจึงยัง เก็บสถานะของสิ่งที่แสดงหรือซ่อนใน SystemUIOverlayWindow

คุณสามารถดูขั้นตอนการแสดงรายการได้ที่ด้านล่าง

วันที่ แสดงขั้นตอนการดู
รูปที่ 2 แสดงขั้นตอนการดู

ซ่อนโฟลว์มุมมอง

ดูภาพประกอบขั้นตอนการซ่อนได้ที่ด้านล่าง

วันที่ ซ่อนโฟลว์มุมมอง
รูปที่ 3 ซ่อนโฟลว์การดู

ลายเซ็นเมธอดแบบสาธารณะ

ลายเซ็นเมธอดสาธารณะมีการเข้ารหัสดังนี้

/**
 * This controller is responsible for the following:
 * <p><ul>
 * <li>Holds the global state for SystemUIOverlayWindow.
 * <li>Allows {@link SystemUIOverlayWindowManager} to register {@link OverlayViewMediator}(s).
 * <li>Enables {@link OverlayViewController)(s) to reveal/conceal themselves while respecting the
 * global state of SystemUIOverlayWindow.
 * </ul>
 */
@SysUISingleton
public class OverlayViewGlobalStateController {
    /**
     * Register {@link OverlayViewMediator} to use in SystemUIOverlayWindow.
     */
    public void registerMediator(OverlayViewMediator overlayViewMediator);

    /**
     * Show content in Overlay Window using {@link OverlayPanelViewController}.
     *
     * This calls {@link OverlayViewGlobalStateController#showView(OverlayViewController, Runnable)}
     * where the runnable is nullified since the actual showing of the panel is handled by the
     * controller itself.
     */
    public void showView(OverlayPanelViewController panelViewController);

    /**
     * Show content in Overlay Window using {@link OverlayViewController}.
     */
    public void showView(OverlayViewController viewController, @Nullable Runnable show);

    /**
     * Hide content in Overlay Window using {@link OverlayPanelViewController}.
     *
     * This calls {@link OverlayViewGlobalStateController#hideView(OverlayViewController, Runnable)}
     * where the runnable is nullified since the actual hiding of the panel is handled by the
     * controller itself.
     */
    public void hideView(OverlayPanelViewController panelViewController);

    /**
     * Hide content in Overlay Window using {@link OverlayViewController}.
     */
    public void hideView(OverlayViewController viewController, @Nullable Runnable hide);

    /** Returns {@code true} is the window is visible. */
    public boolean isWindowVisible();

    /**
     * Sets the {@link android.view.WindowManager.LayoutParams#FLAG_ALT_FOCUSABLE_IM} flag of the
     * sysui overlay window.
     */
    public void setWindowNeedsInput(boolean needsInput);

    /** Returns {@code true} if the window is focusable. */
    public boolean isWindowFocusable();

    /** Sets the focusable flag of the sysui overlawy window. */
    public void setWindowFocusable(boolean focusable);

    /** Inflates the view controlled by the given view controller. */
    public void inflateView(OverlayViewController viewController);

    /**
     * Return {@code true} if OverlayWindow is in a state where HUNs should be displayed above it.
     */
    public boolean shouldShowHUN();

    /**
     * Set the OverlayViewWindow to be in occluded or unoccluded state. When OverlayViewWindow is
     * occluded, all views mounted to it that are not configured to be shown during occlusion will
     * be hidden.
     */
    public void setOccluded(boolean occluded);
}

วิธีเพิ่มมุมมองไปยัง SysUIOverlayWindow

โปรดดูรายละเอียดที่ Codelab

ขั้นตอนที่ 1: เพิ่ม ViewStub ลงใน SysUIOverlayWindow

เพิ่มViewStub ไปยัง เลย์เอาต์หน้าต่าง

ขั้นตอนที่ 2: สร้าง OverlayViewController

ใช้ ViewStub ใหม่เพื่อสร้าง Injectable ใหม่ OverlayViewController

ขั้นตอนที่ 3: OverlayViewMediator

สร้าง Injectable ใหม่ OverlayViewMediator หรือใช้รายการที่มีอยู่ (ข้ามขั้นตอนที่ 4) และลงทะเบียน Listener เพื่อซ่อนหรือแสดง OverlayViewController

ขั้นตอนที่ 4: กำหนดค่า OverlayViewMediator ใหม่

เพิ่มOverlayViewMediatorใหม่ไปยัง OverlayWindowModule และ ถึง config_carSystemUIOverlayViewsMediator

ข้อควรระวัง

เมื่อ SysUIPrimaryWindow ครอบคลุมทั้งหน้าจอ องค์ประกอบใดก็ตามที่อยู่ใต้หน้าต่าง ไม่บันทึกเหตุการณ์การแตะ ดังนั้นเมื่อหน้าต่างครอบคลุมทั้งหน้าจอยกเว้นเนื้อหา ปล่อยพื้นที่ว่างไว้บางส่วน คุณสามารถเลือก ที่จะเบลอพื้นที่เชิงลบและแนบ Listener ได้ เพื่อปิดเนื้อหาในหน้าต่างนั้น