From b23c8c8e87972380cdf77e6bacbf9ae608ebcf40 Mon Sep 17 00:00:00 2001 From: Vadim Caen Date: Tue, 29 Mar 2022 13:32:12 +0200 Subject: [PATCH] Add View.findOnBackInvokedDispatcher To make it easier for developer to migrate away from KEYCODE_BACK without having to walk up the view hierachy in order to find an OnBackDispatcher, introduce findOnBackInvokedDispatcher. Bug: 227301455 Test: android.view.cts.OnBackInvokedDispatcherTest#testGetDispatcherOnView Change-Id: I7f3e76df596d306fa26d72df8115d5b15d7ac564 --- core/api/current.txt | 2 ++ core/java/android/view/View.java | 18 ++++++++++++++++++ core/java/android/view/ViewGroup.java | 22 ++++++++++++++++++++++ core/java/android/view/ViewParent.java | 17 +++++++++++++++++ core/java/android/view/ViewRootImpl.java | 7 +++++++ 5 files changed, 66 insertions(+) diff --git a/core/api/current.txt b/core/api/current.txt index 89b994189e925..0be6341f5b496 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -49642,6 +49642,7 @@ package android.view { method @CallSuper public void drawableHotspotChanged(float, float); method @CallSuper protected void drawableStateChanged(); method public android.view.View findFocus(); + method @Nullable public final android.window.OnBackInvokedDispatcher findOnBackInvokedDispatcher(); method public final T findViewById(@IdRes int); method public final T findViewWithTag(Object); method public void findViewsWithText(java.util.ArrayList, CharSequence, int); @@ -50819,6 +50820,7 @@ package android.view { method public void childHasTransientStateChanged(@NonNull android.view.View, boolean); method public void clearChildFocus(android.view.View); method public void createContextMenu(android.view.ContextMenu); + method @Nullable public default android.window.OnBackInvokedDispatcher findOnBackInvokedDispatcherForChild(@NonNull android.view.View, @NonNull android.view.View); method public android.view.View focusSearch(android.view.View, int); method public void focusableViewAvailable(android.view.View); method public boolean getChildVisibleRect(android.view.View, android.graphics.Rect, android.graphics.Point); diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 7d823b1c100d2..0fc365784e49e 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -162,6 +162,7 @@ import android.view.translation.ViewTranslationResponse; import android.widget.Checkable; import android.widget.FrameLayout; import android.widget.ScrollBarDrawable; +import android.window.OnBackInvokedDispatcher; import com.android.internal.R; import com.android.internal.util.ArrayUtils; @@ -12098,6 +12099,23 @@ public class View implements Drawable.Callback, KeyEvent.Callback, return null; } + + /** + * Walk up the View hierarchy to find the nearest {@link OnBackInvokedDispatcher}. + * + * @return The {@link OnBackInvokedDispatcher} from this or the nearest + * ancestor, or null if this view is both not attached and have no ancestor providing an + * {@link OnBackInvokedDispatcher}. + */ + @Nullable + public final OnBackInvokedDispatcher findOnBackInvokedDispatcher() { + ViewParent parent = getParent(); + if (parent != null) { + return parent.findOnBackInvokedDispatcherForChild(this, this); + } + return null; + } + /** * @hide Compute the insets that should be consumed by this view and the ones * that should propagate to those under it. diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index fe672327346a1..9f0ad1169a8e5 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -72,6 +72,7 @@ import android.view.inspector.InspectableProperty.EnumEntry; import android.view.translation.TranslationCapability; import android.view.translation.TranslationSpec.DataFormat; import android.view.translation.ViewTranslationRequest; +import android.window.OnBackInvokedDispatcher; import com.android.internal.R; @@ -9296,4 +9297,25 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager requests); } } + + /** + * Walk up the View hierarchy to find the nearest {@link OnBackInvokedDispatcher}. + * + * @return The {@link OnBackInvokedDispatcher} from this or the nearest + * ancestor, or null if the view is both not attached and have no ancestor providing an + * {@link OnBackInvokedDispatcher}. + * + * @param child The direct child of this view for which to find a dispatcher. + * @param requester The requester that will use the dispatcher. Can be the same as child. + */ + @Nullable + @Override + public OnBackInvokedDispatcher findOnBackInvokedDispatcherForChild(@NonNull View child, + @NonNull View requester) { + ViewParent parent = getParent(); + if (parent != null) { + return parent.findOnBackInvokedDispatcherForChild(this, requester); + } + return null; + } } diff --git a/core/java/android/view/ViewParent.java b/core/java/android/view/ViewParent.java index 128da314e9075..1020d2ef02be3 100644 --- a/core/java/android/view/ViewParent.java +++ b/core/java/android/view/ViewParent.java @@ -22,6 +22,7 @@ import android.graphics.Rect; import android.graphics.Region; import android.os.Bundle; import android.view.accessibility.AccessibilityEvent; +import android.window.OnBackInvokedDispatcher; /** * Defines the responsibilities for a class that will be a parent of a View. @@ -697,4 +698,20 @@ public interface ViewParent { getParent().onDescendantUnbufferedRequested(); } } + + /** + * Walk up the View hierarchy to find the nearest {@link OnBackInvokedDispatcher}. + * + * @return The {@link OnBackInvokedDispatcher} from this or the nearest + * ancestor, or null if the view is both not attached and have no ancestor providing an + * {@link OnBackInvokedDispatcher}. + * + * @param child The direct child of this view for which to find a dispatcher. + * @param requester The requester that will use the dispatcher. Can be the same as child. + */ + @Nullable + default OnBackInvokedDispatcher findOnBackInvokedDispatcherForChild(@NonNull View child, + @NonNull View requester) { + return null; + } } diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 931ae2748785c..9edf29d6b8c72 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -10736,6 +10736,13 @@ public final class ViewRootImpl implements ViewParent, return mOnBackInvokedDispatcher; } + @NonNull + @Override + public OnBackInvokedDispatcher findOnBackInvokedDispatcherForChild( + @NonNull View child, @NonNull View requester) { + return getOnBackInvokedDispatcher(); + } + /** * When this ViewRootImpl is added to the window manager, transfers the first * {@link OnBackInvokedCallback} to be called to the server.