summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Jae Seo <jaeseo@google.com> 2016-05-27 17:23:57 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2016-05-27 17:23:58 +0000
commitf8c504db7f2e0e35c5fa19cad46681dc17db7488 (patch)
tree9a0782c46ea50764584e9a6aaef74460a2ea3c49
parent4f620d423f82dd43ed79178e0091132dd49ca2a9 (diff)
parenta9e0621f33233c43f29e876b6c1055cf1dc855fc (diff)
Merge "PIP: Improve PIP control row's focus change animation in Recents" into nyc-dev
-rw-r--r--packages/SystemUI/res/anim/tv_pip_controls_focus_gain_animation.xml (renamed from packages/SystemUI/res/anim/tv_pip_controls_text_focus_gain_animation.xml)0
-rw-r--r--packages/SystemUI/res/anim/tv_pip_controls_focus_loss_animation.xml (renamed from packages/SystemUI/res/anim/tv_pip_controls_text_focus_lose_animation.xml)0
-rw-r--r--packages/SystemUI/res/anim/tv_pip_controls_in_recents_focus_loss_animation.xml (renamed from packages/SystemUI/res/anim/tv_pip_controls_in_recents_focus_lose_animation.xml)0
-rw-r--r--packages/SystemUI/res/layout-television/recents_on_tv.xml5
-rw-r--r--packages/SystemUI/res/layout/tv_pip_control_button.xml18
-rw-r--r--packages/SystemUI/res/layout/tv_pip_recents_overlay.xml7
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java100
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/tv/animations/HomeRecentsEnterExitAnimationHolder.java22
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/tv/animations/RecentsRowFocusAnimationHolder.java39
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/tv/animations/ViewFocusAnimator.java34
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvView.java30
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java62
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalGridView.java89
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalViewAdapter.java28
-rw-r--r--packages/SystemUI/src/com/android/systemui/tv/pip/PipControlButtonView.java100
-rw-r--r--packages/SystemUI/src/com/android/systemui/tv/pip/PipControlsView.java40
-rw-r--r--packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/tv/pip/PipRecentsControlsView.java55
-rw-r--r--packages/SystemUI/src/com/android/systemui/tv/pip/PipRecentsOverlayManager.java82
19 files changed, 372 insertions, 343 deletions
diff --git a/packages/SystemUI/res/anim/tv_pip_controls_text_focus_gain_animation.xml b/packages/SystemUI/res/anim/tv_pip_controls_focus_gain_animation.xml
index 257bf35c8e76..257bf35c8e76 100644
--- a/packages/SystemUI/res/anim/tv_pip_controls_text_focus_gain_animation.xml
+++ b/packages/SystemUI/res/anim/tv_pip_controls_focus_gain_animation.xml
diff --git a/packages/SystemUI/res/anim/tv_pip_controls_text_focus_lose_animation.xml b/packages/SystemUI/res/anim/tv_pip_controls_focus_loss_animation.xml
index e032008b3750..e032008b3750 100644
--- a/packages/SystemUI/res/anim/tv_pip_controls_text_focus_lose_animation.xml
+++ b/packages/SystemUI/res/anim/tv_pip_controls_focus_loss_animation.xml
diff --git a/packages/SystemUI/res/anim/tv_pip_controls_in_recents_focus_lose_animation.xml b/packages/SystemUI/res/anim/tv_pip_controls_in_recents_focus_loss_animation.xml
index b571aa569f0d..b571aa569f0d 100644
--- a/packages/SystemUI/res/anim/tv_pip_controls_in_recents_focus_lose_animation.xml
+++ b/packages/SystemUI/res/anim/tv_pip_controls_in_recents_focus_loss_animation.xml
diff --git a/packages/SystemUI/res/layout-television/recents_on_tv.xml b/packages/SystemUI/res/layout-television/recents_on_tv.xml
index 82b9f8c3c48c..2b78beef3708 100644
--- a/packages/SystemUI/res/layout-television/recents_on_tv.xml
+++ b/packages/SystemUI/res/layout-television/recents_on_tv.xml
@@ -21,6 +21,7 @@
android:clipChildren="false"
android:clipToPadding="false"
android:background="@drawable/recents_tv_background_gradient">
+
<com.android.systemui.recents.tv.views.TaskStackHorizontalGridView
android:id="@+id/task_list"
android:layout_width="wrap_content"
@@ -32,13 +33,13 @@
android:focusable="true"
android:layoutDirection="rtl" />
- <!-- Placeholder view to give focus to the PIP menus. -->
+ <!-- Placeholder view to give focus to the PIP menus in talkback mode -->
<View
android:id="@+id/pip"
android:layout_width="1dp"
android:layout_height="1dp"
android:focusable="true"
- android:visibility="visible" />
+ android:visibility="gone" />
<!-- Placeholder to dismiss during talkback. -->
<ImageView
diff --git a/packages/SystemUI/res/layout/tv_pip_control_button.xml b/packages/SystemUI/res/layout/tv_pip_control_button.xml
index f18a5da03570..096dda881693 100644
--- a/packages/SystemUI/res/layout/tv_pip_control_button.xml
+++ b/packages/SystemUI/res/layout/tv_pip_control_button.xml
@@ -23,15 +23,25 @@
<ImageView android:id="@+id/button"
android:layout_width="34dp"
android:layout_height="34dp"
- android:padding="5dp"
+ android:layout_alignParentTop="true"
+ android:layout_centerHorizontal="true"
android:focusable="true"
- android:src="@drawable/ic_fullscreen_white_24dp"
- android:background="@drawable/tv_pip_button_focused"
- android:layerType="software" />
+ android:src="@drawable/tv_pip_button_focused"
+ android:importantForAccessibility="yes" />
+
+ <ImageView android:id="@+id/icon"
+ android:layout_width="34dp"
+ android:layout_height="34dp"
+ android:layout_alignParentTop="true"
+ android:layout_centerHorizontal="true"
+ android:padding="5dp"
+ android:importantForAccessibility="no" />
<TextView android:id="@+id/desc"
android:layout_width="100dp"
android:layout_height="wrap_content"
+ android:layout_below="@id/icon"
+ android:layout_centerHorizontal="true"
android:layout_marginTop="3dp"
android:gravity="center"
android:text="@string/pip_fullscreen"
diff --git a/packages/SystemUI/res/layout/tv_pip_recents_overlay.xml b/packages/SystemUI/res/layout/tv_pip_recents_overlay.xml
index 557bbe66b29b..f157fd59b23d 100644
--- a/packages/SystemUI/res/layout/tv_pip_recents_overlay.xml
+++ b/packages/SystemUI/res/layout/tv_pip_recents_overlay.xml
@@ -15,7 +15,7 @@
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="top|center_horizontal"
android:orientation="vertical">
@@ -33,7 +33,8 @@
android:layout_height="32dp"
android:translationY="-46dp"
android:layout_gravity="top|center_horizontal"
- android:background="@drawable/tv_pip_recents_overlay_scrim" />
+ android:background="@drawable/tv_pip_recents_overlay_scrim"
+ android:alpha="0" />
<com.android.systemui.tv.pip.PipControlsView
android:id="@+id/pip_control_contents"
android:layout_width="wrap_content"
@@ -42,6 +43,8 @@
android:layout_gravity="top|center_horizontal" />
</com.android.systemui.tv.pip.PipRecentsControlsView>
+ <!-- Placeholder view to handle focus change between Recents row and PIP controls
+ in talkback mode -->
<View
android:id="@+id/recents"
android:layout_width="1dp"
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java b/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java
index 1a559585e5c0..ecb12d3c9c5c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java
@@ -81,6 +81,7 @@ public class RecentsTvActivity extends Activity implements OnPreDrawListener {
private long mLastTabKeyEventTime;
private boolean mIgnoreAltTabRelease;
private boolean mLaunchedFromHome;
+ private boolean mTalkBackEnabled;
private RecentsTvView mRecentsView;
private View mPipView;
@@ -133,15 +134,22 @@ public class RecentsTvActivity extends Activity implements OnPreDrawListener {
@Override
public void onRecentsFocused() {
- mRecentsView.requestFocus();
- mRecentsView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
+ if (mTalkBackEnabled) {
+ mTaskStackHorizontalGridView.requestFocus();
+ mTaskStackHorizontalGridView.sendAccessibilityEvent(
+ AccessibilityEvent.TYPE_VIEW_FOCUSED);
+ }
+ mTaskStackHorizontalGridView.startFocusGainAnimation();
}
};
+
private final View.OnFocusChangeListener mPipViewFocusChangeListener =
new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
- handlePipViewFocusChange(hasFocus);
+ if (hasFocus) {
+ requestPipControlsFocus();
+ }
}
};
@@ -194,17 +202,18 @@ public class RecentsTvActivity extends Activity implements OnPreDrawListener {
loadOpts.numVisibleTaskThumbnails = numVisibleTasks;
loader.loadTasks(this, plan, loadOpts);
-
- mRecentsView.setTaskStack(stack);
List stackTasks = stack.getStackTasks();
Collections.reverse(stackTasks);
if (mTaskStackViewAdapter == null) {
mTaskStackViewAdapter = new TaskStackHorizontalViewAdapter(stackTasks);
mTaskStackHorizontalGridView = mRecentsView
.setTaskStackViewAdapter(mTaskStackViewAdapter);
+ mHomeRecentsEnterExitAnimationHolder = new HomeRecentsEnterExitAnimationHolder(
+ getApplicationContext(), mTaskStackHorizontalGridView);
} else {
mTaskStackViewAdapter.setNewStackTasks(stackTasks);
}
+ mRecentsView.init(stack);
if (launchState.launchedToTaskId != -1) {
ArrayList<Task> tasks = stack.getStackTasks();
@@ -305,6 +314,7 @@ public class RecentsTvActivity extends Activity implements OnPreDrawListener {
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
mPipView = findViewById(R.id.pip);
+ mPipView.setOnFocusChangeListener(mPipViewFocusChangeListener);
// Place mPipView at the PIP bounds for fine tuned focus handling.
Rect pipBounds = mPipManager.getRecentsFocusedPipBounds();
LayoutParams lp = (LayoutParams) mPipView.getLayoutParams();
@@ -342,7 +352,6 @@ public class RecentsTvActivity extends Activity implements OnPreDrawListener {
if(mLaunchedFromHome) {
mHomeRecentsEnterExitAnimationHolder.startEnterAnimation(mPipManager.isPipShown());
}
- mTaskStackViewAdapter.setResetAddedCards(true);
EventBus.getDefault().send(new EnterRecentsWindowAnimationCompletedEvent());
}
@@ -353,19 +362,6 @@ public class RecentsTvActivity extends Activity implements OnPreDrawListener {
// Update the recent tasks
updateRecentsTasks();
- mHomeRecentsEnterExitAnimationHolder = new HomeRecentsEnterExitAnimationHolder(
- getApplicationContext(), mTaskStackHorizontalGridView);
- if(mTaskStackHorizontalGridView != null &&
- mTaskStackHorizontalGridView.getChildCount() > 0) {
- if(mLaunchedFromHome) {
- mHomeRecentsEnterExitAnimationHolder.setEnterFromHomeStartingAnimationValues();
- } else {
- mHomeRecentsEnterExitAnimationHolder.setEnterFromAppStartingAnimationValues();
- }
- } else {
- mRecentsView.getViewTreeObserver().addOnPreDrawListener(this);
- }
-
// If this is a new instance from a configuration change, then we have to manually trigger
// the enter animation state, or if recents was relaunched by AM, without going through
// the normal mechanisms
@@ -387,9 +383,11 @@ public class RecentsTvActivity extends Activity implements OnPreDrawListener {
} else {
mTaskStackHorizontalGridView.setSelectedPosition(0);
}
+ mRecentsView.getViewTreeObserver().addOnPreDrawListener(this);
View dismissPlaceholder = findViewById(R.id.dismiss_placeholder);
- if (ssp.isTouchExplorationEnabled()) {
+ mTalkBackEnabled = ssp.isTouchExplorationEnabled();
+ if (mTalkBackEnabled) {
dismissPlaceholder.setAccessibilityTraversalBefore(R.id.task_list);
dismissPlaceholder.setAccessibilityTraversalAfter(R.id.dismiss_placeholder);
mTaskStackHorizontalGridView.setAccessibilityTraversalAfter(R.id.dismiss_placeholder);
@@ -408,14 +406,29 @@ public class RecentsTvActivity extends Activity implements OnPreDrawListener {
}
});
}
- updatePipUI();
+
+ // Initialize PIP UI
+ if (mPipManager.isPipShown()) {
+ if (mTalkBackEnabled) {
+ // If talkback is on, use the mPipView to handle focus changes
+ // between recents row and PIP controls.
+ mPipView.setVisibility(View.VISIBLE);
+ } else {
+ mPipView.setVisibility(View.GONE);
+ }
+ // When PIP view has focus, recents overlay view will takes the focus
+ // as if it's the part of the Recents UI.
+ mPipRecentsOverlayManager.requestFocus(mTaskStackViewAdapter.getItemCount() > 0);
+ } else {
+ mPipView.setVisibility(View.GONE);
+ mPipRecentsOverlayManager.removePipRecentsOverlayView();
+ }
}
@Override
public void onPause() {
super.onPause();
mPipRecentsOverlayManager.onRecentsPaused();
- mTaskStackViewAdapter.setResetAddedCards(false);
}
@Override
@@ -534,6 +547,7 @@ public class RecentsTvActivity extends Activity implements OnPreDrawListener {
public final void onBusEvent(AllTaskViewsDismissedEvent event) {
if (mPipManager.isPipShown()) {
mRecentsView.showEmptyView();
+ mPipRecentsOverlayManager.requestFocus(false);
} else {
dismissRecentsToHome(false);
}
@@ -547,10 +561,14 @@ public class RecentsTvActivity extends Activity implements OnPreDrawListener {
@Override
public boolean onPreDraw() {
mRecentsView.getViewTreeObserver().removeOnPreDrawListener(this);
- if(mLaunchedFromHome) {
- mHomeRecentsEnterExitAnimationHolder.setEnterFromHomeStartingAnimationValues();
+ // Sets the initial values for enter animation.
+ // Animation will be started in {@link #onEnterAnimationComplete()}
+ if (mLaunchedFromHome) {
+ mHomeRecentsEnterExitAnimationHolder
+ .setEnterFromHomeStartingAnimationValues(mPipManager.isPipShown());
} else {
- mHomeRecentsEnterExitAnimationHolder.setEnterFromAppStartingAnimationValues();
+ mHomeRecentsEnterExitAnimationHolder
+ .setEnterFromAppStartingAnimationValues(mPipManager.isPipShown());
}
// We post to make sure that this information is delivered after this traversals is
// finished.
@@ -564,35 +582,25 @@ public class RecentsTvActivity extends Activity implements OnPreDrawListener {
}
private void updatePipUI() {
- if (mPipManager.isPipShown()) {
- mPipView.setVisibility(View.VISIBLE);
- mPipView.setOnFocusChangeListener(mPipViewFocusChangeListener);
- if (mPipView.hasFocus()) {
- // This can happen only if the activity is resumed. Ask for reset.
- handlePipViewFocusChange(true);
- } else {
- mPipView.requestFocus();
- }
- } else {
- mPipView.setVisibility(View.GONE);
+ if (!mPipManager.isPipShown()) {
mPipRecentsOverlayManager.removePipRecentsOverlayView();
+ mTaskStackHorizontalGridView.startFocusLossAnimation();
+ } else {
+ Log.w(TAG, "An activity entered PIP mode while Recents is shown");
}
}
/**
- * Handles the PIP view's focus change.
+ * Requests the focus to the PIP controls.
* This starts the relevant recents row animation
* and give focus to the recents overlay if needed.
*/
- private void handlePipViewFocusChange(boolean hasFocus) {
- mRecentsView.startRecentsRowFocusAnimation(!hasFocus);
- if (hasFocus) {
- // When PIP view has focus, recents overlay view will takes the focus
- // as if it's the part of the Recents UI.
- mPipRecentsOverlayManager.requestFocus(
- mTaskStackViewAdapter.getItemCount() > 0);
- } else {
- mPipRecentsOverlayManager.clearFocus();
+ public void requestPipControlsFocus() {
+ if (!mPipManager.isPipShown()) {
+ return;
}
+
+ mTaskStackHorizontalGridView.startFocusLossAnimation();
+ mPipRecentsOverlayManager.requestFocus(mTaskStackViewAdapter.getItemCount() > 0);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/animations/HomeRecentsEnterExitAnimationHolder.java b/packages/SystemUI/src/com/android/systemui/recents/tv/animations/HomeRecentsEnterExitAnimationHolder.java
index 92718a3b5ac1..9faaa4bdccb6 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/animations/HomeRecentsEnterExitAnimationHolder.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/animations/HomeRecentsEnterExitAnimationHolder.java
@@ -74,19 +74,35 @@ public class HomeRecentsEnterExitAnimationHolder {
}
}
- public void setEnterFromHomeStartingAnimationValues() {
+ /**
+ * Sets the initial values Recents enter animation
+ * when Recents is started from the Launcher.
+ */
+ public void setEnterFromHomeStartingAnimationValues(boolean isPipShown) {
for(int i = 0; i < mGridView.getChildCount(); i++) {
TaskCardView view = (TaskCardView) mGridView.getChildAt(i);
view.setTranslationX(0);
view.setAlpha(0.0f);
+ view.getInfoFieldView().setAlpha(isPipShown ? 0 : 1f);
+ if (isPipShown && view.hasFocus()) {
+ view.getViewFocusAnimator().changeSize(false);
+ }
}
}
- public void setEnterFromAppStartingAnimationValues() {
+ /**
+ * Sets the initial values Recents enter animation
+ * when Recents is started from an app.
+ */
+ public void setEnterFromAppStartingAnimationValues(boolean isPipShown) {
for(int i = 0; i < mGridView.getChildCount(); i++) {
TaskCardView view = (TaskCardView) mGridView.getChildAt(i);
view.setTranslationX(0);
- view.setAlpha(1.0f);
+ view.setAlpha(isPipShown ? mDimAlpha : 1f);
+ view.getInfoFieldView().setAlpha(isPipShown ? 0 : 1f);
+ if (isPipShown && view.hasFocus()) {
+ view.getViewFocusAnimator().changeSize(false);
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/animations/RecentsRowFocusAnimationHolder.java b/packages/SystemUI/src/com/android/systemui/recents/tv/animations/RecentsRowFocusAnimationHolder.java
index 45c15379485b..8a4cf399b813 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/animations/RecentsRowFocusAnimationHolder.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/animations/RecentsRowFocusAnimationHolder.java
@@ -29,11 +29,11 @@ import com.android.systemui.recents.tv.views.TaskCardView;
* Recents row's focus animation with PIP controls.
*/
public class RecentsRowFocusAnimationHolder {
- private View mView;
- private View mTitleView;
+ private final View mView;
+ private final View mTitleView;
private AnimatorSet mFocusGainAnimatorSet;
- private AnimatorSet mFocusLoseAnimatorSet;
+ private AnimatorSet mFocusLossAnimatorSet;
public RecentsRowFocusAnimationHolder(View view, View titleView) {
mView = view;
@@ -50,28 +50,45 @@ public class RecentsRowFocusAnimationHolder {
mFocusGainAnimatorSet.setDuration(duration);
mFocusGainAnimatorSet.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
- mFocusLoseAnimatorSet = new AnimatorSet();
- mFocusLoseAnimatorSet.playTogether(
+ mFocusLossAnimatorSet = new AnimatorSet();
+ mFocusLossAnimatorSet.playTogether(
// Animation doesn't start from the current value (1f) sometimes,
// so specify the desired initial value here.
ObjectAnimator.ofFloat(mView, "alpha", 1f, dimAlpha),
ObjectAnimator.ofFloat(mTitleView, "alpha", 0f));
- mFocusLoseAnimatorSet.setDuration(duration);
- mFocusLoseAnimatorSet.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
+ mFocusLossAnimatorSet.setDuration(duration);
+ mFocusLossAnimatorSet.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
}
/**
- * Returns the Recents row's focus change animation.
+ * Starts the Recents row's focus gain animation.
*/
- public Animator getFocusChangeAnimator(boolean hasFocus) {
- return hasFocus ? mFocusGainAnimatorSet : mFocusLoseAnimatorSet;
+ public void startFocusGainAnimation() {
+ cancelAnimator(mFocusLossAnimatorSet);
+ mFocusGainAnimatorSet.start();
}
/**
- * Resets the views to the initial state immediately.
+ * Starts the Recents row's focus loss animation.
+ */
+ public void startFocusLossAnimation() {
+ cancelAnimator(mFocusGainAnimatorSet);
+ mFocusLossAnimatorSet.start();
+ }
+
+ /**
+ * Resets the views immediately and ends the animations.
*/
public void reset() {
+ cancelAnimator(mFocusLossAnimatorSet);
+ cancelAnimator(mFocusGainAnimatorSet);
mView.setAlpha(1f);
mTitleView.setAlpha(1f);
}
+
+ private static void cancelAnimator(Animator animator) {
+ if (animator.isStarted()) {
+ animator.cancel();
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/animations/ViewFocusAnimator.java b/packages/SystemUI/src/com/android/systemui/recents/tv/animations/ViewFocusAnimator.java
index 82185990c828..72fd7a4114ac 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/animations/ViewFocusAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/animations/ViewFocusAnimator.java
@@ -89,7 +89,7 @@ public class ViewFocusAnimator implements View.OnFocusChangeListener {
});
}
- public void setFocusProgress(float level) {
+ private void setFocusProgress(float level) {
mFocusProgress = level;
float scale = mUnselectedScale + (level * mSelectedScaleDelta);
@@ -107,33 +107,19 @@ public class ViewFocusAnimator implements View.OnFocusChangeListener {
mTargetView.getDismissIconView().setZ(z);
}
- public float getFocusProgress() {
- return mFocusProgress;
- }
-
- public void animateFocus(boolean focused) {
+ private void animateFocus(boolean focused) {
if (mFocusAnimation.isStarted()) {
mFocusAnimation.cancel();
}
float target = focused ? 1.0f : 0.0f;
- if (getFocusProgress() != target) {
- mFocusAnimation.setFloatValues(getFocusProgress(), target);
+ if (mFocusProgress != target) {
+ mFocusAnimation.setFloatValues(mFocusProgress, target);
mFocusAnimation.start();
}
}
- public void setFocusImmediate(boolean focused) {
- if (mFocusAnimation.isStarted()) {
- mFocusAnimation.cancel();
- }
-
- float target = focused ? 1.0f : 0.0f;
-
- setFocusProgress(target);
- }
-
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (v != mTargetView) {
@@ -142,21 +128,27 @@ public class ViewFocusAnimator implements View.OnFocusChangeListener {
changeSize(hasFocus);
}
- protected void changeSize(boolean hasFocus) {
+ /**
+ * Changes the size of the {@link TaskCardView} to show its focused state.
+ */
+ public void changeSize(boolean hasFocus) {
ViewGroup.LayoutParams lp = mTargetView.getLayoutParams();
int width = lp.width;
int height = lp.height;
if (width < 0 && height < 0) {
mTargetView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
- height = mTargetView.getMeasuredHeight();
}
if (mTargetView.isAttachedToWindow() && mTargetView.hasWindowFocus() &&
mTargetView.getVisibility() == View.VISIBLE) {
animateFocus(hasFocus);
} else {
- setFocusImmediate(hasFocus);
+ // Set focus immediately.
+ if (mFocusAnimation.isStarted()) {
+ mFocusAnimation.cancel();
+ }
+ setFocusProgress(hasFocus ? 1.0f : 0.0f);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvView.java b/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvView.java
index 06b24418a572..318b7f91fabf 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvView.java
@@ -59,7 +59,7 @@ public class RecentsTvView extends FrameLayout {
private boolean mAwaitingFirstLayout = true;
private Rect mSystemInsets = new Rect();
private RecentsTvTransitionHelper mTransitionHelper;
- private Handler mHandler;
+ private final Handler mHandler = new Handler();
private OnScrollListener mScrollListener;
public RecentsTvView(Context context) {
this(context, null);
@@ -81,9 +81,7 @@ public class RecentsTvView extends FrameLayout {
LayoutInflater inflater = LayoutInflater.from(context);
mEmptyView = inflater.inflate(R.layout.recents_tv_empty, this, false);
addView(mEmptyView);
- mEmptyViewFocusAnimationHolder = new RecentsRowFocusAnimationHolder(mEmptyView, null);
- mHandler = new Handler();
mTransitionHelper = new RecentsTvTransitionHelper(mContext, mHandler);
}
@@ -91,20 +89,18 @@ public class RecentsTvView extends FrameLayout {
protected void onFinishInflate() {
super.onFinishInflate();
mDismissPlaceholder = findViewById(R.id.dismiss_placeholder);
+ mTaskStackHorizontalView = (TaskStackHorizontalGridView) findViewById(R.id.task_list);
}
- public void setTaskStack(TaskStack stack) {
+ /**
+ * Initialize the view.
+ */
+ public void init(TaskStack stack) {
RecentsConfiguration config = Recents.getConfiguration();
RecentsActivityLaunchState launchState = config.getLaunchState();
mStack = stack;
- if (mTaskStackHorizontalView != null) {
- mTaskStackHorizontalView.reset();
- mTaskStackHorizontalView.setStack(stack);
- } else {
- mTaskStackHorizontalView = (TaskStackHorizontalGridView) findViewById(R.id.task_list);
- mTaskStackHorizontalView.setStack(stack);
- }
+ mTaskStackHorizontalView.init(stack);
if (stack.getStackTaskCount() > 0) {
hideEmptyView();
@@ -112,6 +108,7 @@ public class RecentsTvView extends FrameLayout {
showEmptyView();
}
+ // Layout with the new stack
requestLayout();
}
@@ -189,17 +186,6 @@ public class RecentsTvView extends FrameLayout {
}
/**
- * Starts the focus change animation.
- */
- public void startRecentsRowFocusAnimation(boolean hasFocus) {
- if (mEmptyView.getVisibility() == View.VISIBLE) {
- mEmptyViewFocusAnimationHolder.getFocusChangeAnimator(hasFocus).start();
- } else {
- mTaskStackHorizontalView.startRecentsRowFocusAnimation(hasFocus);
- }
- }
-
- /**
* Hides the task stack and shows the empty view.
*/
public void showEmptyView() {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java
index 758f93a5f5d5..72a589fe3c1a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java
@@ -40,16 +40,18 @@ import android.widget.TextView;
import com.android.systemui.R;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.misc.SystemServicesProxy;
+import com.android.systemui.recents.model.Task;
+import com.android.systemui.recents.tv.RecentsTvActivity;
import com.android.systemui.recents.tv.animations.DismissAnimationsHolder;
import com.android.systemui.recents.tv.animations.RecentsRowFocusAnimationHolder;
import com.android.systemui.recents.tv.animations.ViewFocusAnimator;
-import com.android.systemui.recents.model.Task;
public class TaskCardView extends LinearLayout {
private static final String TAG = "TaskCardView";
private View mThumbnailView;
private View mDismissIconView;
+ private View mInfoFieldView;
private TextView mTitleTextView;
private ImageView mBadgeView;
private Task mTask;
@@ -79,14 +81,14 @@ public class TaskCardView extends LinearLayout {
protected void onFinishInflate() {
super.onFinishInflate();
mThumbnailView = findViewById(R.id.card_view_thumbnail);
+ mInfoFieldView = findViewById(R.id.card_info_field);
mTitleTextView = (TextView) findViewById(R.id.card_title_text);
mBadgeView = (ImageView) findViewById(R.id.card_extra_badge);
mDismissIconView = findViewById(R.id.dismiss_icon);
mDismissAnimationsHolder = new DismissAnimationsHolder(this);
- View title = findViewById(R.id.card_info_field);
mCornerRadius = getResources().getDimensionPixelSize(
R.dimen.recents_task_view_rounded_corners_radius);
- mRecentsRowFocusAnimationHolder = new RecentsRowFocusAnimationHolder(this, title);
+ mRecentsRowFocusAnimationHolder = new RecentsRowFocusAnimationHolder(this, mInfoFieldView);
SystemServicesProxy ssp = Recents.getSystemServices();
if (!ssp.isTouchExplorationEnabled()) {
mDismissIconView.setVisibility(VISIBLE);
@@ -102,6 +104,9 @@ public class TaskCardView extends LinearLayout {
mBadgeView.setImageDrawable(task.icon);
setThumbnailView();
setContentDescription(task.titleDescription);
+ mDismissState = false;
+ mDismissAnimationsHolder.reset();
+ mRecentsRowFocusAnimationHolder.reset();
}
public Task getTask() {
@@ -196,40 +201,37 @@ public class TaskCardView extends LinearLayout {
}
@Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- switch (keyCode) {
+ public boolean dispatchKeyEvent(KeyEvent event) {
+ // Override dispatchKeyEvent() instead of onKeyDown() to prevent warning from ViewRootImpl.
+ switch (event.getKeyCode()) {
case KeyEvent.KEYCODE_DPAD_DOWN : {
- if (!isInDismissState()) {
+ if (!isInDismissState() && event.getAction() == KeyEvent.ACTION_DOWN) {
setDismissState(true);
return true;
}
break;
}
case KeyEvent.KEYCODE_DPAD_UP : {
- if (isInDismissState()) {
- setDismissState(false);
- return true;
+ if (event.getAction() == KeyEvent.ACTION_DOWN) {
+ if (isInDismissState()) {
+ setDismissState(false);
+ } else {
+ ((RecentsTvActivity) getContext()).requestPipControlsFocus();
+ }
}
- break;
+ return true;
}
- //Eat right and left key presses when we are in dismiss state
- case KeyEvent.KEYCODE_DPAD_LEFT : {
- if (isInDismissState()) {
- return true;
- }
- break;
- }
+ // Eat right and left key presses when we are in dismiss state
+ case KeyEvent.KEYCODE_DPAD_LEFT :
case KeyEvent.KEYCODE_DPAD_RIGHT : {
if (isInDismissState()) {
return true;
}
break;
}
- default:
- break;
}
- return super.onKeyDown(keyCode, event);
+ return super.dispatchKeyEvent(event);
}
private void setDismissState(boolean dismissState) {
@@ -252,20 +254,12 @@ public class TaskCardView extends LinearLayout {
mDismissAnimationsHolder.startDismissAnimation(listener);
}
- public RecentsRowFocusAnimationHolder getRecentsRowFocusAnimationHolder() {
- return mRecentsRowFocusAnimationHolder;
+ public ViewFocusAnimator getViewFocusAnimator() {
+ return mViewFocusAnimator;
}
- @Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- setDismissState(false);
- }
-
- public void reset() {
- mDismissState = false;
- mRecentsRowFocusAnimationHolder.reset();
- mDismissAnimationsHolder.reset();
+ public RecentsRowFocusAnimationHolder getRecentsRowFocusAnimationHolder() {
+ return mRecentsRowFocusAnimationHolder;
}
private void setThumbnailView() {
@@ -332,6 +326,10 @@ public class TaskCardView extends LinearLayout {
return mThumbnailView;
}
+ public View getInfoFieldView() {
+ return mInfoFieldView;
+ }
+
public View getDismissIconView() {
return mDismissIconView;
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalGridView.java b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalGridView.java
index 3fb339e8f98a..f9b8700c1d46 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalGridView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalGridView.java
@@ -18,8 +18,6 @@ package com.android.systemui.recents.tv.views;
import android.animation.Animator;
import android.animation.AnimatorSet;
import android.content.Context;
-import android.os.Handler;
-import android.os.Message;
import android.support.v17.leanback.widget.HorizontalGridView;
import android.util.AttributeSet;
import android.view.View;
@@ -39,14 +37,6 @@ import com.android.systemui.recents.views.AnimationProps;
public class TaskStackHorizontalGridView extends HorizontalGridView implements TaskStackCallbacks {
private static final int ANIMATION_DELAY_MS = 50;
private static final int MSG_START_RECENT_ROW_FOCUS_ANIMATION = 100;
- private final Handler mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- if (msg.what == MSG_START_RECENT_ROW_FOCUS_ANIMATION) {
- startRecentsRowFocusAnimation(msg.arg1 == 1);
- }
- }
- };
private TaskStack mStack;
private Task mFocusedTask;
private AnimatorSet mRecentsRowFocusAnimation;
@@ -74,38 +64,15 @@ public class TaskStackHorizontalGridView extends HorizontalGridView implements T
}
/**
- * Resets this view for reuse.
- */
- public void reset() {
- for (int i = 0; i < getChildCount(); i++) {
- ((TaskCardView) getChildAt(i)).getRecentsRowFocusAnimationHolder().reset();
- }
- if (mRecentsRowFocusAnimation != null && mRecentsRowFocusAnimation.isStarted()) {
- mRecentsRowFocusAnimation.cancel();
- }
- mHandler.removeCallbacksAndMessages(null);
- requestLayout();
- }
-
- /**
- * @param task - Task to reset
- */
- private void resetFocusedTask(Task task) {
- mFocusedTask = null;
- }
-
- /**
- * Sets the task stack.
+ * Initializes the grid view.
* @param stack
*/
- public void setStack(TaskStack stack) {
- //Set new stack
+ public void init(TaskStack stack) {
+ // Set new stack
mStack = stack;
if (mStack != null) {
mStack.setCallbacks(this);
}
- //Layout with new stack
- requestLayout();
}
/**
@@ -126,13 +93,6 @@ public class TaskStackHorizontalGridView extends HorizontalGridView implements T
}
/**
- * @return - The focused task card view.
- */
- public TaskCardView getFocusedTaskCardView() {
- return ((TaskCardView)findFocus());
- }
-
- /**
* @param task
* @return Child view for given task
*/
@@ -146,32 +106,31 @@ public class TaskStackHorizontalGridView extends HorizontalGridView implements T
return null;
}
+
/**
- * Starts the focus change animation.
+ * Starts the Recents row's focus gain animation.
*/
- public void startRecentsRowFocusAnimation(final boolean hasFocus) {
- if (getChildCount() == 0) {
- // Animation request may happen before view is attached.
- // Post again with small dealy so animation can be run again later.
- if (getAdapter().getItemCount() > 0) {
- mHandler.sendMessageDelayed(mHandler.obtainMessage(
- MSG_START_RECENT_ROW_FOCUS_ANIMATION, hasFocus ? 1 : 0),
- ANIMATION_DELAY_MS);
+ public void startFocusGainAnimation() {
+ for (int i = 0; i < getChildCount(); i++) {
+ TaskCardView v = (TaskCardView) getChildAt(i);
+ if (v.hasFocus()) {
+ v.getViewFocusAnimator().changeSize(true);
}
- return;
- }
- if (mRecentsRowFocusAnimation != null && mRecentsRowFocusAnimation.isStarted()) {
- mRecentsRowFocusAnimation.cancel();
+ v.getRecentsRowFocusAnimationHolder().startFocusGainAnimation();
}
- Animator animator = ((TaskCardView) getChildAt(0)).getRecentsRowFocusAnimationHolder()
- .getFocusChangeAnimator(hasFocus);
- mRecentsRowFocusAnimation = new AnimatorSet();
- AnimatorSet.Builder builder = mRecentsRowFocusAnimation.play(animator);
- for (int i = 1; i < getChildCount(); i++) {
- builder.with(((TaskCardView) getChildAt(i)).getRecentsRowFocusAnimationHolder()
- .getFocusChangeAnimator(hasFocus));
+ }
+
+ /**
+ * Starts the Recents row's focus loss animation.
+ */
+ public void startFocusLossAnimation() {
+ for (int i = 0; i < getChildCount(); i++) {
+ TaskCardView v = (TaskCardView) getChildAt(i);
+ if (v.hasFocus()) {
+ v.getViewFocusAnimator().changeSize(false);
+ }
+ v.getRecentsRowFocusAnimationHolder().startFocusLossAnimation();
}
- mRecentsRowFocusAnimation.start();
}
@Override
@@ -185,7 +144,7 @@ public class TaskStackHorizontalGridView extends HorizontalGridView implements T
AnimationProps animation, boolean fromDockGesture) {
((TaskStackHorizontalViewAdapter) getAdapter()).removeTask(removedTask);
if (mFocusedTask == removedTask) {
- resetFocusedTask(removedTask);
+ mFocusedTask = null;
}
// If there are no remaining tasks, then just close recents
if (mStack.getStackTaskCount() == 0) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalViewAdapter.java b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalViewAdapter.java
index b6b86b409948..236d0778fadd 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalViewAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalViewAdapter.java
@@ -43,17 +43,13 @@ public class TaskStackHorizontalViewAdapter extends
private static final String TAG = "TaskStackViewAdapter";
private List<Task> mTaskList;
private TaskStackHorizontalGridView mGridView;
- private boolean mResetAddedCards;
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
private TaskCardView mTaskCardView;
private Task mTask;
- private boolean mShouldReset;
public ViewHolder(View v) {
super(v);
- if(v instanceof TaskCardView) {
- mTaskCardView = (TaskCardView) v;
- }
+ mTaskCardView = (TaskCardView) v;
}
public void init(Task task) {
@@ -90,7 +86,6 @@ public class TaskStackHorizontalViewAdapter extends
public void onAnimationEnd(Animator animation) {
removeTask(task);
EventBus.getDefault().send(new DeleteTaskDataEvent(task));
- mShouldReset = true;
}
@Override
@@ -131,23 +126,6 @@ public class TaskStackHorizontalViewAdapter extends
}
@Override
- public void onViewAttachedToWindow(ViewHolder holder) {
- if (mResetAddedCards) {
- holder.mTaskCardView.reset();
- }
- }
-
- @Override
- public void onViewDetachedFromWindow(ViewHolder holder) {
- // We only want to reset on view detach if this is the last task being dismissed.
- // This is so that we do not reset when shifting to apps etc, as it is not needed.
- if (holder.mShouldReset) {
- holder.mTaskCardView.reset();
- holder.mShouldReset = false;
- }
- }
-
- @Override
public int getItemCount() {
return mTaskList.size();
}
@@ -178,8 +156,4 @@ public class TaskStackHorizontalViewAdapter extends
mTaskList.add(position, task);
notifyItemInserted(position);
}
-
- public void setResetAddedCards(boolean reset) {
- mResetAddedCards = reset;
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipControlButtonView.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipControlButtonView.java
index bcf2f67944a6..80c593c076e9 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipControlButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipControlButtonView.java
@@ -21,12 +21,11 @@ import android.animation.AnimatorInflater;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
-import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View.OnFocusChangeListener;
import android.view.View;
import android.widget.ImageView;
-import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
import android.widget.TextView;
import com.android.systemui.R;
@@ -34,31 +33,28 @@ import com.android.systemui.R;
/**
* A view containing PIP controls including fullscreen, close, and media controls.
*/
-public class PipControlButtonView extends LinearLayout {
+public class PipControlButtonView extends RelativeLayout {
private OnFocusChangeListener mFocusChangeListener;
- private ImageView mButtonImageView;
+ private ImageView mIconImageView;
+ ImageView mButtonImageView;
private TextView mDescriptionTextView;
- private Animator mFocusGainAnimator;
- private Animator mFocusLoseAnimator;
+ private Animator mTextFocusGainAnimator;
+ private Animator mButtonFocusGainAnimator;
+ private Animator mTextFocusLossAnimator;
+ private Animator mButtonFocusLossAnimator;
private final OnFocusChangeListener mInternalFocusChangeListener =
new OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
- if (mFocusLoseAnimator.isStarted()) {
- mFocusLoseAnimator.cancel();
- }
- mFocusGainAnimator.start();
+ startFocusGainAnimation();
} else {
- if (mFocusGainAnimator.isStarted()) {
- mFocusGainAnimator.cancel();
- }
- mFocusLoseAnimator.start();
+ startFocusLossAnimation();
}
if (mFocusChangeListener != null) {
- mFocusChangeListener.onFocusChange(v, hasFocus);
+ mFocusChangeListener.onFocusChange(PipControlButtonView.this, hasFocus);
}
}
};
@@ -82,9 +78,7 @@ public class PipControlButtonView extends LinearLayout {
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.tv_pip_control_button, this);
- setOrientation(LinearLayout.VERTICAL);
- setGravity(Gravity.CENTER);
-
+ mIconImageView = (ImageView) findViewById(R.id.icon);
mButtonImageView = (ImageView) findViewById(R.id.button);
mDescriptionTextView = (TextView) findViewById(R.id.desc);
@@ -103,12 +97,19 @@ public class PipControlButtonView extends LinearLayout {
super.onFinishInflate();
mButtonImageView.setOnFocusChangeListener(mInternalFocusChangeListener);
- mFocusGainAnimator = AnimatorInflater.loadAnimator(getContext(),
- R.anim.tv_pip_controls_text_focus_gain_animation);
- mFocusGainAnimator.setTarget(mDescriptionTextView);
- mFocusLoseAnimator = AnimatorInflater.loadAnimator(getContext(),
- R.anim.tv_pip_controls_text_focus_lose_animation);
- mFocusLoseAnimator.setTarget(mDescriptionTextView);
+ mTextFocusGainAnimator = AnimatorInflater.loadAnimator(getContext(),
+ R.anim.tv_pip_controls_focus_gain_animation);
+ mTextFocusGainAnimator.setTarget(mDescriptionTextView);
+ mButtonFocusGainAnimator = AnimatorInflater.loadAnimator(getContext(),
+ R.anim.tv_pip_controls_focus_gain_animation);
+ mButtonFocusGainAnimator.setTarget(mButtonImageView);
+
+ mTextFocusLossAnimator = AnimatorInflater.loadAnimator(getContext(),
+ R.anim.tv_pip_controls_focus_loss_animation);
+ mTextFocusLossAnimator.setTarget(mDescriptionTextView);
+ mButtonFocusLossAnimator = AnimatorInflater.loadAnimator(getContext(),
+ R.anim.tv_pip_controls_focus_loss_animation);
+ mButtonFocusLossAnimator.setTarget(mButtonImageView);
}
@Override
@@ -125,7 +126,7 @@ public class PipControlButtonView extends LinearLayout {
* Sets the drawable for the button with the given resource id.
*/
public void setImageResource(int resId) {
- mButtonImageView.setImageResource(resId);
+ mIconImageView.setImageResource(resId);
}
/**
@@ -136,8 +137,51 @@ public class PipControlButtonView extends LinearLayout {
mDescriptionTextView.setText(resId);
}
- @Override
- public boolean isFocused() {
- return mButtonImageView.isFocused();
+ private static void cancelAnimator(Animator animator) {
+ if (animator.isStarted()) {
+ animator.cancel();
+ }
+ }
+
+ /**
+ * Starts the focus gain animation.
+ */
+ public void startFocusGainAnimation() {
+ cancelAnimator(mButtonFocusLossAnimator);
+ cancelAnimator(mTextFocusLossAnimator);
+ mTextFocusGainAnimator.start();
+ if (mButtonImageView.getAlpha() < 1f) {
+ // If we had faded out the ripple drawable, run our manual focus change animation.
+ // See the comment at {@link #startFocusLossAnimation()} for the reason of manual
+ // animator.
+ mButtonFocusGainAnimator.start();
+ }
+ }
+
+ /**
+ * Starts the focus loss animation.
+ */
+ public void startFocusLossAnimation() {
+ cancelAnimator(mButtonFocusGainAnimator);
+ cancelAnimator(mTextFocusGainAnimator);
+ mTextFocusLossAnimator.start();
+ if (mButtonImageView.hasFocus()) {
+ // Button uses ripple that has the default animation for the focus changes.
+ // Howevever, it doesn't expose the API to fade out while it is focused,
+ // so we should manually run the fade out animation when PIP controls row loses focus.
+ mButtonFocusLossAnimator.start();
+ }
+ }
+
+ /**
+ * Resets to initial state.
+ */
+ public void reset() {
+ cancelAnimator(mButtonFocusGainAnimator);
+ cancelAnimator(mTextFocusGainAnimator);
+ cancelAnimator(mButtonFocusLossAnimator);
+ cancelAnimator(mTextFocusLossAnimator);
+ mButtonImageView.setAlpha(1f);
+ mDescriptionTextView.setAlpha(mButtonImageView.hasFocus() ? 1f : 0f);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipControlsView.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipControlsView.java
index 5614bf9c566b..71740ce1b391 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipControlsView.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipControlsView.java
@@ -61,8 +61,7 @@ public class PipControlsView extends LinearLayout {
private PipControlButtonView mCloseButtonView;
private PipControlButtonView mPlayPauseButtonView;
- private boolean mHasFocus;
- private OnFocusChangeListener mOnChildFocusChangeListener;
+ private PipControlButtonView mFocusedChild;
private MediaController.Callback mMediaControllerCallback = new MediaController.Callback() {
@Override
@@ -80,8 +79,12 @@ public class PipControlsView extends LinearLayout {
private final OnFocusChangeListener mFocusChangeListener = new OnFocusChangeListener() {
@Override
- public void onFocusChange(View v, boolean hasFocus) {
- onChildViewFocusChanged();
+ public void onFocusChange(View view, boolean hasFocus) {
+ if (hasFocus) {
+ mFocusedChild = (PipControlButtonView) view;
+ } else if (mFocusedChild == view) {
+ mFocusedChild = null;
+ }
}
};
@@ -200,23 +203,13 @@ public class PipControlsView extends LinearLayout {
}
/**
- * Sets a listener to be invoked when {@link android.view.View.hasFocus()} is changed.
+ * Resets to initial state.
*/
- public void setOnChildFocusChangeListener(OnFocusChangeListener listener) {
- mOnChildFocusChangeListener = listener;
- }
-
- private void onChildViewFocusChanged() {
- // At this moment, hasFocus() returns true although there's no focused child.
- boolean hasFocus = (mFullButtonView != null && mFullButtonView.isFocused())
- || (mPlayPauseButtonView != null && mPlayPauseButtonView.isFocused())
- || (mCloseButtonView != null && mCloseButtonView.isFocused());
- if (mHasFocus != hasFocus) {
- mHasFocus = hasFocus;
- if (mOnChildFocusChangeListener != null) {
- mOnChildFocusChangeListener.onFocusChange(getFocusedChild(), mHasFocus);
- }
- }
+ public void reset() {
+ mFullButtonView.reset();
+ mCloseButtonView.reset();
+ mPlayPauseButtonView.reset();
+ mFullButtonView.requestFocus();
}
/**
@@ -225,4 +218,11 @@ public class PipControlsView extends LinearLayout {
public void setListener(Listener listener) {
mListener = listener;
}
+
+ /**
+ * Returns the focused control button view to animate focused button.
+ */
+ PipControlButtonView getFocusedButton() {
+ return mFocusedChild;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java
index 476598d3afc7..30622d29b9a9 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java
@@ -126,7 +126,6 @@ public class PipManager {
private int mSuspendPipResizingReason;
private Context mContext;
- private SystemServicesProxy mSystemServiceProxy;
private PipRecentsOverlayManager mPipRecentsOverlayManager;
private IActivityManager mActivityManager;
private MediaSessionManager mMediaSessionManager;
@@ -213,8 +212,7 @@ public class PipManager {
mPipBounds = mDefaultPipBounds;
mActivityManager = ActivityManagerNative.getDefault();
- mSystemServiceProxy = SystemServicesProxy.getInstance(context);
- mSystemServiceProxy.registerTaskStackListener(mTaskStackListener);
+ SystemServicesProxy.getInstance(context).registerTaskStackListener(mTaskStackListener);
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_MEDIA_RESOURCE_GRANTED);
mContext.registerReceiver(mBroadcastReceiver, intentFilter);
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipRecentsControlsView.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipRecentsControlsView.java
index df44dc1c2362..ffe96afae3a3 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipRecentsControlsView.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipRecentsControlsView.java
@@ -48,12 +48,12 @@ public class PipRecentsControlsView extends FrameLayout {
abstract void onBackPressed();
}
- final PipManager mPipManager = PipManager.getInstance();
+ private final PipManager mPipManager = PipManager.getInstance();
private Listener mListener;
private PipControlsView mPipControlsView;
private View mScrim;
private Animator mFocusGainAnimator;
- private AnimatorSet mFocusLoseAnimatorSet;
+ private AnimatorSet mFocusLossAnimatorSet;
public PipRecentsControlsView(Context context) {
this(context, null, 0, 0);
@@ -80,12 +80,12 @@ public class PipRecentsControlsView extends FrameLayout {
mScrim = findViewById(R.id.scrim);
mFocusGainAnimator = loadAnimator(mPipControlsView,
- R.anim.tv_pip_controls_in_recents_focus_gain_animation);
+ R.anim.tv_pip_controls_in_recents_focus_gain_animation);
- mFocusLoseAnimatorSet = new AnimatorSet();
- mFocusLoseAnimatorSet.playSequentially(
+ mFocusLossAnimatorSet = new AnimatorSet();
+ mFocusLossAnimatorSet.playSequentially(
loadAnimator(mPipControlsView,
- R.anim.tv_pip_controls_in_recents_focus_lose_animation),
+ R.anim.tv_pip_controls_in_recents_focus_loss_animation),
loadAnimator(mScrim, R.anim.tv_pip_controls_in_recents_scrim_fade_in_animation));
Rect pipBounds = mPipManager.getRecentsFocusedPipBounds();
@@ -99,21 +99,29 @@ public class PipRecentsControlsView extends FrameLayout {
}
/**
- * Starts focus gaining animation.
+ * Starts focus gain animation.
*/
public void startFocusGainAnimation() {
// Hides the scrim view as soon as possible, before the PIP resize animation starts.
// If we don't, PIP will be moved down a bit and a gap between the scrim and PIP will be
// shown at the bottom of the PIP.
mScrim.setAlpha(0);
- startAnimator(mFocusGainAnimator, mFocusLoseAnimatorSet);
+ PipControlButtonView focus = mPipControlsView.getFocusedButton();
+ if (focus != null) {
+ focus.startFocusGainAnimation();
+ }
+ startAnimator(mFocusGainAnimator, mFocusLossAnimatorSet);
}
/**
- * Starts focus losing animation.
+ * Starts focus loss animation.
*/
- public void startFocusLoseAnimation() {
- startAnimator(mFocusLoseAnimatorSet, mFocusGainAnimator);
+ public void startFocusLossAnimation() {
+ PipControlButtonView focus = mPipControlsView.getFocusedButton();
+ if (focus != null) {
+ focus.startFocusLossAnimation();
+ }
+ startAnimator(mFocusLossAnimatorSet, mFocusGainAnimator);
}
/**
@@ -121,14 +129,14 @@ public class PipRecentsControlsView extends FrameLayout {
*/
public void reset() {
cancelAnimator(mFocusGainAnimator);
- cancelAnimator(mFocusLoseAnimatorSet);
+ cancelAnimator(mFocusLossAnimatorSet);
// Reset to initial state (i.e. end of focused)
- requestFocus();
+ mScrim.setAlpha(0);
mPipControlsView.setTranslationY(0);
mPipControlsView.setScaleX(1);
mPipControlsView.setScaleY(1);
- mScrim.setAlpha(0);
+ mPipControlsView.reset();
}
private static void startAnimator(Animator animator, Animator previousAnimator) {
@@ -153,13 +161,20 @@ public class PipRecentsControlsView extends FrameLayout {
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
- if (!event.isCanceled()
- && event.getKeyCode() == KeyEvent.KEYCODE_BACK
- && event.getAction() == KeyEvent.ACTION_UP) {
- if (mPipControlsView.mListener != null) {
- ((PipRecentsControlsView.Listener) mPipControlsView.mListener).onBackPressed();
+ if (!event.isCanceled()) {
+ if (event.getKeyCode() == KeyEvent.KEYCODE_BACK
+ && event.getAction() == KeyEvent.ACTION_UP) {
+ if (mPipControlsView.mListener != null) {
+ ((PipRecentsControlsView.Listener) mPipControlsView.mListener).onBackPressed();
+ }
+ return true;
+ } else if (event.getKeyCode() == KeyEvent.KEYCODE_DPAD_DOWN) {
+ if (event.getAction() == KeyEvent.ACTION_DOWN) {
+ mPipManager.getPipRecentsOverlayManager().clearFocus();
+ }
+ // Consume the down event always to prevent warning logs from ViewRootImpl.
+ return true;
}
- return true;
}
return super.dispatchKeyEvent(event);
}
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipRecentsOverlayManager.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipRecentsOverlayManager.java
index 6e4a5938d7b5..895b8a228a00 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipRecentsOverlayManager.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipRecentsOverlayManager.java
@@ -18,15 +18,20 @@ package com.android.systemui.tv.pip;
import android.content.Context;
import android.graphics.PixelFormat;
+import android.graphics.Rect;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
-import android.view.accessibility.AccessibilityEvent;
-import android.view.WindowManager.LayoutParams;
import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
+import android.view.accessibility.AccessibilityEvent;
import com.android.systemui.R;
+import com.android.systemui.recents.misc.SystemServicesProxy;
+import static android.view.Gravity.CENTER_HORIZONTAL;
+import static android.view.Gravity.TOP;
+import static android.view.View.MeasureSpec.UNSPECIFIED;
import static com.android.systemui.tv.pip.PipManager.STATE_PIP_OVERLAY;
import static com.android.systemui.tv.pip.PipManager.STATE_PIP_RECENTS;
import static com.android.systemui.tv.pip.PipManager.STATE_PIP_RECENTS_FOCUSED;
@@ -42,13 +47,16 @@ public class PipRecentsOverlayManager {
private final PipManager mPipManager = PipManager.getInstance();
private final WindowManager mWindowManager;
+ private final SystemServicesProxy mSystemServicesProxy;
private View mOverlayView;
private PipRecentsControlsView mPipControlsView;
private View mRecentsView;
+ private boolean mTalkBackEnabled;
- private final LayoutParams mPipRecentsControlsViewLayoutParams;
- private final LayoutParams mPipRecentsControlsViewFocusedLayoutParams;
+ private LayoutParams mPipRecentsControlsViewLayoutParams;
+ private LayoutParams mPipRecentsControlsViewFocusedLayoutParams;
+ private boolean mHasFocusableInRecents;
private boolean mIsPipRecentsOverlayShown;
private boolean mIsRecentsShown;
private boolean mIsPipFocusedInRecent;
@@ -72,18 +80,7 @@ public class PipRecentsOverlayManager {
PipRecentsOverlayManager(Context context) {
mWindowManager = (WindowManager) context.getSystemService(WindowManager.class);
-
- mPipRecentsControlsViewLayoutParams = new WindowManager.LayoutParams(
- LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
- LayoutParams.TYPE_SYSTEM_DIALOG,
- LayoutParams.FLAG_NOT_FOCUSABLE | LayoutParams.FLAG_NOT_TOUCHABLE,
- PixelFormat.TRANSLUCENT);
- mPipRecentsControlsViewFocusedLayoutParams = new WindowManager.LayoutParams(
- LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
- LayoutParams.TYPE_SYSTEM_DIALOG,
- 0,
- PixelFormat.TRANSLUCENT);
-
+ mSystemServicesProxy = SystemServicesProxy.getInstance(context);
initViews(context);
}
@@ -101,6 +98,20 @@ public class PipRecentsOverlayManager {
}
}
});
+
+ mOverlayView.measure(UNSPECIFIED, UNSPECIFIED);
+ mPipRecentsControlsViewLayoutParams = new WindowManager.LayoutParams(
+ mOverlayView.getMeasuredWidth(), mOverlayView.getMeasuredHeight(),
+ LayoutParams.TYPE_SYSTEM_DIALOG,
+ LayoutParams.FLAG_NOT_FOCUSABLE | LayoutParams.FLAG_NOT_TOUCHABLE,
+ PixelFormat.TRANSLUCENT);
+ mPipRecentsControlsViewLayoutParams.gravity = TOP | CENTER_HORIZONTAL;
+ mPipRecentsControlsViewFocusedLayoutParams = new WindowManager.LayoutParams(
+ mOverlayView.getMeasuredWidth(), mOverlayView.getMeasuredHeight(),
+ LayoutParams.TYPE_SYSTEM_DIALOG,
+ 0,
+ PixelFormat.TRANSLUCENT);
+ mPipRecentsControlsViewFocusedLayoutParams.gravity = TOP | CENTER_HORIZONTAL;
}
/**
@@ -111,9 +122,10 @@ public class PipRecentsOverlayManager {
if (mIsPipRecentsOverlayShown) {
return;
}
+ mTalkBackEnabled = mSystemServicesProxy.isTouchExplorationEnabled();
+ mRecentsView.setVisibility(mTalkBackEnabled ? View.VISIBLE : View.GONE);
mIsPipRecentsOverlayShown = true;
mIsPipFocusedInRecent = true;
- mPipControlsView.reset();
mWindowManager.addView(mOverlayView, mPipRecentsControlsViewFocusedLayoutParams);
}
@@ -126,50 +138,46 @@ public class PipRecentsOverlayManager {
return;
}
mWindowManager.removeView(mOverlayView);
+ // Resets the controls view when its removed.
+ // If not, changing focus in reset will be show animation when Recents is resumed.
+ mPipControlsView.reset();
mIsPipRecentsOverlayShown = false;
}
/**
* Request focus to the PIP Recents overlay.
- * Called when the PIP view in {@link com.android.systemui.recents.tv.RecentsTvActivity}
- * is focused.
* This should be called only by {@link com.android.systemui.recents.tv.RecentsTvActivity}.
- * @param allowRecentsFocusable {@code true} if Recents can have focus. (i.e. Has a recent task)
+ * @param hasFocusableInRecents {@code true} if Recents can have focus. (i.e. Has a recent task)
*/
- public void requestFocus(boolean allowRecentsFocusable) {
- mRecentsView.setVisibility(allowRecentsFocusable ? View.VISIBLE : View.GONE);
+ public void requestFocus(boolean hasFocusableInRecents) {
+ mHasFocusableInRecents = hasFocusableInRecents;
if (!mIsPipRecentsOverlayShown || !mIsRecentsShown || mIsPipFocusedInRecent
|| !mPipManager.isPipShown()) {
return;
}
mIsPipFocusedInRecent = true;
- mPipManager.resizePinnedStack(STATE_PIP_RECENTS_FOCUSED);
-
- mWindowManager.updateViewLayout(mOverlayView, mPipRecentsControlsViewFocusedLayoutParams);
- mPipControlsView.requestFocus();
- mPipControlsView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
mPipControlsView.startFocusGainAnimation();
+ mWindowManager.updateViewLayout(mOverlayView, mPipRecentsControlsViewFocusedLayoutParams);
+ mPipManager.resizePinnedStack(STATE_PIP_RECENTS_FOCUSED);
+ if (mTalkBackEnabled) {
+ mPipControlsView.requestFocus();
+ mPipControlsView.sendAccessibilityEvent(
+ AccessibilityEvent.TYPE_VIEW_FOCUSED);
+ }
}
/**
* Request focus to the PIP Recents overlay.
- * Called when the PIP view in {@link com.android.systemui.recents.tv.RecentsTvActivity}
- * is focused.
- * This should be called only by {@link com.android.systemui.recents.tv.RecentsTvActivity}.
*/
public void clearFocus() {
if (!mIsPipRecentsOverlayShown || !mIsRecentsShown || !mIsPipFocusedInRecent
- || !mPipManager.isPipShown()) {
+ || !mPipManager.isPipShown() || !mHasFocusableInRecents) {
return;
}
- if (!mRecentsView.hasFocus()) {
- // Let mRecentsView's focus listener handle clearFocus().
- mRecentsView.requestFocus();
- }
mIsPipFocusedInRecent = false;
- mPipManager.resizePinnedStack(STATE_PIP_RECENTS);
+ mPipControlsView.startFocusLossAnimation();
mWindowManager.updateViewLayout(mOverlayView, mPipRecentsControlsViewLayoutParams);
- mPipControlsView.startFocusLoseAnimation();
+ mPipManager.resizePinnedStack(STATE_PIP_RECENTS);
if (mCallback != null) {
mCallback.onRecentsFocused();
}