Merge "Add user selection to car status bar and animate." into oc-mr1-dev
am: 04d69537ea
Change-Id: I1afa270c8a2f22c1cb2f8e38248b50333d52b01b
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user