summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Bryan Eyler <bryaneyler@google.com> 2017-08-08 16:53:33 -0700
committer Bryan Eyler <bryaneyler@google.com> 2017-08-17 13:36:59 -0700
commit2ff95846dae60c6c4ddffa3ce5a34687d9f88d3b (patch)
treed7d4a77b91a34f37d119948f921ab0845ca55cd1
parent1b08a4a8a3271f04b98c34747fe077610b7ee534 (diff)
Add user selection to car status bar and animate.
Adds the UserGridView to the car status bar and adds an animation when expanding/hiding. Bug: 63593747 Tested on Mojave with the fullscreen user switcher and status bar. Change-Id: If6ddbd4da896c5eb661393dcc35ab299361754e9
-rw-r--r--packages/SystemUI/res/layout/car_qs_panel.xml7
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java22
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridView.java113
5 files changed, 143 insertions, 13 deletions
diff --git a/packages/SystemUI/res/layout/car_qs_panel.xml b/packages/SystemUI/res/layout/car_qs_panel.xml
index d1f7ff83db93..0b46b0bdaa1c 100644
--- a/packages/SystemUI/res/layout/car_qs_panel.xml
+++ b/packages/SystemUI/res/layout/car_qs_panel.xml
@@ -24,4 +24,11 @@
<include layout="@layout/car_status_bar_header" />
<include layout="@layout/car_qs_footer" />
+
+ <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" />
</LinearLayout>
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 9730f29da977..d42b87bcef28 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java
@@ -18,6 +18,7 @@ import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
+import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;
@@ -27,6 +28,7 @@ import com.android.systemui.R;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.qs.QSFooter;
import com.android.systemui.qs.QSPanel;
+import com.android.systemui.statusbar.car.UserGridView;
import com.android.systemui.statusbar.phone.MultiUserSwitch;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.UserInfoController;
@@ -37,10 +39,13 @@ import com.android.systemui.statusbar.policy.UserInfoController;
*/
public class CarQSFooter extends RelativeLayout implements QSFooter,
UserInfoController.OnUserInfoChangedListener {
+ private static final String TAG = "CarQSFooter";
+
private UserInfoController mUserInfoController;
private MultiUserSwitch mMultiUserSwitch;
private ImageView mMultiUserAvatar;
+ private UserGridView mUserGridView;
public CarQSFooter(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -54,6 +59,19 @@ public class CarQSFooter extends RelativeLayout implements QSFooter,
mUserInfoController = Dependency.get(UserInfoController.class);
+ mMultiUserSwitch.setOnClickListener(v -> {
+ if (mUserGridView == null) {
+ Log.e(TAG, "CarQSFooter not properly set up; cannot display user switcher.");
+ return;
+ }
+
+ if (!mUserGridView.isShowing()) {
+ mUserGridView.show();
+ } else {
+ mUserGridView.hide();
+ }
+ });
+
findViewById(R.id.settings_button).setOnClickListener(v -> {
ActivityStarter activityStarter = Dependency.get(ActivityStarter.class);
@@ -80,6 +98,10 @@ public class CarQSFooter extends RelativeLayout implements QSFooter,
}
}
+ public void setUserGridView(UserGridView view) {
+ mUserGridView = view;
+ }
+
@Override
public void setListening(boolean listening) {
if (listening) {
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 7c2a8129813a..13298d378845 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java
@@ -22,9 +22,12 @@ import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
+import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.qs.QSFooter;
+import com.android.systemui.statusbar.car.UserGridView;
+import com.android.systemui.statusbar.policy.UserSwitcherController;
/**
* A quick settings fragment for the car. For auto, there is no row for quick settings or ability
@@ -33,7 +36,8 @@ import com.android.systemui.qs.QSFooter;
*/
public class CarQSFragment extends Fragment implements QS {
private View mHeader;
- private QSFooter mFooter;
+ private CarQSFooter mFooter;
+ private UserGridView mUserGridView;
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@@ -46,6 +50,12 @@ public class CarQSFragment extends Fragment implements QS {
super.onViewCreated(view, savedInstanceState);
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 */);
+
+ mFooter.setUserGridView(mUserGridView);
}
@Override
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 6060134de6da..172c62a99db2 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 @@ public class FullscreenUserSwitcher {
mParent = containerStub.inflate();
mContainer = mParent.findViewById(R.id.container);
mUserGridView = mContainer.findViewById(R.id.user_grid);
- mUserGridView.init(statusBar, mUserSwitcherController);
+ mUserGridView.init(statusBar, mUserSwitcherController, true /* showInitially */);
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 f178aa634247..e551801ca434 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridView.java
@@ -16,20 +16,21 @@
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;
import android.graphics.Canvas;
-import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
-import android.os.UserHandle;
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.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -37,9 +38,7 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
-import com.android.internal.util.UserIcons;
import com.android.systemui.R;
-import com.android.systemui.statusbar.UserUtil;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.policy.UserSwitcherController;
@@ -48,21 +47,44 @@ import com.android.systemui.statusbar.policy.UserSwitcherController;
* 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) {
+ public void init(StatusBar statusBar, UserSwitcherController userSwitcherController,
+ boolean showInitially) {
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) {
@@ -83,16 +105,85 @@ public class UserGridView extends ViewPager {
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// Wrap content doesn't work in ViewPagers, so simulate the behavior in code.
int height = 0;
- for(int i = 0; i < getChildCount(); i++) {
- View child = getChildAt(i);
- child.measure(widthMeasureSpec,
- MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
- height = Math.max(child.getMeasuredHeight(), height);
+ if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY) {
+ height = MeasureSpec.getSize(heightMeasureSpec);
+ } else {
+ for (int i = 0; i < getChildCount(); i++) {
+ View child = getChildAt(i);
+ child.measure(widthMeasureSpec,
+ MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
+ 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);
+ }
}
heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
+
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