summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Sergey Nikolaienkov <sergeynv@google.com> 2020-09-24 07:55:22 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2020-09-24 07:55:22 +0000
commitfa9e5cd3555a48126c6c1cf4bccc209c46c96f3b (patch)
tree82fc3d7b915d8402488464ca64edd80683fcf65a
parentdf17ab0e4beeb4809be660f1bd1d6f640992a563 (diff)
parent1dbc58650490bfafa9389a1bfae138fabaf2975f (diff)
Merge changes from topic "tv-mic-indicator-refresh"
* changes: Make AudioRecordingDisclosureBar animations interruptable Update AudioRecordingDisclosureBar animations Clean up unused Views in AudioRecordingDisclosureBar
-rw-r--r--packages/SystemUI/res/drawable/tv_rect_dark_left_rounded.xml26
-rw-r--r--packages/SystemUI/res/drawable/tv_rect_dark_right_rounded.xml26
-rw-r--r--packages/SystemUI/res/layout/tv_audio_recording_indicator.xml81
-rw-r--r--packages/SystemUI/res/values/colors_tv.xml2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java207
5 files changed, 97 insertions, 245 deletions
diff --git a/packages/SystemUI/res/drawable/tv_rect_dark_left_rounded.xml b/packages/SystemUI/res/drawable/tv_rect_dark_left_rounded.xml
deleted file mode 100644
index 9b48a70d9439..000000000000
--- a/packages/SystemUI/res/drawable/tv_rect_dark_left_rounded.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2019 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.
- -->
-
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle">
-
- <corners
- android:bottomLeftRadius="8dp"
- android:topLeftRadius="8dp" />
- <solid android:color="@color/tv_audio_recording_indicator_background" />
-
-</shape> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/tv_rect_dark_right_rounded.xml b/packages/SystemUI/res/drawable/tv_rect_dark_right_rounded.xml
deleted file mode 100644
index 03348756231b..000000000000
--- a/packages/SystemUI/res/drawable/tv_rect_dark_right_rounded.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2019 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.
- -->
-
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle">
-
- <corners
- android:bottomRightRadius="8dp"
- android:topRightRadius="8dp" />
- <solid android:color="@color/tv_audio_recording_indicator_background" />
-
-</shape> \ No newline at end of file
diff --git a/packages/SystemUI/res/layout/tv_audio_recording_indicator.xml b/packages/SystemUI/res/layout/tv_audio_recording_indicator.xml
index f9336a540376..b62018d7cb9e 100644
--- a/packages/SystemUI/res/layout/tv_audio_recording_indicator.xml
+++ b/packages/SystemUI/res/layout/tv_audio_recording_indicator.xml
@@ -22,80 +22,17 @@
android:padding="12dp">
<FrameLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content">
+ android:layout_width="34dp"
+ android:layout_height="24dp"
+ android:layout_gravity="center"
+ android:background="@drawable/tv_rect_shadow_rounded">
- <LinearLayout
- android:id="@+id/icon_texts_container"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="horizontal">
-
- <FrameLayout
- android:layout_width="wrap_content"
- android:layout_height="match_parent">
-
- <View
- android:id="@+id/icon_container_bg"
- android:layout_width="50dp"
- android:layout_height="match_parent"
- android:background="@drawable/tv_rect_dark_left_rounded"/>
-
- <FrameLayout
- android:id="@+id/icon_mic"
- android:layout_width="34dp"
- android:layout_height="24dp"
- android:layout_gravity="center"
- android:background="@drawable/tv_rect_shadow_rounded">
-
- <ImageView
- android:layout_width="13dp"
- android:layout_height="13dp"
- android:layout_gravity="center"
- android:background="@drawable/tv_ic_mic_white"/>
- </FrameLayout>
-
- </FrameLayout>
-
- <LinearLayout
- android:id="@+id/texts_container"
- android:layout_width="wrap_content"
- android:layout_height="47dp"
- android:background="@color/tv_audio_recording_indicator_background"
- android:orientation="vertical"
- android:visibility="visible">
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="14dp"
- android:layout_marginTop="10dp"
- android:layout_marginBottom="1dp"
- android:text="@string/mic_active"
- android:textColor="@android:color/white"
- android:fontFamily="sans-serif"
- android:textSize="10dp"/>
-
- <TextView
- android:id="@+id/text"
- android:layout_width="wrap_content"
- android:layout_height="14dp"
- android:singleLine="true"
- android:text="SomeApplication accessed your microphone"
- android:textColor="@android:color/white"
- android:fontFamily="sans-serif"
- android:textSize="8dp"/>
-
- </LinearLayout>
-
- </LinearLayout>
+ <ImageView
+ android:layout_width="13dp"
+ android:layout_height="13dp"
+ android:layout_gravity="center"
+ android:src="@drawable/tv_ic_mic_white"/>
</FrameLayout>
- <View
- android:id="@+id/bg_end"
- android:layout_width="12dp"
- android:layout_height="47dp"
- android:background="@drawable/tv_rect_dark_right_rounded"
- android:visibility="visible"/>
-
</LinearLayout>
diff --git a/packages/SystemUI/res/values/colors_tv.xml b/packages/SystemUI/res/values/colors_tv.xml
index cb49918e4e3f..1177bb5757c2 100644
--- a/packages/SystemUI/res/values/colors_tv.xml
+++ b/packages/SystemUI/res/values/colors_tv.xml
@@ -22,8 +22,6 @@
<color name="recents_tv_dismiss_text_color">#7FEEEEEE</color>
<color name="recents_tv_text_shadow_color">#7F000000</color>
- <!-- Background color for audio recording indicator (G800) -->
- <color name="tv_audio_recording_indicator_background">#FF3C4043</color>
<color name="tv_audio_recording_indicator_icon_background">#CC000000</color>
<color name="tv_audio_recording_indicator_stroke">#33FFFFFF</color>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java
index a29db4d98329..7aeca64ba9e8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java
@@ -21,7 +21,6 @@ import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
-import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.annotation.IntDef;
import android.annotation.UiThread;
@@ -36,7 +35,6 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
-import android.widget.TextView;
import com.android.systemui.R;
import com.android.systemui.statusbar.tv.TvStatusBar;
@@ -83,19 +81,14 @@ public class AudioRecordingDisclosureBar implements
private static final int STATE_SHOWN = 2;
private static final int STATE_DISAPPEARING = 3;
- private static final int ANIMATION_DURATION = 600;
+ private static final int ANIMATION_DURATION_MS = 200;
private final Context mContext;
private boolean mIsEnabled;
private View mIndicatorView;
- private View mIconTextsContainer;
- private View mIconContainerBg;
- private View mIcon;
- private View mBgEnd;
- private View mTextsContainers;
- private TextView mTextView;
- private boolean mIsLtr;
+ private boolean mViewAndWindowAdded;
+ private ObjectAnimator mAnimator;
@State private int mState = STATE_STOPPED;
@@ -190,7 +183,7 @@ public class AudioRecordingDisclosureBar implements
}
if (active) {
- showIfNotShown();
+ showIfNeeded();
} else {
hideIndicatorIfNeeded();
}
@@ -198,153 +191,132 @@ public class AudioRecordingDisclosureBar implements
@UiThread
private void hideIndicatorIfNeeded() {
- // If not STATE_APPEARING, will check whether the indicator should be hidden when the
- // indicator comes to the STATE_SHOWN.
- // If STATE_DISAPPEARING or STATE_SHOWN - nothing else for us to do here.
- if (mState != STATE_SHOWN) return;
-
- // If is in the STATE_SHOWN and there are no active recorders - hide.
- if (!hasActiveRecorders()) {
- hide();
+ // If STOPPED, NOT_SHOWN or DISAPPEARING - nothing else for us to do here.
+ if (mState != STATE_SHOWN && mState != STATE_APPEARING) return;
+
+ if (hasActiveRecorders()) {
+ return;
+ }
+
+ if (mViewAndWindowAdded) {
+ mState = STATE_DISAPPEARING;
+ animateDisappearance();
+ } else {
+ // Appearing animation has not started yet, as we were still waiting for the View to be
+ // laid out.
+ mState = STATE_NOT_SHOWN;
+ removeIndicatorView();
}
}
@UiThread
- private void showIfNotShown() {
- if (mState != STATE_NOT_SHOWN) return;
+ private void showIfNeeded() {
+ // If STOPPED, SHOWN or APPEARING - nothing else for us to do here.
+ if (mState != STATE_NOT_SHOWN && mState != STATE_DISAPPEARING) return;
+
if (DEBUG) Log.d(TAG, "Showing indicator");
- mIsLtr = mContext.getResources().getConfiguration().getLayoutDirection()
- == View.LAYOUT_DIRECTION_LTR;
+ final int prevState = mState;
+ mState = STATE_APPEARING;
+
+ if (prevState == STATE_DISAPPEARING) {
+ animateAppearance();
+ return;
+ }
// Inflate the indicator view
mIndicatorView = LayoutInflater.from(mContext).inflate(
- R.layout.tv_audio_recording_indicator,
- null);
- mIconTextsContainer = mIndicatorView.findViewById(R.id.icon_texts_container);
- mIconContainerBg = mIconTextsContainer.findViewById(R.id.icon_container_bg);
- mIcon = mIconTextsContainer.findViewById(R.id.icon_mic);
- mTextsContainers = mIconTextsContainer.findViewById(R.id.texts_container);
- mTextView = mTextsContainers.findViewById(R.id.text);
- mBgEnd = mIndicatorView.findViewById(R.id.bg_end);
-
- mTextsContainers.setVisibility(View.GONE);
- mIconContainerBg.setVisibility(View.GONE);
- mTextView.setVisibility(View.GONE);
- mBgEnd.setVisibility(View.GONE);
- mTextsContainers = null;
- mIconContainerBg = null;
- mTextView = null;
- mBgEnd = null;
-
- // Initially change the visibility to INVISIBLE, wait until and receives the size and
- // then animate it moving from "off" the screen correctly
- mIndicatorView.setVisibility(View.INVISIBLE);
+ R.layout.tv_audio_recording_indicator, null);
+
+ // 1. Set alpha to 0.
+ // 2. Wait until the window is shown and the view is laid out.
+ // 3. Start a "fade in" (alpha) animation.
+ mIndicatorView.setAlpha(0f);
mIndicatorView
.getViewTreeObserver()
.addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
- if (mState == STATE_STOPPED) {
- return;
- }
+ // State could have changed to NOT_SHOWN (if all the recorders are
+ // already gone) to STOPPED (if the indicator was disabled)
+ if (mState != STATE_APPEARING) return;
+ mViewAndWindowAdded = true;
// Remove the observer
mIndicatorView.getViewTreeObserver().removeOnGlobalLayoutListener(
this);
- // Now that the width of the indicator has been assigned, we can
- // move it in from off the screen.
- final int initialOffset =
- (mIsLtr ? 1 : -1) * mIndicatorView.getWidth();
- final AnimatorSet set = new AnimatorSet();
- set.setDuration(ANIMATION_DURATION);
- set.playTogether(
- ObjectAnimator.ofFloat(mIndicatorView,
- View.TRANSLATION_X, initialOffset, 0),
- ObjectAnimator.ofFloat(mIndicatorView, View.ALPHA, 0f,
- 1f));
- set.addListener(
- new AnimatorListenerAdapter() {
- @Override
- public void onAnimationStart(Animator animation,
- boolean isReverse) {
- if (mState == STATE_STOPPED) return;
-
- // Indicator is INVISIBLE at the moment, change it.
- mIndicatorView.setVisibility(View.VISIBLE);
- }
-
- @Override
- public void onAnimationEnd(Animator animation) {
- onAppeared();
- }
- });
- set.start();
+ animateAppearance();
}
});
+ final boolean isLtr = mContext.getResources().getConfiguration().getLayoutDirection()
+ == View.LAYOUT_DIRECTION_LTR;
final WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(
WRAP_CONTENT,
WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
- layoutParams.gravity = Gravity.TOP | (mIsLtr ? Gravity.RIGHT : Gravity.LEFT);
+ layoutParams.gravity = Gravity.TOP | (isLtr ? Gravity.RIGHT : Gravity.LEFT);
layoutParams.setTitle(LAYOUT_PARAMS_TITLE);
layoutParams.packageName = mContext.getPackageName();
final WindowManager windowManager = (WindowManager) mContext.getSystemService(
Context.WINDOW_SERVICE);
windowManager.addView(mIndicatorView, layoutParams);
-
- mState = STATE_APPEARING;
}
- @UiThread
- private void hide() {
- if (DEBUG) Log.d(TAG, "Hide indicator");
-
- final int targetOffset = (mIsLtr ? 1 : -1) * (mIndicatorView.getWidth()
- - (int) mIconTextsContainer.getTranslationX());
- final AnimatorSet set = new AnimatorSet();
- set.playTogether(
- ObjectAnimator.ofFloat(mIndicatorView, View.TRANSLATION_X, targetOffset),
- ObjectAnimator.ofFloat(mIcon, View.ALPHA, 0f));
- set.setDuration(ANIMATION_DURATION);
- set.addListener(
- new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- onHidden();
- }
- });
- set.start();
- mState = STATE_DISAPPEARING;
+ private void animateAppearance() {
+ animateAlphaTo(1f);
}
+ private void animateDisappearance() {
+ animateAlphaTo(0f);
+ }
- @UiThread
- private void onAppeared() {
- if (mState == STATE_STOPPED) return;
+ private void animateAlphaTo(final float endValue) {
+ if (mAnimator == null) {
+ if (DEBUG) Log.d(TAG, "set up animator");
- mState = STATE_SHOWN;
+ mAnimator = new ObjectAnimator();
+ mAnimator.setTarget(mIndicatorView);
+ mAnimator.setProperty(View.ALPHA);
+ mAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animation, boolean isReverse) {
+ if (DEBUG) Log.d(TAG, "onAnimationStart");
+ }
- hideIndicatorIfNeeded();
- }
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ if (DEBUG) Log.d(TAG, "onAnimationCancel");
+ }
- @UiThread
- private void onHidden() {
- if (mState == STATE_STOPPED) return;
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (DEBUG) Log.d(TAG, "onAnimationEnd");
+
+ if (mState == STATE_APPEARING) {
+ mState = STATE_SHOWN;
+ } else if (mState == STATE_DISAPPEARING) {
+ removeIndicatorView();
+ mState = STATE_NOT_SHOWN;
+ }
+ }
+ });
+ } else if (mAnimator.isRunning()) {
+ if (DEBUG) Log.d(TAG, "cancel running animation");
+ mAnimator.cancel();
+ }
- removeIndicatorView();
- mState = STATE_NOT_SHOWN;
+ final float currentValue = mIndicatorView.getAlpha();
+ if (DEBUG) Log.d(TAG, "animate alpha to " + endValue + " from " + currentValue);
- if (hasActiveRecorders()) {
- // Got new recorders, show again.
- showIfNotShown();
- }
+ mAnimator.setDuration((int) (Math.abs(currentValue - endValue) * ANIMATION_DURATION_MS));
+ mAnimator.setFloatValues(endValue);
+ mAnimator.start();
}
private boolean hasActiveRecorders() {
@@ -363,12 +335,9 @@ public class AudioRecordingDisclosureBar implements
windowManager.removeView(mIndicatorView);
mIndicatorView = null;
- mIconTextsContainer = null;
- mIconContainerBg = null;
- mIcon = null;
- mTextsContainers = null;
- mTextView = null;
- mBgEnd = null;
+ mAnimator = null;
+
+ mViewAndWindowAdded = false;
}
private static List<String> splitByComma(String string) {