Add pagination dots and fix animation of user switcher.
- Adds pagination dots to user switcher dropdown.
- Adds device name text view for when devices are associated with users.
- Fixes the layout of the user grid to handle changing height for
proper animation.
Bug: 65423882
Tested on Mojave with longer animation times to ensure correctness.
Change-Id: I54ae5cc93f9caa9d6c4a5c2c7e9e2488a6257001
(cherry picked from commit 0de35b5386ad7e00f13a7611fce36ca990b201e0)
diff --git a/packages/SystemUI/res/anim/car_user_switcher_close_animation.xml b/packages/SystemUI/res/anim/car_user_switcher_close_animation.xml
new file mode 100644
index 0000000..da92e85
--- /dev/null
+++ b/packages/SystemUI/res/anim/car_user_switcher_close_animation.xml
@@ -0,0 +1,20 @@
+<!-- Copyright (C) 2017 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.
+-->
+ <animator xmlns:android="http://schemas.android.com/apk/res/android"
+ android:duration="133"
+ android:valueType="intType"
+ android:valueFrom="@dimen/car_user_switcher_container_height"
+ android:valueTo="0"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
diff --git a/packages/SystemUI/res/anim/car_user_switcher_open_animation.xml b/packages/SystemUI/res/anim/car_user_switcher_open_animation.xml
new file mode 100644
index 0000000..8b0e4a5
--- /dev/null
+++ b/packages/SystemUI/res/anim/car_user_switcher_open_animation.xml
@@ -0,0 +1,20 @@
+<!-- Copyright (C) 2017 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.
+-->
+ <animator xmlns:android="http://schemas.android.com/apk/res/android"
+ android:duration="200"
+ android:valueType="intType"
+ android:valueFrom="0"
+ android:valueTo="@dimen/car_user_switcher_container_height"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
diff --git a/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml b/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml
index 2f16516..bc5d37c 100644
--- a/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml
+++ b/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml
@@ -15,27 +15,38 @@
limitations under the License.
-->
-<LinearLayout
+<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:gravity="center" >
+ android:layout_height="@dimen/car_fullscreen_user_pod_height"
+ android:layout_gravity="center_horizontal|bottom" >
<ImageView android:id="@+id/user_avatar"
- android:layout_gravity="center"
+ android:layout_centerHorizontal="true"
+ android:layout_marginTop="@dimen/car_fullscreen_user_pod_margin_image_top"
android:layout_width="@dimen/car_fullscreen_user_pod_image_avatar_width"
- android:layout_height="@dimen/car_fullscreen_user_pod_image_avatar_height" />
+ android:layout_height="@dimen/car_fullscreen_user_pod_image_avatar_height"
+ android:layout_above="@id/user_name" />
<TextView android:id="@+id/user_name"
android:layout_width="@dimen/car_fullscreen_user_pod_width"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/car_fullscreen_user_pod_margin_name_top"
android:layout_marginBottom="@dimen/car_fullscreen_user_pod_margin_name_bottom"
- android:textSize="@dimen/car_fullscreen_user_pod_text_size"
+ android:textSize="@dimen/car_fullscreen_user_pod_name_text_size"
android:textColor="@color/qs_user_detail_name"
android:ellipsize="end"
android:singleLine="true"
android:gravity="center_horizontal"
- android:layout_gravity="center_horizontal" />
-</LinearLayout>
+ android:layout_above="@id/device_name" />
+
+ <TextView android:id="@+id/device_name"
+ android:layout_width="@dimen/car_fullscreen_user_pod_width"
+ android:layout_height="wrap_content"
+ android:textSize="@dimen/car_fullscreen_user_pod_device_text_size"
+ android:textColor="@color/qs_user_detail_name"
+ android:ellipsize="end"
+ android:singleLine="true"
+ android:gravity="center_horizontal"
+ android:layout_alignParentBottom="true" />
+</RelativeLayout>
diff --git a/packages/SystemUI/res/layout/car_fullscreen_user_pod_container.xml b/packages/SystemUI/res/layout/car_fullscreen_user_pod_container.xml
index 99d010f..2f6ad2c 100644
--- a/packages/SystemUI/res/layout/car_fullscreen_user_pod_container.xml
+++ b/packages/SystemUI/res/layout/car_fullscreen_user_pod_container.xml
@@ -18,8 +18,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:gravity="center"
- android:layout_gravity="center" >
+ android:gravity="center" >
<!-- car_fullscreen_user_pods will be dynamically added here. -->
</LinearLayout>
diff --git a/packages/SystemUI/res/layout/car_fullscreen_user_switcher.xml b/packages/SystemUI/res/layout/car_fullscreen_user_switcher.xml
index 257e281..478b656 100644
--- a/packages/SystemUI/res/layout/car_fullscreen_user_switcher.xml
+++ b/packages/SystemUI/res/layout/car_fullscreen_user_switcher.xml
@@ -54,13 +54,13 @@
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/car_margin"
android:layout_marginRight="@dimen/car_margin"
+ android:layout_marginBottom="@dimen/car_user_grid_margin_bottom"
android:layout_centerInParent="true" />
<com.android.systemui.statusbar.car.PageIndicator
android:id="@+id/user_switcher_page_indicator"
android:layout_width="match_parent"
android:layout_height="@dimen/car_page_indicator_dot_diameter"
- android:layout_marginTop="@dimen/car_page_indicator_margin_top"
android:layout_below="@+id/user_grid" />
<Button
diff --git a/packages/SystemUI/res/layout/car_qs_panel.xml b/packages/SystemUI/res/layout/car_qs_panel.xml
index 4cb0fd5..1eb88a1 100644
--- a/packages/SystemUI/res/layout/car_qs_panel.xml
+++ b/packages/SystemUI/res/layout/car_qs_panel.xml
@@ -26,10 +26,29 @@
<include layout="@layout/car_status_bar_header"/>
<include layout="@layout/car_qs_footer"/>
- <com.android.systemui.statusbar.car.UserGridView
- android:id="@+id/user_grid"
+ <RelativeLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/user_switcher_container"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginLeft="@dimen/car_margin"
- android:layout_marginRight="@dimen/car_margin" />
+ android:layout_height="@dimen/car_user_switcher_container_height"
+ android:layout_gravity="center_horizontal" >
+
+ <com.android.systemui.statusbar.car.UserGridView
+ android:id="@+id/user_grid"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="@dimen/car_margin"
+ android:layout_marginRight="@dimen/car_margin"
+ android:layout_marginBottom="@dimen/car_user_grid_margin_bottom"
+ android:layout_above="@id/user_switcher_page_indicator" />
+
+ <com.android.systemui.statusbar.car.PageIndicator
+ android:id="@+id/user_switcher_page_indicator"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/car_page_indicator_dot_diameter"
+ android:layout_marginBottom="@dimen/car_page_indicator_margin_bottom"
+ android:layout_alignParentBottom="true" />
+
+ </RelativeLayout>
+
</LinearLayout>
diff --git a/packages/SystemUI/res/values/dimens_car.xml b/packages/SystemUI/res/values/dimens_car.xml
index 8853587..96bcddc 100644
--- a/packages/SystemUI/res/values/dimens_car.xml
+++ b/packages/SystemUI/res/values/dimens_car.xml
@@ -18,20 +18,23 @@
<resources>
<dimen name="car_margin">148dp</dimen>
+ <dimen name="car_fullscreen_user_pod_margin_image_top">24dp</dimen>
<dimen name="car_fullscreen_user_pod_margin_name_top">24dp</dimen>
- <dimen name="car_fullscreen_user_pod_margin_name_bottom">64dp</dimen>
+ <dimen name="car_fullscreen_user_pod_margin_name_bottom">20dp</dimen>
<dimen name="car_fullscreen_user_pod_margin_between">24dp</dimen>
<dimen name="car_fullscreen_user_pod_icon_text_size">96dp</dimen>
<dimen name="car_fullscreen_user_pod_image_avatar_width">192dp</dimen>
<dimen name="car_fullscreen_user_pod_image_avatar_height">192dp</dimen>
<dimen name="car_fullscreen_user_pod_width">264dp</dimen>
- <dimen name="car_fullscreen_user_pod_text_size">40sp</dimen> <!-- B1 -->
+ <dimen name="car_fullscreen_user_pod_height">356dp</dimen>
+ <dimen name="car_fullscreen_user_pod_name_text_size">40sp</dimen> <!-- B1 -->
+ <dimen name="car_fullscreen_user_pod_device_text_size">@dimen/car_body2_size</dimen>
<dimen name="car_navigation_button_width">64dp</dimen>
<dimen name="car_navigation_bar_width">760dp</dimen>
<dimen name="car_page_indicator_dot_diameter">12dp</dimen>
- <dimen name="car_page_indicator_margin_top">32dp</dimen>
+ <dimen name="car_page_indicator_margin_bottom">24dp</dimen>
<dimen name="car_user_switcher_progress_bar_height">6dp</dimen>
<dimen name="car_user_switcher_progress_bar_margin_top">@dimen/status_bar_height</dimen>
@@ -50,5 +53,8 @@
<dimen name="car_qs_footer_user_switch_margin_right">46dp</dimen>
<dimen name="car_qs_footer_user_name_text_size">@dimen/car_body2_size</dimen>
+ <dimen name="car_user_switcher_container_height">420dp</dimen>
+ <dimen name="car_user_grid_margin_bottom">28dp</dimen>
+
<dimen name="car_body2_size">26sp</dimen>
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java
index 142aab2..23d3ebbb 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java
@@ -47,7 +47,7 @@
private MultiUserSwitch mMultiUserSwitch;
private TextView mUserName;
private ImageView mMultiUserAvatar;
- private UserGridView mUserGridView;
+ private CarQSFragment.UserSwitchCallback mUserSwitchCallback;
public CarQSFooter(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -63,15 +63,15 @@
mUserInfoController = Dependency.get(UserInfoController.class);
mMultiUserSwitch.setOnClickListener(v -> {
- if (mUserGridView == null) {
+ if (mUserSwitchCallback == null) {
Log.e(TAG, "CarQSFooter not properly set up; cannot display user switcher.");
return;
}
- if (!mUserGridView.isShowing()) {
- mUserGridView.show();
+ if (!mUserSwitchCallback.isShowing()) {
+ mUserSwitchCallback.show();
} else {
- mUserGridView.hide();
+ mUserSwitchCallback.hide();
}
});
@@ -102,8 +102,8 @@
}
}
- public void setUserGridView(UserGridView view) {
- mUserGridView = view;
+ public void setUserSwitchCallback(CarQSFragment.UserSwitchCallback callback) {
+ mUserSwitchCallback = callback;
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java
index 13298d3..58a621a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java
@@ -13,6 +13,10 @@
*/
package com.android.systemui.qs.car;
+import android.animation.Animator;
+import android.animation.AnimatorInflater;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
import android.app.Fragment;
import android.os.Bundle;
import android.support.annotation.Nullable;
@@ -26,6 +30,7 @@
import com.android.systemui.R;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.qs.QSFooter;
+import com.android.systemui.statusbar.car.PageIndicator;
import com.android.systemui.statusbar.car.UserGridView;
import com.android.systemui.statusbar.policy.UserSwitcherController;
@@ -36,8 +41,11 @@
*/
public class CarQSFragment extends Fragment implements QS {
private View mHeader;
+ private View mUserSwitcherContainer;
private CarQSFooter mFooter;
private UserGridView mUserGridView;
+ private PageIndicator mPageIndicator;
+ private ValueAnimator mHeightAnimator;
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@@ -51,11 +59,17 @@
mHeader = view.findViewById(R.id.header);
mFooter = view.findViewById(R.id.qs_footer);
- mUserGridView = view.findViewById(R.id.user_grid);
- mUserGridView.init(null, Dependency.get(UserSwitcherController.class),
- false /* showInitially */);
+ mUserSwitcherContainer = view.findViewById(R.id.user_switcher_container);
- mFooter.setUserGridView(mUserGridView);
+ updateUserSwitcherHeight(0);
+
+ mUserGridView = view.findViewById(R.id.user_grid);
+ mUserGridView.init(null, Dependency.get(UserSwitcherController.class));
+
+ mPageIndicator = view.findViewById(R.id.user_switcher_page_indicator);
+ mPageIndicator.setupWithViewPager(mUserGridView);
+
+ mFooter.setUserSwitchCallback(new UserSwitchCallback());
}
@Override
@@ -171,4 +185,49 @@
public void setExpandClickListener(OnClickListener onClickListener) {
// No ability to expand the quick settings.
}
+
+ public class UserSwitchCallback {
+ private boolean mShowing;
+
+ public boolean isShowing() {
+ return mShowing;
+ }
+
+ public void show() {
+ mShowing = true;
+ animateHeightChange(true /* opening */);
+ }
+
+ public void hide() {
+ mShowing = false;
+ animateHeightChange(false /* opening */);
+ }
+ }
+
+ private void updateUserSwitcherHeight(int height) {
+ ViewGroup.LayoutParams layoutParams = mUserSwitcherContainer.getLayoutParams();
+ layoutParams.height = height;
+ mUserSwitcherContainer.requestLayout();
+ }
+
+ private void animateHeightChange(boolean opening) {
+ // Animation in progress; cancel it to avoid contention.
+ if (mHeightAnimator != null){
+ mHeightAnimator.cancel();
+ }
+
+ mHeightAnimator = (ValueAnimator) AnimatorInflater.loadAnimator(getContext(),
+ opening ? R.anim.car_user_switcher_open_animation
+ : R.anim.car_user_switcher_close_animation);
+ mHeightAnimator.addUpdateListener(valueAnimator -> {
+ updateUserSwitcherHeight((Integer)valueAnimator.getAnimatedValue());
+ });
+ mHeightAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mHeightAnimator = null;
+ }
+ });
+ mHeightAnimator.start();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
index 172c62a..6060134 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
@@ -53,7 +53,7 @@
mParent = containerStub.inflate();
mContainer = mParent.findViewById(R.id.container);
mUserGridView = mContainer.findViewById(R.id.user_grid);
- mUserGridView.init(statusBar, mUserSwitcherController, true /* showInitially */);
+ mUserGridView.init(statusBar, mUserSwitcherController);
mUserGridView.setUserSelectionListener(record -> {
if (!record.isCurrent) {
toggleSwitchInProgress(true);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridView.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridView.java
index e551801..e241177 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridView.java
@@ -16,9 +16,6 @@
package com.android.systemui.statusbar.car;
-import android.animation.Animator;
-import android.animation.Animator.AnimatorListener;
-import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
@@ -29,13 +26,11 @@
import android.graphics.drawable.GradientDrawable;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
-import android.support.v4.view.animation.FastOutSlowInInterpolator;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
-import android.widget.LinearLayout;
import android.widget.TextView;
import com.android.systemui.R;
@@ -47,44 +42,21 @@
* One of the uses of this is for the lock screen in auto.
*/
public class UserGridView extends ViewPager {
- private static final int EXPAND_ANIMATION_TIME_MS = 200;
- private static final int HIDE_ANIMATION_TIME_MS = 133;
-
private StatusBar mStatusBar;
private UserSwitcherController mUserSwitcherController;
private Adapter mAdapter;
private UserSelectionListener mUserSelectionListener;
- private ValueAnimator mHeightAnimator;
- private int mTargetHeight;
- private int mHeightChildren;
- private boolean mShowing;
public UserGridView(Context context, AttributeSet attrs) {
super(context, attrs);
}
- public void init(StatusBar statusBar, UserSwitcherController userSwitcherController,
- boolean showInitially) {
+ public void init(StatusBar statusBar, UserSwitcherController userSwitcherController) {
mStatusBar = statusBar;
mUserSwitcherController = userSwitcherController;
mAdapter = new Adapter(mUserSwitcherController);
addOnLayoutChangeListener(mAdapter);
setAdapter(mAdapter);
- mShowing = showInitially;
- }
-
- public boolean isShowing() {
- return mShowing;
- }
-
- public void show() {
- mShowing = true;
- animateHeightChange(getMeasuredHeight(), mHeightChildren);
- }
-
- public void hide() {
- mShowing = false;
- animateHeightChange(getMeasuredHeight(), 0);
}
public void onUserSwitched(int newUserId) {
@@ -115,13 +87,6 @@
height = Math.max(child.getMeasuredHeight(), height);
}
- mHeightChildren = height;
-
- // Override the height if it's not showing.
- if (!mShowing) {
- height = 0;
- }
-
// Respect the AT_MOST request from parent.
if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST) {
height = Math.min(MeasureSpec.getSize(heightMeasureSpec), height);
@@ -132,58 +97,6 @@
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
- private void animateHeightChange(int oldHeight, int newHeight) {
- // If there is no change in height or an animation is already in progress towards the
- // desired height, then there's no need to make any changes.
- if (oldHeight == newHeight || newHeight == mTargetHeight) {
- return;
- }
-
- // Animation in progress is not going towards the new target, so cancel it.
- if (mHeightAnimator != null){
- mHeightAnimator.cancel();
- }
-
- mTargetHeight = newHeight;
- mHeightAnimator = ValueAnimator.ofInt(oldHeight, mTargetHeight);
- mHeightAnimator.addUpdateListener(valueAnimator -> {
- ViewGroup.LayoutParams layoutParams = getLayoutParams();
- layoutParams.height = (Integer) valueAnimator.getAnimatedValue();
- requestLayout();
- });
- mHeightAnimator.addListener(new AnimatorListener() {
- @Override
- public void onAnimationStart(Animator animator) {}
-
- @Override
- public void onAnimationEnd(Animator animator) {
- // ValueAnimator does not guarantee that the update listener will get an update
- // to the final value, so here, the final value is set. Though the final calculated
- // height (mTargetHeight) could be set, WRAP_CONTENT is more appropriate.
- ViewGroup.LayoutParams layoutParams = getLayoutParams();
- layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
- requestLayout();
- mHeightAnimator = null;
- }
-
- @Override
- public void onAnimationCancel(Animator animator) {}
-
- @Override
- public void onAnimationRepeat(Animator animator) {}
- });
-
- mHeightAnimator.setInterpolator(new FastOutSlowInInterpolator());
- if (oldHeight < newHeight) {
- // Expanding
- mHeightAnimator.setDuration(EXPAND_ANIMATION_TIME_MS);
- } else {
- // Hiding
- mHeightAnimator.setDuration(HIDE_ANIMATION_TIME_MS);
- }
- mHeightAnimator.start();
- }
-
/**
* This is a ViewPager.PagerAdapter which deletegates the work to a
* UserSwitcherController.BaseUserAdapter. Java doesn't support multiple inheritance so we have
@@ -245,8 +158,8 @@
// to work for whatever reason. Instead, set a right margin on the pod if it's not
// the right-most pod and there is more than one pod in the container.
if (i < limit - 1 && limit > 1) {
- LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
- LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
+ ViewGroup.MarginLayoutParams params =
+ (ViewGroup.MarginLayoutParams) v.getLayoutParams();
params.setMargins(0, 0, mPodMarginBetween, 0);
v.setLayoutParams(params);
}