Merge "Enforce that the user switcher icons are circular" into pi-dev

This commit is contained in:
android-build-team Robot
2018-05-03 20:19:39 +00:00
committed by Android (Google) Code Review
2 changed files with 110 additions and 11 deletions

View File

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

View File

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