Merge "Enforce that the user switcher icons are circular" into pi-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
52edc7c2ad
@@ -38,6 +38,8 @@ import android.widget.TextView;
|
|||||||
|
|
||||||
import androidx.car.widget.PagedListView;
|
import androidx.car.widget.PagedListView;
|
||||||
|
|
||||||
|
import androidx.core.graphics.drawable.RoundedBitmapDrawable;
|
||||||
|
import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory;
|
||||||
import com.android.internal.util.UserIcons;
|
import com.android.internal.util.UserIcons;
|
||||||
import com.android.settingslib.users.UserManagerHelper;
|
import com.android.settingslib.users.UserManagerHelper;
|
||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
@@ -193,7 +195,10 @@ public class UserGridRecyclerView extends PagedListView implements
|
|||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(UserAdapterViewHolder holder, int position) {
|
public void onBindViewHolder(UserAdapterViewHolder holder, int position) {
|
||||||
UserRecord userRecord = mUsers.get(position);
|
UserRecord userRecord = mUsers.get(position);
|
||||||
holder.mUserAvatarImageView.setImageBitmap(getUserRecordIcon(userRecord));
|
RoundedBitmapDrawable circleIcon = RoundedBitmapDrawableFactory.create(mRes,
|
||||||
|
getUserRecordIcon(userRecord));
|
||||||
|
circleIcon.setCircular(true);
|
||||||
|
holder.mUserAvatarImageView.setImageDrawable(circleIcon);
|
||||||
holder.mUserNameTextView.setText(userRecord.mInfo.name);
|
holder.mUserNameTextView.setText(userRecord.mInfo.name);
|
||||||
holder.mView.setOnClickListener(v -> {
|
holder.mView.setOnClickListener(v -> {
|
||||||
if (userRecord == null) {
|
if (userRecord == null) {
|
||||||
|
|||||||
@@ -20,33 +20,41 @@ import android.content.Context;
|
|||||||
import android.content.pm.UserInfo;
|
import android.content.pm.UserInfo;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.BitmapFactory;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
|
import android.graphics.ColorFilter;
|
||||||
|
import android.graphics.Paint;
|
||||||
|
import android.graphics.Path;
|
||||||
|
import android.graphics.PixelFormat;
|
||||||
|
import android.graphics.PorterDuff;
|
||||||
|
import android.graphics.PorterDuffXfermode;
|
||||||
|
import android.graphics.Rect;
|
||||||
|
import android.graphics.RectF;
|
||||||
import android.graphics.drawable.ColorDrawable;
|
import android.graphics.drawable.ColorDrawable;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
import android.os.UserManager;
|
import android.os.UserManager;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import com.android.internal.R;
|
import com.android.internal.R;
|
||||||
import com.android.server.pm.UserManagerService;
|
|
||||||
import java.io.FileDescriptor;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dialog to show when a user switch it about to happen for the car. The intent is to snapshot the
|
* Dialog to show when a user switch it about to happen for the car. The intent is to snapshot the
|
||||||
* screen immediately after the dialog shows so that the user is informed that something is
|
* screen immediately after the dialog shows so that the user is informed that something is
|
||||||
* happening in the background rather than just freeze the screen and not know if the user-switch
|
* happening in the background rather than just freeze the screen and not know if the user-switch
|
||||||
* affordance was being handled.
|
* affordance was being handled.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
final class CarUserSwitchingDialog extends UserSwitchingDialog {
|
final class CarUserSwitchingDialog extends UserSwitchingDialog {
|
||||||
|
|
||||||
private static final String TAG = "ActivityManagerCarUserSwitchingDialog";
|
private static final String TAG = "ActivityManagerCarUserSwitchingDialog";
|
||||||
|
|
||||||
public CarUserSwitchingDialog(ActivityManagerService service, Context context, UserInfo oldUser,
|
public CarUserSwitchingDialog(ActivityManagerService service, Context context, UserInfo oldUser,
|
||||||
UserInfo newUser, boolean aboveSystem, String switchingFromSystemUserMessage,
|
UserInfo newUser, boolean aboveSystem, String switchingFromSystemUserMessage,
|
||||||
String switchingToSystemUserMessage) {
|
String switchingToSystemUserMessage) {
|
||||||
super(service, context, oldUser, newUser, aboveSystem, switchingFromSystemUserMessage,
|
super(service, context, oldUser, newUser, aboveSystem, switchingFromSystemUserMessage,
|
||||||
switchingToSystemUserMessage);
|
switchingToSystemUserMessage);
|
||||||
|
|
||||||
getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
|
getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
|
||||||
}
|
}
|
||||||
@@ -58,18 +66,104 @@ final class CarUserSwitchingDialog extends UserSwitchingDialog {
|
|||||||
Resources res = getContext().getResources();
|
Resources res = getContext().getResources();
|
||||||
// Custom view due to alignment and font size requirements
|
// Custom view due to alignment and font size requirements
|
||||||
View view = LayoutInflater.from(getContext()).inflate(R.layout.car_user_switching_dialog,
|
View view = LayoutInflater.from(getContext()).inflate(R.layout.car_user_switching_dialog,
|
||||||
null);
|
null);
|
||||||
|
|
||||||
UserManager userManager =
|
UserManager userManager =
|
||||||
(UserManager) getContext().getSystemService(Context.USER_SERVICE);
|
(UserManager) getContext().getSystemService(Context.USER_SERVICE);
|
||||||
Bitmap bitmap = userManager.getUserIcon(mNewUser.id);
|
Bitmap bitmap = userManager.getUserIcon(mNewUser.id);
|
||||||
if (bitmap != null) {
|
if (bitmap != null) {
|
||||||
|
CircleFramedDrawable drawable = CircleFramedDrawable.getInstance(bitmap,
|
||||||
|
res.getDimension(R.dimen.car_fullscreen_user_pod_image_avatar_height));
|
||||||
((ImageView) view.findViewById(R.id.user_loading_avatar))
|
((ImageView) view.findViewById(R.id.user_loading_avatar))
|
||||||
.setImageBitmap(bitmap);
|
.setImageDrawable(drawable);
|
||||||
}
|
}
|
||||||
|
|
||||||
((TextView) view.findViewById(R.id.user_loading))
|
((TextView) view.findViewById(R.id.user_loading))
|
||||||
.setText(res.getString(R.string.car_loading_profile));
|
.setText(res.getString(R.string.car_loading_profile));
|
||||||
setView(view);
|
setView(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the user icon to a circularly clipped one. This is used in the User Picker and
|
||||||
|
* Settings.
|
||||||
|
*/
|
||||||
|
static class CircleFramedDrawable extends Drawable {
|
||||||
|
|
||||||
|
private final Bitmap mBitmap;
|
||||||
|
private final int mSize;
|
||||||
|
private final Paint mPaint;
|
||||||
|
|
||||||
|
private float mScale;
|
||||||
|
private Rect mSrcRect;
|
||||||
|
private RectF mDstRect;
|
||||||
|
|
||||||
|
public static CircleFramedDrawable getInstance(Bitmap icon, float iconSize) {
|
||||||
|
CircleFramedDrawable instance = new CircleFramedDrawable(icon, (int) iconSize);
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CircleFramedDrawable(Bitmap icon, int size) {
|
||||||
|
super();
|
||||||
|
mSize = size;
|
||||||
|
|
||||||
|
mBitmap = Bitmap.createBitmap(mSize, mSize, Bitmap.Config.ARGB_8888);
|
||||||
|
final Canvas canvas = new Canvas(mBitmap);
|
||||||
|
|
||||||
|
final int width = icon.getWidth();
|
||||||
|
final int height = icon.getHeight();
|
||||||
|
final int square = Math.min(width, height);
|
||||||
|
|
||||||
|
final Rect cropRect = new Rect((width - square) / 2, (height - square) / 2,
|
||||||
|
square, square);
|
||||||
|
final RectF circleRect = new RectF(0f, 0f, mSize, mSize);
|
||||||
|
|
||||||
|
final Path fillPath = new Path();
|
||||||
|
fillPath.addArc(circleRect, 0f, 360f);
|
||||||
|
|
||||||
|
canvas.drawColor(0, PorterDuff.Mode.CLEAR);
|
||||||
|
|
||||||
|
// opaque circle
|
||||||
|
mPaint = new Paint();
|
||||||
|
mPaint.setAntiAlias(true);
|
||||||
|
mPaint.setColor(Color.BLACK);
|
||||||
|
mPaint.setStyle(Paint.Style.FILL);
|
||||||
|
canvas.drawPath(fillPath, mPaint);
|
||||||
|
|
||||||
|
// mask in the icon where the bitmap is opaque
|
||||||
|
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
|
||||||
|
canvas.drawBitmap(icon, cropRect, circleRect, mPaint);
|
||||||
|
|
||||||
|
// prepare paint for frame drawing
|
||||||
|
mPaint.setXfermode(null);
|
||||||
|
|
||||||
|
mScale = 1f;
|
||||||
|
|
||||||
|
mSrcRect = new Rect(0, 0, mSize, mSize);
|
||||||
|
mDstRect = new RectF(0, 0, mSize, mSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void draw(Canvas canvas) {
|
||||||
|
final float inside = mScale * mSize;
|
||||||
|
final float pad = (mSize - inside) / 2f;
|
||||||
|
|
||||||
|
mDstRect.set(pad, pad, mSize - pad, mSize - pad);
|
||||||
|
canvas.drawBitmap(mBitmap, mSrcRect, mDstRect, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getOpacity() {
|
||||||
|
return PixelFormat.TRANSLUCENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAlpha(int alpha) {
|
||||||
|
// Needed to implement abstract method. Do nothing.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setColorFilter(ColorFilter colorFilter) {
|
||||||
|
// Needed to implement abstract method. Do nothing.
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user