سیستم مدیریت پنجره SystemUIOverlay

سیستم مدیریت SystemUIOverlayWindow راهی برای نمایش و مدیریت نماها در SystemUIOverlayWindow فراهم می کند. در حال حاضر، این پنجره برای نماهایی از جمله تغییر دهنده کاربر تمام صفحه، پانل اعلان و محافظ صفحه کلید استفاده می شود. این مقاله انجام نمی دهد:

  • محدودیت هایی در مورد آنچه OEM می تواند به پنجره اضافه کند ایجاد کنید.
  • شما را مجبور به اتخاذ انتزاعات شرح داده شده در این سند می کند.

بررسی اجمالی

می‌توانید از سیستم مدیریت SystemUIOverlayWindow برای نشان دادن نماهایی مانند اعلامیه قانونی، تعویض‌کننده کاربر تمام‌صفحه، دوربین دید عقب، کنترل‌های HVAC و محافظ صفحه‌کلید استفاده کنید. این پنجره خارج از فضای برنامه قرار دارد و به شما امکان کنترل بر ترتیب Z-نما، آشکار/پنهان کردن محرک‌ها و سفارشی‌سازی‌های کلی از جمله محل نمایش، اندازه، شفافیت و رنگ را می‌دهد. در عین حال، لازم نیست نگران وضعیت نوارهای سیستم یا سایر اشیاء رابط کاربری سیستم باشید که باید پنهان یا نمایش داده شوند، وقتی نمای مربوطه آنها پنهان یا نشان داده می شود.

برای استفاده از SystemUIOverlayWindow ، کنترل‌کننده‌های مشاهده را برای واسطه‌های مشاهده خود ایجاد می‌کنید. میانجی‌ها به کنترل‌کننده حالت جهانی پنجره منتقل می‌شوند. اینها واسطه ها را می بینند:

  • هماهنگی بین نمایش کنترلرها
  • منطق تجاری خانه برای کنترل‌کننده‌های مشاهده.

مشاهده کنترلرها (هماهنگ شده توسط واسطه های مشاهده):

  • صاحب دیدگاهش
  • تنظیم کننده هایی ایجاد کنید که از طریق آنها OverlayViewsMediator بتواند منطق تجاری را ضمیمه کند.
  • انیمیشن های آشکار و پنهان نمای آنها را ایجاد کنید.

SystemUIOverlayWindow Manager، یک مؤلفه SystemUI، به عنوان نقطه ورودی برای مقداردهی اولیه و ثبت میانجی‌ها با کنترل‌کننده حالت جهانی عمل می‌کند، در حالی که کنترل‌کننده حالت جهانی به کنترل‌کننده‌های view متصل می‌شود به گونه‌ای که واسطه‌ها می‌توانند مستقیماً کنترل‌کننده‌های view را فراخوانی کنند تا نماها را نشان داده و پنهان کنند. پنجره.

OverlayViewController

OverlayViewController مسئول نمای نمایش داده شده در SystemUIOverlayWindow است و نحوه آشکار و پنهان شدن نما را کنترل می کند. همچنین شنوندگان مورد نیاز را قادر می سازد تا به منطق تجاری متصل شوند.

امضاهای روش مهم

/**
 * 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 (های) را آشکار یا پنهان می کند، از این رو، به نحوی هماهنگی بین کنترل کننده های view را نیز مدیریت می کند.

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

OverlayViewGlobalStateController

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 جدید برای ایجاد یک OverlayViewController جدید تزریقی استفاده کنید.

مرحله 3: OverlayViewMediator

یک OverlayViewMediator تزریقی جدید ایجاد کنید یا از یک موجود استفاده کنید (از مرحله 4 صرفنظر کنید) و شنوندگان را برای پنهان کردن یا نمایش OverlayViewController جدید ثبت کنید.

مرحله 4: OverlayViewMediator جدید را پیکربندی کنید

OverlayViewMediator جدید خود را به OverlayWindowModule و به config_carSystemUIOverlayViewsMediator اضافه کنید.

هشدارها

توجه داشته باشید که وقتی SysUIPrimaryWindow کل صفحه را پوشش می دهد، هیچ عنصری در زیر پنجره رویدادهای لمسی را ثبت نمی کند. بنابراین، هنگامی که پنجره کل صفحه را می پوشاند اما محتویات آن مقداری فضای منفی باقی می گذارد، می توانید انتخاب کنید که فضای منفی را محو کنید و شنوندگان را به آن فضا متصل کنید تا محتوا را در پنجره حذف کنید.