summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Jacqueline Bronger <bronger@google.com> 2022-05-02 08:41:46 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2022-05-02 08:41:46 +0000
commita512a9b95584576d71bed77c34596d5267fcbf28 (patch)
tree2eabd9c37391e34a7068ef85022fad444f8ebb1a
parent936456aebcd67580ea6016e162d9cf2a8cfecabe (diff)
parent442ba6ca2c88fa49a0a13eea400ef256f565869c (diff)
Merge changes from topics "presubmit-am-5a31146ec7864d04ab14351725610831", "presubmit-am-bcec5630c20a4c7ca37a5694c6a3b126" into tm-dev
* changes: TV:Fade out PiP content during aspect ratio change Reorder PiP menu buttons. Improve TV PiP menu buttons
-rw-r--r--libs/WindowManager/Shell/res/animator/tv_pip_menu_action_button_animator.xml53
-rw-r--r--libs/WindowManager/Shell/res/layout/tv_pip_menu.xml29
-rw-r--r--libs/WindowManager/Shell/res/layout/tv_pip_menu_action_button.xml11
-rw-r--r--libs/WindowManager/Shell/res/values-tvdpi/dimen.xml2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuActionButton.java12
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuController.java12
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuView.java257
8 files changed, 322 insertions, 56 deletions
diff --git a/libs/WindowManager/Shell/res/animator/tv_pip_menu_action_button_animator.xml b/libs/WindowManager/Shell/res/animator/tv_pip_menu_action_button_animator.xml
new file mode 100644
index 000000000000..7475abac4695
--- /dev/null
+++ b/libs/WindowManager/Shell/res/animator/tv_pip_menu_action_button_animator.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2022 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<selector
+ xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item android:state_focused="true">
+ <set>
+ <objectAnimator
+ android:duration="200"
+ android:propertyName="scaleX"
+ android:valueFrom="1.0"
+ android:valueTo="1.1"
+ android:valueType="floatType"/>
+ <objectAnimator
+ android:duration="200"
+ android:propertyName="scaleY"
+ android:valueFrom="1.0"
+ android:valueTo="1.1"
+ android:valueType="floatType"/>
+ </set>
+ </item>
+ <item android:state_focused="false">
+ <set>
+ <objectAnimator
+ android:duration="200"
+ android:propertyName="scaleX"
+ android:valueFrom="1.1"
+ android:valueTo="1.0"
+ android:valueType="floatType"/>
+ <objectAnimator
+ android:duration="200"
+ android:propertyName="scaleY"
+ android:valueFrom="1.1"
+ android:valueTo="1.0"
+ android:valueType="floatType"/>
+ </set>
+ </item>
+</selector> \ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/layout/tv_pip_menu.xml b/libs/WindowManager/Shell/res/layout/tv_pip_menu.xml
index dbd5a9b370ab..7a3ee23d8cdc 100644
--- a/libs/WindowManager/Shell/res/layout/tv_pip_menu.xml
+++ b/libs/WindowManager/Shell/res/layout/tv_pip_menu.xml
@@ -21,10 +21,13 @@
android:layout_height="match_parent"
android:gravity="center|top">
+ <!-- Matches the PiP app content -->
<View
android:id="@+id/tv_pip"
android:layout_width="0dp"
android:layout_height="0dp"
+ android:alpha="0"
+ android:background="@color/tv_pip_menu_background"
android:layout_marginTop="@dimen/pip_menu_outer_space"
android:layout_marginStart="@dimen/pip_menu_outer_space"
android:layout_marginEnd="@dimen/pip_menu_outer_space"/>
@@ -33,7 +36,6 @@
android:id="@+id/tv_pip_menu_scroll"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:gravity="center_horizontal"
android:layout_alignTop="@+id/tv_pip"
android:layout_alignStart="@+id/tv_pip"
android:layout_alignEnd="@+id/tv_pip"
@@ -49,15 +51,12 @@
android:layout_alignStart="@+id/tv_pip"
android:layout_alignEnd="@+id/tv_pip"
android:layout_alignBottom="@+id/tv_pip"
- android:gravity="center_vertical"
android:scrollbars="none">
<LinearLayout
android:id="@+id/tv_pip_menu_action_buttons"
android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:gravity="center"
- android:layout_gravity="center"
+ android:layout_height="wrap_content"
android:orientation="horizontal"
android:alpha="0">
@@ -73,11 +72,20 @@
android:text="@string/pip_fullscreen" />
<com.android.wm.shell.pip.tv.TvPipMenuActionButton
+ android:id="@+id/tv_pip_menu_close_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/pip_ic_close_white"
+ android:text="@string/pip_close" />
+
+ <!-- More TvPipMenuActionButtons may be added here at runtime. -->
+
+ <com.android.wm.shell.pip.tv.TvPipMenuActionButton
android:id="@+id/tv_pip_menu_move_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/pip_ic_move_white"
- android:text="@String/pip_move" />
+ android:text="@string/pip_move" />
<com.android.wm.shell.pip.tv.TvPipMenuActionButton
android:id="@+id/tv_pip_menu_expand_button"
@@ -87,15 +95,6 @@
android:visibility="gone"
android:text="@string/pip_collapse" />
- <com.android.wm.shell.pip.tv.TvPipMenuActionButton
- android:id="@+id/tv_pip_menu_close_button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@drawable/pip_ic_close_white"
- android:text="@string/pip_close" />
-
- <!-- More TvPipMenuActionButtons may be added here at runtime. -->
-
<Space
android:layout_width="@dimen/pip_menu_button_wrapper_margin"
android:layout_height="@dimen/pip_menu_button_wrapper_margin"/>
diff --git a/libs/WindowManager/Shell/res/layout/tv_pip_menu_action_button.xml b/libs/WindowManager/Shell/res/layout/tv_pip_menu_action_button.xml
index a86a14525022..db96d8de4094 100644
--- a/libs/WindowManager/Shell/res/layout/tv_pip_menu_action_button.xml
+++ b/libs/WindowManager/Shell/res/layout/tv_pip_menu_action_button.xml
@@ -20,10 +20,17 @@
android:id="@+id/button"
android:layout_width="@dimen/pip_menu_button_size"
android:layout_height="@dimen/pip_menu_button_size"
- android:layout_margin="@dimen/pip_menu_button_margin"
- android:background="@drawable/tv_pip_button_bg"
+ android:padding="@dimen/pip_menu_button_margin"
+ android:stateListAnimator="@animator/tv_pip_menu_action_button_animator"
android:focusable="true">
+ <View android:id="@+id/background"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_gravity="center"
+ android:duplicateParentState="true"
+ android:background="@drawable/tv_pip_button_bg"/>
+
<ImageView android:id="@+id/icon"
android:layout_width="@dimen/pip_menu_icon_size"
android:layout_height="@dimen/pip_menu_icon_size"
diff --git a/libs/WindowManager/Shell/res/values-tvdpi/dimen.xml b/libs/WindowManager/Shell/res/values-tvdpi/dimen.xml
index 776b18ecc01b..02e726fbc3bf 100644
--- a/libs/WindowManager/Shell/res/values-tvdpi/dimen.xml
+++ b/libs/WindowManager/Shell/res/values-tvdpi/dimen.xml
@@ -16,7 +16,7 @@
-->
<resources>
<!-- The dimensions to user for picture-in-picture action buttons. -->
- <dimen name="pip_menu_button_size">40dp</dimen>
+ <dimen name="pip_menu_button_size">48dp</dimen>
<dimen name="pip_menu_button_radius">20dp</dimen>
<dimen name="pip_menu_icon_size">20dp</dimen>
<dimen name="pip_menu_button_margin">4dp</dimen>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java
index 7f155cae4ff5..8326588bbbad 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java
@@ -384,6 +384,7 @@ public class TvPipController implements PipTransitionController.PipTransitionCal
animationDuration, rect -> {
mTvPipMenuController.updateExpansionState();
});
+ mTvPipMenuController.onPipTransitionStarted(bounds);
}
/**
@@ -573,6 +574,7 @@ public class TvPipController implements PipTransitionController.PipTransitionCal
"%s: onExpandedAspectRatioChanged: %f", TAG, ratio);
mTvPipBoundsState.setDesiredTvExpandedAspectRatio(ratio, false);
+ mTvPipMenuController.updateExpansionState();
// 1) PiP is expanded and only aspect ratio changed, but wasn't disabled
// --> update bounds, but don't toggle
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuActionButton.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuActionButton.java
index abbc614b4b4f..a09aab666a31 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuActionButton.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuActionButton.java
@@ -33,6 +33,7 @@ import com.android.wm.shell.R;
*/
public class TvPipMenuActionButton extends RelativeLayout implements View.OnClickListener {
private final ImageView mIconImageView;
+ private final View mButtonBackgroundView;
private final View mButtonView;
private OnClickListener mOnClickListener;
@@ -57,6 +58,7 @@ public class TvPipMenuActionButton extends RelativeLayout implements View.OnClic
mIconImageView = findViewById(R.id.icon);
mButtonView = findViewById(R.id.button);
+ mButtonBackgroundView = findViewById(R.id.background);
final int[] values = new int[]{android.R.attr.src, android.R.attr.text};
final TypedArray typedArray = context.obtainStyledAttributes(attrs, values, defStyleAttr,
@@ -132,9 +134,17 @@ public class TvPipMenuActionButton extends RelativeLayout implements View.OnClic
getResources().getColorStateList(
isCustomCloseAction ? R.color.tv_pip_menu_close_icon
: R.color.tv_pip_menu_icon));
- mButtonView.setBackgroundTintList(getResources()
+ mButtonBackgroundView.setBackgroundTintList(getResources()
.getColorStateList(isCustomCloseAction ? R.color.tv_pip_menu_close_icon_bg
: R.color.tv_pip_menu_icon_bg));
}
+ @Override
+ public String toString() {
+ if (mButtonView.getContentDescription() == null) {
+ return TvPipMenuActionButton.class.getSimpleName();
+ }
+ return mButtonView.getContentDescription().toString();
+ }
+
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuController.java
index bbd21b4940a5..132c04481bce 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuController.java
@@ -199,6 +199,9 @@ public class TvPipMenuController implements PipMenuController, TvPipMenuView.Lis
void notifyPipAnimating(boolean animating) {
mPipMenuView.setEduTextActive(!animating);
+ if (!animating) {
+ mPipMenuView.onPipTransitionFinished();
+ }
}
void showMovementMenuOnly() {
@@ -235,6 +238,13 @@ public class TvPipMenuController implements PipMenuController, TvPipMenuView.Lis
} else {
mPipMenuView.showButtonsMenu();
}
+ mPipMenuView.updateBounds(mTvPipBoundsState.getBounds());
+ }
+
+ void onPipTransitionStarted(Rect finishBounds) {
+ if (mPipMenuView != null) {
+ mPipMenuView.onPipTransitionStarted(finishBounds);
+ }
}
private void maybeCloseEduText() {
@@ -559,7 +569,7 @@ public class TvPipMenuController implements PipMenuController, TvPipMenuView.Lis
menuBounds.height()));
if (mPipMenuView != null) {
- mPipMenuView.updateLayout(destinationBounds);
+ mPipMenuView.updateBounds(destinationBounds);
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuView.java
index 3161b02d1545..868e45655ba3 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuView.java
@@ -44,8 +44,10 @@ import android.view.View;
import android.view.ViewGroup;
import android.view.ViewRootImpl;
import android.widget.FrameLayout;
+import android.widget.HorizontalScrollView;
import android.widget.ImageView;
import android.widget.LinearLayout;
+import android.widget.ScrollView;
import android.widget.TextView;
import androidx.annotation.NonNull;
@@ -69,6 +71,8 @@ public class TvPipMenuView extends FrameLayout implements View.OnClickListener {
private static final String TAG = "TvPipMenuView";
private static final boolean DEBUG = TvPipController.DEBUG;
+ private static final int FIRST_CUSTOM_ACTION_POSITION = 3;
+
@Nullable
private Listener mListener;
@@ -90,15 +94,21 @@ public class TvPipMenuView extends FrameLayout implements View.OnClickListener {
private final ImageView mArrowDown;
private final ImageView mArrowLeft;
- private final ViewGroup mScrollView;
- private final ViewGroup mHorizontalScrollView;
+ private final ScrollView mScrollView;
+ private final HorizontalScrollView mHorizontalScrollView;
+ private View mFocusedButton;
private Rect mCurrentPipBounds;
+ private boolean mMoveMenuIsVisible;
+ private boolean mButtonMenuIsVisible;
private final TvPipMenuActionButton mExpandButton;
private final TvPipMenuActionButton mCloseButton;
+ private boolean mSwitchingOrientation;
+
private final int mPipMenuFadeAnimationDuration;
+ private final int mResizeAnimationDuration;
public TvPipMenuView(@NonNull Context context) {
this(context, null);
@@ -146,8 +156,11 @@ public class TvPipMenuView extends FrameLayout implements View.OnClickListener {
mEduTextView = findViewById(R.id.tv_pip_menu_edu_text);
mEduTextContainerView = findViewById(R.id.tv_pip_menu_edu_text_container);
+ mResizeAnimationDuration = context.getResources().getInteger(
+ R.integer.config_pipResizeAnimationDuration);
mPipMenuFadeAnimationDuration = context.getResources()
.getInteger(R.integer.pip_menu_fade_animation_duration);
+
mPipMenuOuterSpace = context.getResources()
.getDimensionPixelSize(R.dimen.pip_menu_outer_space);
mPipMenuBorderWidth = context.getResources()
@@ -203,43 +216,179 @@ public class TvPipMenuView extends FrameLayout implements View.OnClickListener {
heightAnimation.start();
}
- void updateLayout(Rect updatedPipBounds) {
+ void onPipTransitionStarted(Rect finishBounds) {
+ // Fade out content by fading in view on top.
+ if (mCurrentPipBounds != null && finishBounds != null) {
+ boolean ratioChanged = PipUtils.aspectRatioChanged(
+ mCurrentPipBounds.width() / (float) mCurrentPipBounds.height(),
+ finishBounds.width() / (float) finishBounds.height());
+ if (ratioChanged) {
+ mPipView.animate()
+ .alpha(1f)
+ .setInterpolator(TvPipInterpolators.EXIT)
+ .setDuration(mResizeAnimationDuration / 2)
+ .start();
+ }
+ }
+
+ // Update buttons.
+ final boolean vertical = finishBounds.height() > finishBounds.width();
+ final boolean orientationChanged =
+ vertical != (mActionButtonsContainer.getOrientation() == LinearLayout.VERTICAL);
+ ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+ "%s: onPipTransitionStarted(), orientation changed %b", TAG, orientationChanged);
+ if (!orientationChanged) {
+ return;
+ }
+
+ if (mButtonMenuIsVisible) {
+ mSwitchingOrientation = true;
+ mActionButtonsContainer.animate()
+ .alpha(0)
+ .setInterpolator(TvPipInterpolators.EXIT)
+ .setDuration(mResizeAnimationDuration / 2)
+ .withEndAction(() -> {
+ changeButtonScrollOrientation(finishBounds);
+ updateButtonGravity(finishBounds);
+ // Only make buttons visible again in onPipTransitionFinished to keep in
+ // sync with PiP content alpha animation.
+ });
+ } else {
+ changeButtonScrollOrientation(finishBounds);
+ updateButtonGravity(finishBounds);
+ }
+ }
+
+ void onPipTransitionFinished() {
ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
- "%s: update menu layout: %s", TAG, updatedPipBounds.toShortString());
+ "%s: onPipTransitionFinished()", TAG);
- boolean previouslyVertical =
- mCurrentPipBounds != null && mCurrentPipBounds.height() > mCurrentPipBounds.width();
- boolean vertical = updatedPipBounds.height() > updatedPipBounds.width();
+ // Fade in content by fading out view on top.
+ mPipView.animate()
+ .alpha(0f)
+ .setDuration(mResizeAnimationDuration / 2)
+ .setInterpolator(TvPipInterpolators.ENTER)
+ .start();
+
+ // Update buttons.
+ if (mSwitchingOrientation) {
+ mActionButtonsContainer.animate()
+ .alpha(1)
+ .setInterpolator(TvPipInterpolators.ENTER)
+ .setDuration(mResizeAnimationDuration / 2);
+ } else {
+ refocusPreviousButton();
+ }
+ mSwitchingOrientation = false;
+ }
- mCurrentPipBounds = updatedPipBounds;
+ /**
+ * Also updates the button gravity.
+ */
+ void updateBounds(Rect updatedBounds) {
+ ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+ "%s: updateLayout, width: %s, height: %s", TAG, updatedBounds.width(),
+ updatedBounds.height());
+ mCurrentPipBounds = updatedBounds;
+ if (!mSwitchingOrientation) {
+ updateButtonGravity(mCurrentPipBounds);
+ }
updatePipFrameBounds();
+ }
- if (previouslyVertical == vertical) {
- if (DEBUG) {
- ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
- "%s: no update for menu layout", TAG);
+ private void changeButtonScrollOrientation(Rect bounds) {
+ final boolean vertical = bounds.height() > bounds.width();
+
+ final ViewGroup oldScrollView = vertical ? mHorizontalScrollView : mScrollView;
+ final ViewGroup newScrollView = vertical ? mScrollView : mHorizontalScrollView;
+
+ if (oldScrollView.getChildCount() == 1) {
+ ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+ "%s: orientation changed", TAG);
+ oldScrollView.removeView(mActionButtonsContainer);
+ oldScrollView.setVisibility(GONE);
+ mActionButtonsContainer.setOrientation(vertical ? LinearLayout.VERTICAL
+ : LinearLayout.HORIZONTAL);
+ newScrollView.addView(mActionButtonsContainer);
+ newScrollView.setVisibility(VISIBLE);
+ if (mFocusedButton != null) {
+ mFocusedButton.requestFocus();
}
+ }
+ }
+
+ /**
+ * Change button gravity based on new dimensions
+ */
+ private void updateButtonGravity(Rect bounds) {
+ final boolean vertical = bounds.height() > bounds.width();
+ // Use Math.max since the possible orientation change might not have been applied yet.
+ final int buttonsSize = Math.max(mActionButtonsContainer.getHeight(),
+ mActionButtonsContainer.getWidth());
+
+ ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+ "%s: buttons container width: %s, height: %s", TAG,
+ mActionButtonsContainer.getWidth(), mActionButtonsContainer.getHeight());
+
+ final boolean buttonsFit =
+ vertical ? buttonsSize < bounds.height()
+ : buttonsSize < bounds.width();
+ final int buttonGravity = buttonsFit ? Gravity.CENTER
+ : (vertical ? Gravity.CENTER_HORIZONTAL : Gravity.CENTER_VERTICAL);
+
+ final LayoutParams params = (LayoutParams) mActionButtonsContainer.getLayoutParams();
+ params.gravity = buttonGravity;
+ mActionButtonsContainer.setLayoutParams(params);
+
+ ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+ "%s: vertical: %b, buttonsFit: %b, gravity: %s", TAG, vertical, buttonsFit,
+ Gravity.toString(buttonGravity));
+ }
+
+ private void refocusPreviousButton() {
+ if (mMoveMenuIsVisible || mCurrentPipBounds == null || mFocusedButton == null) {
return;
+ }
+ final boolean vertical = mCurrentPipBounds.height() > mCurrentPipBounds.width();
+
+ if (!mFocusedButton.hasFocus()) {
+ ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+ "%s: request focus from: %s", TAG, mFocusedButton);
+ mFocusedButton.requestFocus();
} else {
- if (DEBUG) {
- ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
- "%s: change menu layout to vertical: %b", TAG, vertical);
- }
+ ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+ "%s: already focused: %s", TAG, mFocusedButton);
}
+ // Do we need to scroll?
+ final Rect buttonBounds = new Rect();
+ final Rect scrollBounds = new Rect();
if (vertical) {
- mHorizontalScrollView.removeView(mActionButtonsContainer);
- mScrollView.addView(mActionButtonsContainer);
+ mScrollView.getDrawingRect(scrollBounds);
} else {
- mScrollView.removeView(mActionButtonsContainer);
- mHorizontalScrollView.addView(mActionButtonsContainer);
+ mHorizontalScrollView.getDrawingRect(scrollBounds);
+ }
+ mFocusedButton.getHitRect(buttonBounds);
+
+ if (scrollBounds.contains(buttonBounds)) {
+ // Button is already completely visible, don't scroll
+ ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+ "%s: not scrolling", TAG);
+ return;
}
- mActionButtonsContainer.setOrientation(vertical ? LinearLayout.VERTICAL
- : LinearLayout.HORIZONTAL);
- mScrollView.setVisibility(vertical ? VISIBLE : GONE);
- mHorizontalScrollView.setVisibility(vertical ? GONE : VISIBLE);
+ // Scrolling so the button is visible to the user.
+ ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+ "%s: scrolling to focused button", TAG);
+
+ if (vertical) {
+ mScrollView.smoothScrollTo((int) mFocusedButton.getX(),
+ (int) mFocusedButton.getY());
+ } else {
+ mHorizontalScrollView.smoothScrollTo((int) mFocusedButton.getX(),
+ (int) mFocusedButton.getY());
+ }
}
Rect getPipMenuContainerBounds(Rect pipBounds) {
@@ -300,6 +449,8 @@ public class TvPipMenuView extends FrameLayout implements View.OnClickListener {
if (DEBUG) {
ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, "%s: showMoveMenu()", TAG);
}
+ mButtonMenuIsVisible = false;
+ mMoveMenuIsVisible = true;
showButtonsMenu(false);
showMovementHints(gravity);
setFrameHighlighted(true);
@@ -310,19 +461,34 @@ public class TvPipMenuView extends FrameLayout implements View.OnClickListener {
ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
"%s: showButtonsMenu()", TAG);
}
+
+ mButtonMenuIsVisible = true;
+ mMoveMenuIsVisible = false;
showButtonsMenu(true);
hideMovementHints();
setFrameHighlighted(true);
+
+ // Always focus on the first button when opening the menu, except directly after moving.
+ if (mFocusedButton == null) {
+ // Focus on first button (there is a Space at position 0)
+ mFocusedButton = mActionButtonsContainer.getChildAt(1);
+ // Reset scroll position.
+ mScrollView.scrollTo(0, 0);
+ mHorizontalScrollView.scrollTo(
+ isLayoutRtl() ? mActionButtonsContainer.getWidth() : 0, 0);
+ }
+ refocusPreviousButton();
}
/**
* Hides all menu views, including the menu frame.
*/
void hideAllUserControls() {
- if (DEBUG) {
- ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
- "%s: hideAllUserControls()", TAG);
- }
+ ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+ "%s: hideAllUserControls()", TAG);
+ mFocusedButton = null;
+ mButtonMenuIsVisible = false;
+ mMoveMenuIsVisible = false;
showButtonsMenu(false);
hideMovementHints();
setFrameHighlighted(false);
@@ -348,6 +514,13 @@ public class TvPipMenuView extends FrameLayout implements View.OnClickListener {
});
}
+ /**
+ * Button order:
+ * - Fullscreen
+ * - Close
+ * - Custom actions (app or media actions)
+ * - System actions
+ */
void setAdditionalActions(List<RemoteAction> actions, RemoteAction closeAction,
Handler mainHandler) {
if (DEBUG) {
@@ -370,13 +543,13 @@ public class TvPipMenuView extends FrameLayout implements View.OnClickListener {
final int actionsNumber = actions.size();
int buttonsNumber = mAdditionalButtons.size();
if (actionsNumber > buttonsNumber) {
- // Add buttons until we have enough to display all of the actions.
+ // Add buttons until we have enough to display all the actions.
while (actionsNumber > buttonsNumber) {
TvPipMenuActionButton button = new TvPipMenuActionButton(mContext);
button.setOnClickListener(this);
mActionButtonsContainer.addView(button,
- mActionButtonsContainer.getChildCount() - 1);
+ FIRST_CUSTOM_ACTION_POSITION + buttonsNumber);
mAdditionalButtons.add(button);
buttonsNumber++;
@@ -404,12 +577,21 @@ public class TvPipMenuView extends FrameLayout implements View.OnClickListener {
}
setActionForButton(action, button, mainHandler);
}
+
+ if (mCurrentPipBounds != null) {
+ updateButtonGravity(mCurrentPipBounds);
+ refocusPreviousButton();
+ }
}
private void setActionForButton(RemoteAction action, TvPipMenuActionButton button,
Handler mainHandler) {
button.setVisibility(View.VISIBLE); // Ensure the button is visible.
- button.setTextAndDescription(action.getContentDescription());
+ if (action.getContentDescription().length() > 0) {
+ button.setTextAndDescription(action.getContentDescription());
+ } else {
+ button.setTextAndDescription(action.getTitle());
+ }
button.setEnabled(action.isEnabled());
button.setTag(action);
action.getIcon().loadDrawableAsync(mContext, button::setImageDrawable, mainHandler);
@@ -460,12 +642,11 @@ public class TvPipMenuView extends FrameLayout implements View.OnClickListener {
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
- if (DEBUG) {
- ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
- "%s: dispatchKeyEvent, action: %d, keycode: %d",
- TAG, event.getAction(), event.getKeyCode());
- }
if (mListener != null && event.getAction() == ACTION_UP) {
+ if (!mMoveMenuIsVisible) {
+ mFocusedButton = mActionButtonsContainer.getFocusedChild();
+ }
+
switch (event.getKeyCode()) {
case KEYCODE_BACK:
mListener.onBackPress();
@@ -527,6 +708,10 @@ public class TvPipMenuView extends FrameLayout implements View.OnClickListener {
ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
"%s: showUserActions: %b", TAG, show);
}
+ if (show) {
+ mActionButtonsContainer.setVisibility(VISIBLE);
+ refocusPreviousButton();
+ }
animateAlphaTo(show ? 1 : 0, mActionButtonsContainer);
}