Hệ thống quản lý SystemUIOverlayWindow

Hệ thống quản lý SystemUIOverlayWindow cung cấp cho bạn một cách để hiển thị và quản lý các thành phần hiển thị trong SystemUIOverlayWindow. Hiện tại, cửa sổ này đang được dùng cho các chế độ xem bao gồm trình chuyển đổi người dùng toàn màn hình, bảng thông báo và chế độ bảo vệ bàn phím. Trang này không:

  • Tạo các quy định hạn chế về nội dung mà nhà sản xuất thiết bị gốc (OEM) có thể thêm vào cửa sổ.
  • Buộc bạn phải sử dụng các khái niệm trừu tượng được mô tả trên trang này.

Tổng quan

Bạn có thể sử dụng Hệ thống quản lý SystemUIOverlayWindow để hiển thị các chế độ xem như thông báo pháp lý, trình chuyển đổi người dùng ở chế độ toàn màn hình, camera lùi, hệ thống điều khiển HVAC và tính năng bảo vệ bàn phím. Chiến dịch này cửa sổ nằm bên ngoài không gian ứng dụng và cho phép bạn kiểm soát thứ tự Z của chế độ xem. hiển thị/ẩn các điều kiện kích hoạt và tuỳ chỉnh tổng thể (bao gồm cả vị trí đặt chế độ xem, kích thước, độ trong suốt), và màu sắc. Đồng thời, bạn không cần lo lắng về trạng thái của các thanh hệ thống hoặc các đối tượng Giao diện người dùng hệ thống khác cần ẩn hoặc hiển thị khi thành phần hiển thị tương ứng của chúng bị ẩn hoặc hiển thị.

Để tận dụng SystemUIOverlayWindow, hãy tạo bộ điều khiển chế độ xem cho chế độ xem trung gian hoà giải. Các bên hoà giải được chuyển đến trình kiểm soát trạng thái chung của cửa sổ. Các trình dàn xếp chế độ xem này:

  • Phối hợp giữa các bộ điều khiển chế độ xem.
  • Logic nghiệp vụ cho nội bộ cho bộ điều khiển chế độ xem.

Xem các đơn vị kiểm soát (được phối hợp bởi các bên dàn xếp chế độ xem):

  • Sở hữu chế độ xem của nó.
  • Tạo các phương thức setter thông qua đó OverlayViewsMediator có thể đính kèm logic nghiệp vụ.
  • Tạo ảnh động hiển thị và ẩn ảnh trong khung hiển thị.

SystemUIOverlayWindowTrình quản lý, một thành phần SystemUI,đóng vai trò là điểm truy cập đến khởi tạo và đăng ký đơn vị hoà giải với đơn vị kiểm soát trạng thái chung trong khi đơn vị kiểm soát trạng thái chung liên kết với các đơn vị kiểm soát chế độ xem theo cách mà các bên dàn xếp có thể gọi trực tiếp các đơn vị kiểm soát chế độ xem để hiện và ẩn khung hiển thị trong cửa sổ.

OverlayViewController

OverlayViewController chịu trách nhiệm về khung hiển thị xuất hiện trong SystemUIOverlayWindow và kiểm soát cách khung hiển thị đó được tiết lộ và ẩn giấu. Phương thức này cũng cho phép đính kèm trình nghe bắt buộc để có thể liên kết sang logic kinh doanh.

Chữ ký phương thức quan trọng

/**
 * 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

Bộ điều khiển OverlayPanelViewController mở rộng OverlayViewController và cung cấp thêm khả năng tạo ảnh động kéo cho lớp cấp cao.

OverlayViewMediator

OverlayViewMediator chứa logic kinh doanh hiển thị hoặc ẩn nhiều thực thể OverlayViewController, vì vậy, theo một cách nào đó, lớp này cũng quản lý việc điều phối giữa các trình điều khiển thành phần hiển thị.

/**
 * 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();
}

Hệ thốngUIOverlayWindowManager

SystemUIOverlayWindowManager chịu trách nhiệm là đối tượng SystemUI phân phát điểm truy cập cho Hệ thống quản lý SystemUIOverlayWindow để khởi tạo và đăng ký các thực thể OverlayViewMediator bằng OverlayViewGlobalStateController.

Hiện luồng chế độ xem
Hình 1. SystemUIOverlayWindowManager

OverlayViewGlobalStateController

OverlayViewGlobalStateController nhận cuộc gọi từ OverlayViewController thực thể để tiết lộ hoặc che giấu bản thân. Do đó, tính năng này cũng giữ trạng thái của nội dung hiện hoặc ẩn trong SystemUIOverlayWindow.

Luồng xem chương trình được minh hoạ dưới đây:

Hiển thị luồng xem
Hình 2. Hiển thị luồng xem

Ẩn luồng xem

Quy trình ẩn khung hiển thị được minh hoạ bên dưới:

Ẩn luồng xem
Hình 3. Ẩn luồng thành phần hiển thị

Chữ ký phương thức công khai

Chữ ký phương thức công khai được mã hoá như sau:

​/**
 * 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);
}

Cách thêm thành phần hiển thị vào SysUIOverlayWindow

Để biết thông tin chi tiết, hãy xem Lớp học lập trình.

Bước 1: Thêm ViewStub vào SysUIOverlayWindow

Thêm ViewStub vào bố cục cửa sổ.

Bước 2: Tạo OverlayViewController

Sử dụng ViewStub mới để tạo một OverlayViewController mới có thể chèn.

Bước 3: OverlayViewMediator

Tạo một tệp chèn mới OverlayViewMediator hoặc sử dụng một kênh hiện có (bỏ qua Bước 4) và đăng ký trình nghe để ẩn hoặc hiện OverlayViewController.

Bước 4: Định cấu hình OverlayViewMediator mới

Thêm OverlayViewMediator mới của bạn vào OverlayWindowModule và lên config_carSystemUIOverlayViewsMediator.

Chú ý

Khi SysUIPrimaryWindow bao phủ toàn bộ màn hình, mọi phần tử trong cửa sổ sẽ không đăng ký sự kiện chạm. Do đó, khi cửa sổ bao phủ toàn bộ màn hình nhưng nội dung của cửa sổ để lại một số không gian âm, bạn có thể chọn làm mờ không gian âm và đính kèm trình nghe vào không gian đó để loại bỏ nội dung trong cửa sổ.