Merge "Add user selection to car status bar and animate." into oc-mr1-dev

am: 04d69537ea

Change-Id: I1afa270c8a2f22c1cb2f8e38248b50333d52b01b
This commit is contained in:
Bryan Eyler
2017-08-17 23:47:44 +00:00
committed by android-build-merger
5 changed files with 143 additions and 13 deletions

View File

@@ -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>

View File

@@ -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) {

View File

@@ -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

View File

@@ -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);

View File

@@ -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