Merge "Centralized user icon drawing with badges" into nyc-dev
am: 289d8a0
* commit '289d8a08501125ef1bfb5cd49245df91519b0fe6':
Centralized user icon drawing with badges
Change-Id: I9547131f6dadb2ca384e42df52cd135f9038f1ab
This commit is contained in:
24
core/res/res/drawable/ic_corp_user_badge.xml
Normal file
24
core/res/res/drawable/ic_corp_user_badge.xml
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<!--
|
||||||
|
Copyright (C) 2016 The Android Open Source Project
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
-->
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="36dp"
|
||||||
|
android:height="36dp"
|
||||||
|
android:viewportWidth="36.0"
|
||||||
|
android:viewportHeight="36.0">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFFFF"
|
||||||
|
android:pathData="M18,0C8.06,-0 0,8.06 0,18C0,27.94 8.06,36 18,36C27.94,36 36,27.94 36,18C36,8.06 27.94,0 18,0zM15.5,10.5L20.5,10.5L21.75,11.75L21.75,13L24.66,13C25.57,13 26.34,13.74 26.34,14.66L26.34,18C26.34,18.92 25.57,19.66 24.66,19.66L19.66,19.66L19.66,18.41L16.34,18.41L16.34,19.66L11.34,19.66C10.43,19.66 9.66,18.92 9.66,18L9.66,14.66C9.66,13.74 10.43,13 11.34,13L14.25,13L14.25,11.78L15.5,10.5zM15.5,11.75L15.5,13L20.5,13L20.5,11.75L15.5,11.75zM10.5,20.5L16.34,20.5L16.34,21.75L19.66,21.75L19.66,20.5L25.5,20.5L25.5,23.84C25.5,24.76 24.76,25.5 23.84,25.5L12.16,25.5C11.24,25.5 10.5,24.76 10.5,23.84L10.5,20.5z"/>
|
||||||
|
</vector>
|
||||||
@@ -1265,6 +1265,7 @@
|
|||||||
<java-symbol type="drawable" name="ic_corp_badge" />
|
<java-symbol type="drawable" name="ic_corp_badge" />
|
||||||
<java-symbol type="drawable" name="ic_corp_badge_off" />
|
<java-symbol type="drawable" name="ic_corp_badge_off" />
|
||||||
<java-symbol type="drawable" name="ic_corp_icon_badge" />
|
<java-symbol type="drawable" name="ic_corp_icon_badge" />
|
||||||
|
<java-symbol type="drawable" name="ic_corp_user_badge" />
|
||||||
<java-symbol type="drawable" name="ic_corp_badge_no_background" />
|
<java-symbol type="drawable" name="ic_corp_badge_no_background" />
|
||||||
<java-symbol type="drawable" name="ic_corp_icon" />
|
<java-symbol type="drawable" name="ic_corp_icon" />
|
||||||
<java-symbol type="drawable" name="ic_corp_statusbar_icon" />
|
<java-symbol type="drawable" name="ic_corp_statusbar_icon" />
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import android.net.ConnectivityManager;
|
|||||||
import android.os.BatteryManager;
|
import android.os.BatteryManager;
|
||||||
import android.os.UserManager;
|
import android.os.UserManager;
|
||||||
import com.android.internal.util.UserIcons;
|
import com.android.internal.util.UserIcons;
|
||||||
import com.android.settingslib.drawable.CircleFramedDrawable;
|
import com.android.settingslib.drawable.UserIconDrawable;
|
||||||
|
|
||||||
import java.text.NumberFormat;
|
import java.text.NumberFormat;
|
||||||
|
|
||||||
@@ -73,21 +73,22 @@ public class Utils {
|
|||||||
/**
|
/**
|
||||||
* Returns a circular icon for a user.
|
* Returns a circular icon for a user.
|
||||||
*/
|
*/
|
||||||
public static Drawable getUserIcon(Context context, UserManager um, UserInfo user) {
|
public static UserIconDrawable getUserIcon(Context context, UserManager um, UserInfo user) {
|
||||||
|
final int iconSize = UserIconDrawable.getSizeForList(context);
|
||||||
if (user.isManagedProfile()) {
|
if (user.isManagedProfile()) {
|
||||||
// We use predefined values for managed profiles
|
// We use predefined values for managed profiles
|
||||||
Bitmap b = BitmapFactory.decodeResource(context.getResources(),
|
Bitmap b = BitmapFactory.decodeResource(context.getResources(),
|
||||||
com.android.internal.R.drawable.ic_corp_icon);
|
com.android.internal.R.drawable.ic_corp_icon);
|
||||||
return CircleFramedDrawable.getInstance(context, b);
|
return new UserIconDrawable(iconSize).setIcon(b).bake();
|
||||||
}
|
}
|
||||||
if (user.iconPath != null) {
|
if (user.iconPath != null) {
|
||||||
Bitmap icon = um.getUserIcon(user.id);
|
Bitmap icon = um.getUserIcon(user.id);
|
||||||
if (icon != null) {
|
if (icon != null) {
|
||||||
return CircleFramedDrawable.getInstance(context, icon);
|
return new UserIconDrawable(iconSize).setIcon(icon).bake();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return CircleFramedDrawable.getInstance(context, UserIcons.convertToBitmap(
|
return new UserIconDrawable(iconSize).setIconDrawable(
|
||||||
UserIcons.getDefaultUserIcon(user.id, /* light= */ false)));
|
UserIcons.getDefaultUserIcon(user.id, /* light= */ false)).bake();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Formats the ratio of amount/total as a percentage. */
|
/** Formats the ratio of amount/total as a percentage. */
|
||||||
|
|||||||
@@ -0,0 +1,428 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.settingslib.drawable;
|
||||||
|
|
||||||
|
import android.annotation.NonNull;
|
||||||
|
import android.app.admin.DevicePolicyManager;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.ColorStateList;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.BitmapShader;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.ColorFilter;
|
||||||
|
import android.graphics.Matrix;
|
||||||
|
import android.graphics.Paint;
|
||||||
|
import android.graphics.PixelFormat;
|
||||||
|
import android.graphics.PorterDuff;
|
||||||
|
import android.graphics.PorterDuffColorFilter;
|
||||||
|
import android.graphics.PorterDuffXfermode;
|
||||||
|
import android.graphics.Rect;
|
||||||
|
import android.graphics.RectF;
|
||||||
|
import android.graphics.Shader;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
|
||||||
|
import com.android.settingslib.R;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the user avatar icon to a circularly clipped one with an optional badge and frame
|
||||||
|
*/
|
||||||
|
public class UserIconDrawable extends Drawable implements Drawable.Callback {
|
||||||
|
|
||||||
|
private Drawable mUserDrawable;
|
||||||
|
private Bitmap mUserIcon;
|
||||||
|
private Bitmap mBitmap; // baked representation. Required for transparent border around badge
|
||||||
|
private final Paint mIconPaint = new Paint();
|
||||||
|
private final Paint mPaint = new Paint();
|
||||||
|
private final Matrix mIconMatrix = new Matrix();
|
||||||
|
private float mIntrinsicRadius;
|
||||||
|
private float mDisplayRadius;
|
||||||
|
private float mPadding = 0;
|
||||||
|
private int mSize = 0; // custom "intrinsic" size for this drawable if non-zero
|
||||||
|
private boolean mInvalidated = true;
|
||||||
|
private ColorStateList mTintColor = null;
|
||||||
|
private PorterDuff.Mode mTintMode = PorterDuff.Mode.SRC_ATOP;
|
||||||
|
|
||||||
|
private float mFrameWidth;
|
||||||
|
private float mFramePadding;
|
||||||
|
private ColorStateList mFrameColor = null;
|
||||||
|
private Paint mFramePaint;
|
||||||
|
|
||||||
|
private Drawable mBadge;
|
||||||
|
private Paint mClearPaint;
|
||||||
|
private float mBadgeRadius;
|
||||||
|
private float mBadgeMargin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the system default managed-user badge as a drawable
|
||||||
|
* @param context
|
||||||
|
* @return drawable containing just the badge
|
||||||
|
*/
|
||||||
|
public static Drawable getManagedUserBadgeDrawable(Context context) {
|
||||||
|
int displayDensity = context.getResources().getDisplayMetrics().densityDpi;
|
||||||
|
return context.getResources().getDrawableForDensity(
|
||||||
|
com.android.internal.R.drawable.ic_corp_user_badge,
|
||||||
|
displayDensity, context.getTheme());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the preferred list-item size of this drawable.
|
||||||
|
* @param context
|
||||||
|
* @return size in pixels
|
||||||
|
*/
|
||||||
|
public static int getSizeForList(Context context) {
|
||||||
|
return (int) context.getResources().getDimension(R.dimen.circle_avatar_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserIconDrawable() {
|
||||||
|
this(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use this constructor if the drawable is intended to be placed in listviews
|
||||||
|
* @param intrinsicSize if 0, the intrinsic size will come from the icon itself
|
||||||
|
*/
|
||||||
|
public UserIconDrawable(int intrinsicSize) {
|
||||||
|
super();
|
||||||
|
mIconPaint.setAntiAlias(true);
|
||||||
|
mIconPaint.setFilterBitmap(true);
|
||||||
|
mPaint.setFilterBitmap(true);
|
||||||
|
mPaint.setAntiAlias(true);
|
||||||
|
if (intrinsicSize > 0) {
|
||||||
|
setBounds(0, 0, intrinsicSize, intrinsicSize);
|
||||||
|
setIntrinsicSize(intrinsicSize);
|
||||||
|
}
|
||||||
|
setIcon(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserIconDrawable setIcon(Bitmap icon) {
|
||||||
|
if (mUserDrawable != null) {
|
||||||
|
mUserDrawable.setCallback(null);
|
||||||
|
mUserDrawable = null;
|
||||||
|
}
|
||||||
|
mUserIcon = icon;
|
||||||
|
if (mUserIcon == null) {
|
||||||
|
mIconPaint.setShader(null);
|
||||||
|
mBitmap = null;
|
||||||
|
} else {
|
||||||
|
mIconPaint.setShader(new BitmapShader(icon, Shader.TileMode.CLAMP,
|
||||||
|
Shader.TileMode.CLAMP));
|
||||||
|
}
|
||||||
|
onBoundsChange(getBounds());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserIconDrawable setIconDrawable(Drawable icon) {
|
||||||
|
if (mUserDrawable != null) {
|
||||||
|
mUserDrawable.setCallback(null);
|
||||||
|
}
|
||||||
|
mUserIcon = null;
|
||||||
|
mUserDrawable = icon;
|
||||||
|
if (mUserDrawable == null) {
|
||||||
|
mBitmap = null;
|
||||||
|
} else {
|
||||||
|
mUserDrawable.setCallback(this);
|
||||||
|
}
|
||||||
|
onBoundsChange(getBounds());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserIconDrawable setBadge(Drawable badge) {
|
||||||
|
mBadge = badge;
|
||||||
|
if (mBadge != null) {
|
||||||
|
if (mClearPaint == null) {
|
||||||
|
mClearPaint = new Paint();
|
||||||
|
mClearPaint.setAntiAlias(true);
|
||||||
|
mClearPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
|
||||||
|
mClearPaint.setStyle(Paint.Style.FILL);
|
||||||
|
}
|
||||||
|
// update metrics
|
||||||
|
onBoundsChange(getBounds());
|
||||||
|
} else {
|
||||||
|
invalidateSelf();
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserIconDrawable setBadgeIfManagedUser(Context context, int userId) {
|
||||||
|
Drawable badge = null;
|
||||||
|
boolean isManaged = context.getSystemService(DevicePolicyManager.class)
|
||||||
|
.getProfileOwnerAsUser(userId) != null;
|
||||||
|
if (isManaged) {
|
||||||
|
badge = getManagedUserBadgeDrawable(context);
|
||||||
|
}
|
||||||
|
return setBadge(badge);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBadgeRadius(float radius) {
|
||||||
|
mBadgeRadius = radius;
|
||||||
|
onBoundsChange(getBounds());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBadgeMargin(float margin) {
|
||||||
|
mBadgeMargin = margin;
|
||||||
|
onBoundsChange(getBounds());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets global padding of icon/frame. Doesn't effect the badge.
|
||||||
|
* @param padding
|
||||||
|
*/
|
||||||
|
public void setPadding(float padding) {
|
||||||
|
mPadding = padding;
|
||||||
|
onBoundsChange(getBounds());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initFramePaint() {
|
||||||
|
if (mFramePaint == null) {
|
||||||
|
mFramePaint = new Paint();
|
||||||
|
mFramePaint.setStyle(Paint.Style.STROKE);
|
||||||
|
mFramePaint.setAntiAlias(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFrameWidth(float width) {
|
||||||
|
initFramePaint();
|
||||||
|
mFrameWidth = width;
|
||||||
|
mFramePaint.setStrokeWidth(width);
|
||||||
|
onBoundsChange(getBounds());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFramePadding(float padding) {
|
||||||
|
initFramePaint();
|
||||||
|
mFramePadding = padding;
|
||||||
|
onBoundsChange(getBounds());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFrameColor(int color) {
|
||||||
|
initFramePaint();
|
||||||
|
mFramePaint.setColor(color);
|
||||||
|
invalidateSelf();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFrameColor(ColorStateList colorList) {
|
||||||
|
initFramePaint();
|
||||||
|
mFrameColor = colorList;
|
||||||
|
invalidateSelf();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This sets the "intrinsic" size of this drawable. Useful for views which use the drawable's
|
||||||
|
* intrinsic size for layout. It is independent of the bounds.
|
||||||
|
* @param size if 0, the intrinsic size will be set to the displayed icon's size
|
||||||
|
*/
|
||||||
|
public void setIntrinsicSize(int size) {
|
||||||
|
mSize = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void draw(Canvas canvas) {
|
||||||
|
if (mInvalidated) {
|
||||||
|
rebake();
|
||||||
|
}
|
||||||
|
if (mBitmap != null) {
|
||||||
|
if (mTintColor == null) {
|
||||||
|
mPaint.setColorFilter(null);
|
||||||
|
} else {
|
||||||
|
int color = mTintColor.getColorForState(getState(), mTintColor.getDefaultColor());
|
||||||
|
if (mPaint.getColorFilter() == null) {
|
||||||
|
mPaint.setColorFilter(new PorterDuffColorFilter(color, mTintMode));
|
||||||
|
} else {
|
||||||
|
((PorterDuffColorFilter) mPaint.getColorFilter()).setMode(mTintMode);
|
||||||
|
((PorterDuffColorFilter) mPaint.getColorFilter()).setColor(color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas.drawBitmap(mBitmap, 0, 0, mPaint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAlpha(int alpha) {
|
||||||
|
mPaint.setAlpha(alpha);
|
||||||
|
super.invalidateSelf();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setColorFilter(ColorFilter colorFilter) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setTintList(ColorStateList tintList) {
|
||||||
|
mTintColor = tintList;
|
||||||
|
super.invalidateSelf();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setTintMode(@NonNull PorterDuff.Mode mode) {
|
||||||
|
mTintMode = mode;
|
||||||
|
super.invalidateSelf();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This 'bakes' the current state of this icon into a bitmap and removes/recycles the source
|
||||||
|
* bitmap/drawable. Use this when no more changes will be made and an intrinsic size is set.
|
||||||
|
* This effectively turns this into a static drawable.
|
||||||
|
*/
|
||||||
|
public UserIconDrawable bake() {
|
||||||
|
if (mSize <= 0) {
|
||||||
|
throw new IllegalStateException("Baking requires an explicit intrinsic size");
|
||||||
|
}
|
||||||
|
onBoundsChange(new Rect(0, 0, mSize, mSize));
|
||||||
|
rebake();
|
||||||
|
mFrameColor = null;
|
||||||
|
mFramePaint = null;
|
||||||
|
mClearPaint = null;
|
||||||
|
if (mUserDrawable != null) {
|
||||||
|
mUserDrawable.setCallback(null);
|
||||||
|
mUserDrawable = null;
|
||||||
|
} else if (mUserIcon != null) {
|
||||||
|
mUserIcon.recycle();
|
||||||
|
mUserIcon = null;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void rebake() {
|
||||||
|
mInvalidated = false;
|
||||||
|
|
||||||
|
if (mBitmap == null || (mUserDrawable == null && mUserIcon == null)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Canvas canvas = new Canvas(mBitmap);
|
||||||
|
canvas.drawColor(0, PorterDuff.Mode.CLEAR);
|
||||||
|
|
||||||
|
if(mUserDrawable != null) {
|
||||||
|
mUserDrawable.draw(canvas);
|
||||||
|
} else if (mUserIcon != null) {
|
||||||
|
int saveId = canvas.save();
|
||||||
|
canvas.concat(mIconMatrix);
|
||||||
|
canvas.drawCircle(mUserIcon.getWidth() * 0.5f, mUserIcon.getHeight() * 0.5f,
|
||||||
|
mIntrinsicRadius, mIconPaint);
|
||||||
|
canvas.restoreToCount(saveId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mFrameColor != null) {
|
||||||
|
mFramePaint.setColor(mFrameColor.getColorForState(getState(), Color.TRANSPARENT));
|
||||||
|
}
|
||||||
|
if ((mFrameWidth + mFramePadding) > 0.001f) {
|
||||||
|
float radius = mDisplayRadius - mPadding - mFrameWidth * 0.5f;
|
||||||
|
canvas.drawCircle(getBounds().exactCenterX(), getBounds().exactCenterY(),
|
||||||
|
radius, mFramePaint);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((mBadge != null) && (mBadgeRadius > 0.001f)) {
|
||||||
|
final float badgeDiameter = mBadgeRadius * 2f;
|
||||||
|
final float badgeTop = mBitmap.getHeight() - badgeDiameter;
|
||||||
|
float badgeLeft = mBitmap.getWidth() - badgeDiameter;
|
||||||
|
|
||||||
|
mBadge.setBounds((int) badgeLeft, (int) badgeTop,
|
||||||
|
(int) (badgeLeft + badgeDiameter), (int) (badgeTop + badgeDiameter));
|
||||||
|
|
||||||
|
final float borderRadius = mBadge.getBounds().width() * 0.5f + mBadgeMargin;
|
||||||
|
canvas.drawCircle(badgeLeft + mBadgeRadius, badgeTop + mBadgeRadius,
|
||||||
|
borderRadius, mClearPaint);
|
||||||
|
|
||||||
|
mBadge.draw(canvas);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onBoundsChange(Rect bounds) {
|
||||||
|
if (bounds.isEmpty() || (mUserIcon == null && mUserDrawable == null)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// re-create bitmap if applicable
|
||||||
|
float newDisplayRadius = Math.min(bounds.width(), bounds.height()) * 0.5f;
|
||||||
|
int size = (int) (newDisplayRadius * 2);
|
||||||
|
if (mBitmap == null || size != ((int) (mDisplayRadius * 2))) {
|
||||||
|
mDisplayRadius = newDisplayRadius;
|
||||||
|
if (mBitmap != null) {
|
||||||
|
mBitmap.recycle();
|
||||||
|
}
|
||||||
|
mBitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
|
||||||
|
}
|
||||||
|
|
||||||
|
// update metrics
|
||||||
|
mDisplayRadius = Math.min(bounds.width(), bounds.height()) * 0.5f;
|
||||||
|
final float iconRadius = mDisplayRadius - mFrameWidth - mFramePadding - mPadding;
|
||||||
|
RectF dstRect = new RectF(bounds.exactCenterX() - iconRadius,
|
||||||
|
bounds.exactCenterY() - iconRadius,
|
||||||
|
bounds.exactCenterX() + iconRadius,
|
||||||
|
bounds.exactCenterY() + iconRadius);
|
||||||
|
if (mUserDrawable != null) {
|
||||||
|
Rect rounded = new Rect();
|
||||||
|
dstRect.round(rounded);
|
||||||
|
mIntrinsicRadius = Math.min(mUserDrawable.getIntrinsicWidth(),
|
||||||
|
mUserDrawable.getIntrinsicHeight()) * 0.5f;
|
||||||
|
mUserDrawable.setBounds(rounded);
|
||||||
|
} else if (mUserIcon != null) {
|
||||||
|
// Build square-to-square transformation matrix
|
||||||
|
final float iconCX = mUserIcon.getWidth() * 0.5f;
|
||||||
|
final float iconCY = mUserIcon.getHeight() * 0.5f;
|
||||||
|
mIntrinsicRadius = Math.min(iconCX, iconCY);
|
||||||
|
RectF srcRect = new RectF(iconCX - mIntrinsicRadius, iconCY - mIntrinsicRadius,
|
||||||
|
iconCX + mIntrinsicRadius, iconCY + mIntrinsicRadius);
|
||||||
|
mIconMatrix.setRectToRect(srcRect, dstRect, Matrix.ScaleToFit.FILL);
|
||||||
|
}
|
||||||
|
|
||||||
|
invalidateSelf();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void invalidateSelf() {
|
||||||
|
super.invalidateSelf();
|
||||||
|
mInvalidated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isStateful() {
|
||||||
|
return mFrameColor != null && mFrameColor.isStateful();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getOpacity() {
|
||||||
|
return PixelFormat.TRANSLUCENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getIntrinsicWidth() {
|
||||||
|
return (mSize <= 0 ? (int) mIntrinsicRadius * 2 : mSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getIntrinsicHeight() {
|
||||||
|
return getIntrinsicWidth();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void invalidateDrawable(@NonNull Drawable who) {
|
||||||
|
invalidateSelf();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
|
||||||
|
scheduleSelf(what, when);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
|
||||||
|
unscheduleSelf(what);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -33,7 +33,7 @@ import android.widget.ListAdapter;
|
|||||||
import android.widget.SpinnerAdapter;
|
import android.widget.SpinnerAdapter;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import com.android.internal.util.UserIcons;
|
import com.android.internal.util.UserIcons;
|
||||||
import com.android.settingslib.drawable.CircleFramedDrawable;
|
import com.android.settingslib.drawable.UserIconDrawable;
|
||||||
|
|
||||||
import com.android.settingslib.R;
|
import com.android.settingslib.R;
|
||||||
|
|
||||||
@@ -71,7 +71,8 @@ public class UserAdapter implements SpinnerAdapter, ListAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static Drawable encircle(Context context, Drawable icon) {
|
private static Drawable encircle(Context context, Drawable icon) {
|
||||||
return CircleFramedDrawable.getInstance(context, UserIcons.convertToBitmap(icon));
|
return new UserIconDrawable(UserIconDrawable.getSizeForList(context))
|
||||||
|
.setIconDrawable(icon).bake();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private ArrayList<UserDetails> data;
|
private ArrayList<UserDetails> data;
|
||||||
|
|||||||
22
packages/SystemUI/res/color/qs_user_detail_avatar_frame.xml
Normal file
22
packages/SystemUI/res/color/qs_user_detail_avatar_frame.xml
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
~ Copyright (C) 2016 The Android Open Source Project
|
||||||
|
~
|
||||||
|
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
~ you may not use this file except in compliance with the License.
|
||||||
|
~ You may obtain a copy of the License at
|
||||||
|
~
|
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
~
|
||||||
|
~ Unless required by applicable law or agreed to in writing, software
|
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
~ See the License for the specific language governing permissions and
|
||||||
|
~ limitations under the License
|
||||||
|
-->
|
||||||
|
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:state_activated="true" android:color="@color/current_user_border_color" />
|
||||||
|
<item android:color="@android:color/transparent" />
|
||||||
|
</selector>
|
||||||
22
packages/SystemUI/res/color/qs_user_detail_avatar_tint.xml
Normal file
22
packages/SystemUI/res/color/qs_user_detail_avatar_tint.xml
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
~ Copyright (C) 2016 The Android Open Source Project
|
||||||
|
~
|
||||||
|
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
~ you may not use this file except in compliance with the License.
|
||||||
|
~ You may obtain a copy of the License at
|
||||||
|
~
|
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
~
|
||||||
|
~ Unless required by applicable law or agreed to in writing, software
|
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
~ See the License for the specific language governing permissions and
|
||||||
|
~ limitations under the License
|
||||||
|
-->
|
||||||
|
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:state_enabled="false" android:color="@color/qs_tile_disabled_color" />
|
||||||
|
<item android:color="@android:color/transparent" />
|
||||||
|
</selector>
|
||||||
@@ -33,14 +33,18 @@
|
|||||||
<TextView android:id="@+id/user_name"
|
<TextView android:id="@+id/user_name"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginEnd="16dp"
|
android:layout_marginEnd="13dp"
|
||||||
android:textAppearance="@style/TextAppearance.StatusBar.Expanded.UserSwitcher.UserName"
|
android:textAppearance="@style/TextAppearance.StatusBar.Expanded.UserSwitcher.UserName"
|
||||||
/>
|
/>
|
||||||
<com.android.systemui.statusbar.phone.UserAvatarView android:id="@+id/user_picture"
|
<com.android.systemui.statusbar.phone.UserAvatarView android:id="@+id/user_picture"
|
||||||
android:layout_width="@dimen/max_avatar_size"
|
android:layout_width="@dimen/framed_avatar_size"
|
||||||
android:layout_height="@dimen/max_avatar_size"
|
android:layout_height="@dimen/framed_avatar_size"
|
||||||
android:contentDescription="@null"
|
android:contentDescription="@null"
|
||||||
|
android:backgroundTint="@color/qs_user_detail_avatar_tint"
|
||||||
|
android:backgroundTintMode="src_atop"
|
||||||
sysui:frameWidth="@dimen/keyguard_user_switcher_border_thickness"
|
sysui:frameWidth="@dimen/keyguard_user_switcher_border_thickness"
|
||||||
sysui:framePadding="6dp"
|
sysui:framePadding="2.5dp"
|
||||||
sysui:activeFrameColor="@color/current_user_border_color" />
|
sysui:badgeDiameter="18dp"
|
||||||
|
sysui:badgeMargin="1dp"
|
||||||
|
sysui:frameColor="@color/qs_user_detail_avatar_frame" />
|
||||||
</com.android.systemui.qs.tiles.UserDetailItemView>
|
</com.android.systemui.qs.tiles.UserDetailItemView>
|
||||||
|
|||||||
@@ -33,12 +33,16 @@
|
|||||||
|
|
||||||
<com.android.systemui.statusbar.phone.UserAvatarView
|
<com.android.systemui.statusbar.phone.UserAvatarView
|
||||||
android:id="@+id/user_picture"
|
android:id="@+id/user_picture"
|
||||||
android:layout_width="@dimen/max_avatar_size"
|
android:layout_width="@dimen/framed_avatar_size"
|
||||||
android:layout_height="@dimen/max_avatar_size"
|
android:layout_height="@dimen/framed_avatar_size"
|
||||||
android:layout_marginBottom="10dp"
|
android:layout_marginBottom="7dp"
|
||||||
|
android:backgroundTint="@color/qs_user_detail_avatar_tint"
|
||||||
|
android:backgroundTintMode="src_atop"
|
||||||
systemui:frameWidth="2dp"
|
systemui:frameWidth="2dp"
|
||||||
systemui:framePadding="6dp"
|
systemui:framePadding="2.5dp"
|
||||||
systemui:activeFrameColor="@color/current_user_border_color"/>
|
systemui:badgeDiameter="18dp"
|
||||||
|
systemui:badgeMargin="1dp"
|
||||||
|
systemui:frameColor="@color/qs_user_detail_avatar_frame"/>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|||||||
@@ -53,10 +53,14 @@
|
|||||||
<enum name="vertical" value="1" />
|
<enum name="vertical" value="1" />
|
||||||
</attr>
|
</attr>
|
||||||
<declare-styleable name="UserAvatarView">
|
<declare-styleable name="UserAvatarView">
|
||||||
|
<attr name="avatarPadding" format="dimension" />
|
||||||
<attr name="frameWidth" format="dimension" />
|
<attr name="frameWidth" format="dimension" />
|
||||||
<attr name="framePadding" format="dimension" />
|
<attr name="framePadding" format="dimension" />
|
||||||
|
<!-- {@deprecated Use a statelist in frameColor instead.} -->
|
||||||
<attr name="activeFrameColor" format="color" />
|
<attr name="activeFrameColor" format="color" />
|
||||||
<attr name="frameColor" />
|
<attr name="frameColor" format="color" />
|
||||||
|
<attr name="badgeDiameter" format="dimension" />
|
||||||
|
<attr name="badgeMargin" format="dimension" />
|
||||||
</declare-styleable>
|
</declare-styleable>
|
||||||
<declare-styleable name="UserDetailItemView">
|
<declare-styleable name="UserDetailItemView">
|
||||||
<attr name="regularFontFamily" format="string" />
|
<attr name="regularFontFamily" format="string" />
|
||||||
|
|||||||
@@ -388,6 +388,9 @@
|
|||||||
quick settings header -->
|
quick settings header -->
|
||||||
<dimen name="max_avatar_size">48dp</dimen>
|
<dimen name="max_avatar_size">48dp</dimen>
|
||||||
|
|
||||||
|
<!-- Size of user icon + frame in the qs/keyguard user picker (incl. frame) -->
|
||||||
|
<dimen name="framed_avatar_size">54dp</dimen>
|
||||||
|
|
||||||
<!-- Margin on the left side of the carrier text on Keyguard -->
|
<!-- Margin on the left side of the carrier text on Keyguard -->
|
||||||
<dimen name="keyguard_carrier_text_margin">16dp</dimen>
|
<dimen name="keyguard_carrier_text_margin">16dp</dimen>
|
||||||
|
|
||||||
|
|||||||
@@ -1,54 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2014 The Android Open Source Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.android.systemui;
|
|
||||||
|
|
||||||
import android.graphics.Bitmap;
|
|
||||||
import android.graphics.BitmapShader;
|
|
||||||
import android.graphics.Canvas;
|
|
||||||
import android.graphics.Matrix;
|
|
||||||
import android.graphics.Paint;
|
|
||||||
import android.graphics.RectF;
|
|
||||||
import android.graphics.Shader;
|
|
||||||
|
|
||||||
public class BitmapHelper {
|
|
||||||
/**
|
|
||||||
* Generate a new bitmap (width x height pixels, ARGB_8888) with the input bitmap scaled
|
|
||||||
* to fit and clipped to an inscribed circle.
|
|
||||||
* @param input Bitmap to resize and clip
|
|
||||||
* @param width Width of output bitmap (and diameter of circle)
|
|
||||||
* @param height Height of output bitmap
|
|
||||||
* @return A shiny new bitmap for you to use
|
|
||||||
*/
|
|
||||||
public static Bitmap createCircularClip(Bitmap input, int width, int height) {
|
|
||||||
if (input == null) return null;
|
|
||||||
|
|
||||||
final int inWidth = input.getWidth();
|
|
||||||
final int inHeight = input.getHeight();
|
|
||||||
final Bitmap output = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
|
|
||||||
final Canvas canvas = new Canvas(output);
|
|
||||||
final Paint paint = new Paint();
|
|
||||||
paint.setShader(new BitmapShader(input, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
|
|
||||||
paint.setAntiAlias(true);
|
|
||||||
final RectF srcRect = new RectF(0, 0, inWidth, inHeight);
|
|
||||||
final RectF dstRect = new RectF(0, 0, width, height);
|
|
||||||
final Matrix m = new Matrix();
|
|
||||||
m.setRectToRect(srcRect, dstRect, Matrix.ScaleToFit.CENTER);
|
|
||||||
canvas.setMatrix(m);
|
|
||||||
canvas.drawCircle(inWidth / 2, inHeight / 2, inWidth / 2, paint);
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -30,6 +30,7 @@ import android.widget.LinearLayout;
|
|||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.android.internal.util.ArrayUtils;
|
import com.android.internal.util.ArrayUtils;
|
||||||
|
import com.android.settingslib.drawable.UserIconDrawable;
|
||||||
import com.android.systemui.FontSizeUtils;
|
import com.android.systemui.FontSizeUtils;
|
||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
import com.android.systemui.statusbar.phone.UserAvatarView;
|
import com.android.systemui.statusbar.phone.UserAvatarView;
|
||||||
@@ -87,25 +88,29 @@ public class UserDetailItemView extends LinearLayout {
|
|||||||
return (UserDetailItemView) convertView;
|
return (UserDetailItemView) convertView;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void bind(String name, Bitmap picture) {
|
public void bind(String name, Bitmap picture, int userId) {
|
||||||
mName.setText(name);
|
mName.setText(name);
|
||||||
mAvatar.setBitmap(picture);
|
mAvatar.setAvatarWithBadge(picture, userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void bind(String name, Drawable picture) {
|
public void bind(String name, Drawable picture, int userId) {
|
||||||
mName.setText(name);
|
mName.setText(name);
|
||||||
mAvatar.setDrawable(picture);
|
mAvatar.setDrawableWithBadge(picture, userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAvatarEnabled(boolean enabled) {
|
||||||
|
mAvatar.setEnabled(enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDisabledByAdmin(boolean disabled) {
|
public void setDisabledByAdmin(boolean disabled) {
|
||||||
mRestrictedPadlock.setVisibility(disabled ? View.VISIBLE : View.GONE);
|
mRestrictedPadlock.setVisibility(disabled ? View.VISIBLE : View.GONE);
|
||||||
mName.setEnabled(!disabled);
|
mName.setEnabled(!disabled);
|
||||||
mAvatar.setDisabled(disabled);
|
mAvatar.setEnabled(!disabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setEnabled(boolean enabled) {
|
public void setEnabled(boolean enabled) {
|
||||||
mName.setEnabled(enabled);
|
mName.setEnabled(enabled);
|
||||||
mAvatar.setDisabled(!enabled);
|
mAvatar.setEnabled(enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -76,9 +76,9 @@ public class UserDetailView extends PseudoGridView {
|
|||||||
}
|
}
|
||||||
String name = getName(mContext, item);
|
String name = getName(mContext, item);
|
||||||
if (item.picture == null) {
|
if (item.picture == null) {
|
||||||
v.bind(name, getDrawable(mContext, item));
|
v.bind(name, getDrawable(mContext, item), item.resolveId());
|
||||||
} else {
|
} else {
|
||||||
v.bind(name, item.picture);
|
v.bind(name, item.picture, item.info.id);
|
||||||
}
|
}
|
||||||
v.setActivated(item.isCurrent);
|
v.setActivated(item.isCurrent);
|
||||||
v.setDisabledByAdmin(item.isDisabledByAdmin);
|
v.setDisabledByAdmin(item.isDisabledByAdmin);
|
||||||
|
|||||||
@@ -17,69 +17,57 @@
|
|||||||
package com.android.systemui.statusbar.phone;
|
package com.android.systemui.statusbar.phone;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.res.ColorStateList;
|
||||||
import android.content.res.TypedArray;
|
import android.content.res.TypedArray;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.BitmapShader;
|
|
||||||
import android.graphics.Canvas;
|
|
||||||
import android.graphics.Matrix;
|
|
||||||
import android.graphics.Paint;
|
|
||||||
import android.graphics.PorterDuff;
|
import android.graphics.PorterDuff;
|
||||||
import android.graphics.PorterDuffColorFilter;
|
|
||||||
import android.graphics.Shader;
|
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
|
import com.android.settingslib.drawable.UserIconDrawable;
|
||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A view that displays a user image cropped to a circle with a frame.
|
* A view that displays a user image cropped to a circle with an optional frame.
|
||||||
*/
|
*/
|
||||||
public class UserAvatarView extends View {
|
public class UserAvatarView extends View {
|
||||||
|
|
||||||
private int mActiveFrameColor;
|
private final UserIconDrawable mDrawable = new UserIconDrawable();
|
||||||
private int mFrameColor;
|
|
||||||
private float mFrameWidth;
|
|
||||||
private float mFramePadding;
|
|
||||||
private Bitmap mBitmap;
|
|
||||||
private Drawable mDrawable;
|
|
||||||
private boolean mIsDisabled;
|
|
||||||
|
|
||||||
private final Paint mFramePaint = new Paint();
|
|
||||||
private final Paint mBitmapPaint = new Paint();
|
|
||||||
private final Matrix mDrawMatrix = new Matrix();
|
|
||||||
|
|
||||||
private float mScale = 1;
|
|
||||||
|
|
||||||
public UserAvatarView(Context context, AttributeSet attrs,
|
public UserAvatarView(Context context, AttributeSet attrs,
|
||||||
int defStyleAttr,
|
int defStyleAttr,
|
||||||
int defStyleRes) {
|
int defStyleRes) {
|
||||||
super(context, attrs, defStyleAttr, defStyleRes);
|
super(context, attrs, defStyleAttr, defStyleRes);
|
||||||
|
|
||||||
final TypedArray a = context.obtainStyledAttributes(
|
final TypedArray a = context.obtainStyledAttributes(
|
||||||
attrs, R.styleable.UserAvatarView, defStyleAttr, defStyleRes);
|
attrs, R.styleable.UserAvatarView, defStyleAttr, defStyleRes);
|
||||||
final int N = a.getIndexCount();
|
final int N = a.getIndexCount();
|
||||||
for (int i = 0; i < N; i++) {
|
for (int i = 0; i < N; i++) {
|
||||||
int attr = a.getIndex(i);
|
int attr = a.getIndex(i);
|
||||||
switch (attr) {
|
switch (attr) {
|
||||||
|
case R.styleable.UserAvatarView_avatarPadding:
|
||||||
|
setAvatarPadding(a.getDimension(attr, 0));
|
||||||
|
break;
|
||||||
case R.styleable.UserAvatarView_frameWidth:
|
case R.styleable.UserAvatarView_frameWidth:
|
||||||
setFrameWidth(a.getDimension(attr, 0));
|
setFrameWidth(a.getDimension(attr, 0));
|
||||||
break;
|
break;
|
||||||
case R.styleable.UserAvatarView_framePadding:
|
case R.styleable.UserAvatarView_framePadding:
|
||||||
setFramePadding(a.getDimension(attr, 0));
|
setFramePadding(a.getDimension(attr, 0));
|
||||||
break;
|
break;
|
||||||
case R.styleable.UserAvatarView_activeFrameColor:
|
|
||||||
setActiveFrameColor(a.getColor(attr, 0));
|
|
||||||
break;
|
|
||||||
case R.styleable.UserAvatarView_frameColor:
|
case R.styleable.UserAvatarView_frameColor:
|
||||||
setFrameColor(a.getColor(attr, 0));
|
setFrameColor(a.getColorStateList(attr));
|
||||||
|
break;
|
||||||
|
case R.styleable.UserAvatarView_badgeDiameter:
|
||||||
|
setBadgeDiameter(a.getDimension(attr, 0));
|
||||||
|
break;
|
||||||
|
case R.styleable.UserAvatarView_badgeMargin:
|
||||||
|
setBadgeMargin(a.getDimension(attr, 0));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
a.recycle();
|
a.recycle();
|
||||||
|
setBackground(mDrawable);
|
||||||
mFramePaint.setAntiAlias(true);
|
|
||||||
mFramePaint.setStyle(Paint.Style.STROKE);
|
|
||||||
mBitmapPaint.setAntiAlias(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public UserAvatarView(Context context, AttributeSet attrs, int defStyleAttr) {
|
public UserAvatarView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||||
@@ -94,180 +82,61 @@ public class UserAvatarView extends View {
|
|||||||
this(context, null);
|
this(context, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated use {@link #setAvatar(Bitmap)} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
public void setBitmap(Bitmap bitmap) {
|
public void setBitmap(Bitmap bitmap) {
|
||||||
setDrawable(null);
|
setAvatar(bitmap);
|
||||||
mBitmap = bitmap;
|
|
||||||
if (mBitmap != null) {
|
|
||||||
mBitmapPaint.setShader(new BitmapShader(
|
|
||||||
bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
|
|
||||||
} else {
|
|
||||||
mBitmapPaint.setShader(null);
|
|
||||||
}
|
|
||||||
configureBounds();
|
|
||||||
invalidate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFrameColor(int frameColor) {
|
public void setFrameColor(ColorStateList color) {
|
||||||
mFrameColor = frameColor;
|
mDrawable.setFrameColor(color);
|
||||||
invalidate();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setActiveFrameColor(int activeFrameColor) {
|
|
||||||
mActiveFrameColor = activeFrameColor;
|
|
||||||
invalidate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFrameWidth(float frameWidth) {
|
public void setFrameWidth(float frameWidth) {
|
||||||
mFrameWidth = frameWidth;
|
mDrawable.setFrameWidth(frameWidth);
|
||||||
invalidate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFramePadding(float framePadding) {
|
public void setFramePadding(float framePadding) {
|
||||||
mFramePadding = framePadding;
|
mDrawable.setFramePadding(framePadding);
|
||||||
invalidate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void setAvatarPadding(float avatarPadding) {
|
||||||
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
mDrawable.setPadding(avatarPadding);
|
||||||
super.onLayout(changed, left, top, right, bottom);
|
|
||||||
configureBounds();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void configureBounds() {
|
public void setBadgeDiameter(float diameter) {
|
||||||
int vwidth = getWidth() - mPaddingLeft - mPaddingRight;
|
mDrawable.setBadgeRadius(diameter * 0.5f);
|
||||||
int vheight = getHeight() - mPaddingTop - mPaddingBottom;
|
|
||||||
|
|
||||||
int dwidth;
|
|
||||||
int dheight;
|
|
||||||
if (mBitmap != null) {
|
|
||||||
dwidth = mBitmap.getWidth();
|
|
||||||
dheight = mBitmap.getHeight();
|
|
||||||
} else if (mDrawable != null) {
|
|
||||||
vwidth -= 2 * (mFrameWidth - 1);
|
|
||||||
vheight -= 2 * (mFrameWidth - 1);
|
|
||||||
dwidth = vwidth;
|
|
||||||
dheight = vheight;
|
|
||||||
mDrawable.setBounds(0, 0, dwidth, dheight);
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
float scale;
|
|
||||||
float dx;
|
|
||||||
float dy;
|
|
||||||
|
|
||||||
scale = Math.min((float) vwidth / (float) dwidth,
|
|
||||||
(float) vheight / (float) dheight);
|
|
||||||
|
|
||||||
dx = (int) ((vwidth - dwidth * scale) * 0.5f + 0.5f);
|
|
||||||
dy = (int) ((vheight - dheight * scale) * 0.5f + 0.5f);
|
|
||||||
|
|
||||||
mDrawMatrix.setScale(scale, scale);
|
|
||||||
mDrawMatrix.postTranslate(dx, dy);
|
|
||||||
mScale = scale;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void setBadgeMargin(float margin) {
|
||||||
protected void onDraw(Canvas canvas) {
|
mDrawable.setBadgeMargin(margin);
|
||||||
int frameColor = isActivated() ? mActiveFrameColor : mFrameColor;
|
}
|
||||||
float halfW = getWidth() / 2f;
|
|
||||||
float halfH = getHeight() / 2f;
|
public void setAvatar(Bitmap avatar) {
|
||||||
float halfSW = Math.min(halfH, halfW);
|
mDrawable.setIcon(avatar);
|
||||||
updateDrawableIfDisabled();
|
mDrawable.setBadge(null);
|
||||||
if (mBitmap != null && mScale > 0) {
|
}
|
||||||
int saveCount = canvas.getSaveCount();
|
|
||||||
canvas.save();
|
public void setAvatarWithBadge(Bitmap avatar, int userId) {
|
||||||
canvas.translate(mPaddingLeft, mPaddingTop);
|
mDrawable.setIcon(avatar);
|
||||||
canvas.concat(mDrawMatrix);
|
mDrawable.setBadgeIfManagedUser(getContext(), userId);
|
||||||
float halfBW = mBitmap.getWidth() / 2f;
|
|
||||||
float halfBH = mBitmap.getHeight() / 2f;
|
|
||||||
float halfBSW = Math.min(halfBH, halfBW);
|
|
||||||
canvas.drawCircle(halfBW, halfBH, halfBSW - mFrameWidth / mScale + 1, mBitmapPaint);
|
|
||||||
canvas.restoreToCount(saveCount);
|
|
||||||
} else if (mDrawable != null && mScale > 0) {
|
|
||||||
int saveCount = canvas.getSaveCount();
|
|
||||||
canvas.save();
|
|
||||||
canvas.translate(mPaddingLeft, mPaddingTop);
|
|
||||||
canvas.translate(mFrameWidth - 1, mFrameWidth - 1);
|
|
||||||
canvas.concat(mDrawMatrix);
|
|
||||||
mDrawable.draw(canvas);
|
|
||||||
canvas.restoreToCount(saveCount);
|
|
||||||
}
|
|
||||||
if (frameColor != 0) {
|
|
||||||
mFramePaint.setColor(frameColor);
|
|
||||||
mFramePaint.setStrokeWidth(mFrameWidth);
|
|
||||||
canvas.drawCircle(halfW, halfH, halfSW + (mFramePadding - mFrameWidth) / 2f,
|
|
||||||
mFramePaint);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDrawable(Drawable d) {
|
public void setDrawable(Drawable d) {
|
||||||
if (mDrawable != null) {
|
if (d instanceof UserIconDrawable) {
|
||||||
mDrawable.setCallback(null);
|
throw new RuntimeException("Recursively adding UserIconDrawable");
|
||||||
unscheduleDrawable(mDrawable);
|
|
||||||
}
|
}
|
||||||
mDrawable = d;
|
mDrawable.setIconDrawable(d);
|
||||||
if (d != null) {
|
mDrawable.setBadge(null);
|
||||||
d.setCallback(this);
|
|
||||||
if (d.isStateful()) {
|
|
||||||
d.setState(getDrawableState());
|
|
||||||
}
|
|
||||||
d.setLayoutDirection(getLayoutDirection());
|
|
||||||
configureBounds();
|
|
||||||
}
|
|
||||||
if (d != null) {
|
|
||||||
mBitmap = null;
|
|
||||||
}
|
|
||||||
configureBounds();
|
|
||||||
invalidate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void setDrawableWithBadge(Drawable d, int userId) {
|
||||||
public void invalidateDrawable(Drawable dr) {
|
if (d instanceof UserIconDrawable) {
|
||||||
if (dr == mDrawable) {
|
throw new RuntimeException("Recursively adding UserIconDrawable");
|
||||||
invalidate();
|
|
||||||
} else {
|
|
||||||
super.invalidateDrawable(dr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean verifyDrawable(Drawable who) {
|
|
||||||
return who == mDrawable || super.verifyDrawable(who);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void drawableStateChanged() {
|
|
||||||
super.drawableStateChanged();
|
|
||||||
if (mDrawable != null && mDrawable.isStateful()) {
|
|
||||||
mDrawable.setState(getDrawableState());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDisabled(boolean disabled) {
|
|
||||||
if (mIsDisabled == disabled) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mIsDisabled = disabled;
|
|
||||||
invalidate();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateDrawableIfDisabled() {
|
|
||||||
int disabledColor = getContext().getColor(R.color.qs_tile_disabled_color);
|
|
||||||
PorterDuffColorFilter filter = new PorterDuffColorFilter(disabledColor,
|
|
||||||
PorterDuff.Mode.SRC_ATOP);
|
|
||||||
if (mBitmap != null) {
|
|
||||||
if (mIsDisabled) {
|
|
||||||
mBitmapPaint.setColorFilter(filter);
|
|
||||||
} else {
|
|
||||||
mBitmapPaint.setColorFilter(null);
|
|
||||||
}
|
|
||||||
} else if (mDrawable != null) {
|
|
||||||
if (mIsDisabled) {
|
|
||||||
mDrawable.setColorFilter(filter);
|
|
||||||
} else {
|
|
||||||
mDrawable.setColorFilter(null);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
mDrawable.setIconDrawable(d);
|
||||||
|
mDrawable.setBadgeIfManagedUser(getContext(), userId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -253,17 +253,13 @@ public class KeyguardUserSwitcher {
|
|||||||
UserDetailItemView v = (UserDetailItemView) convertView;
|
UserDetailItemView v = (UserDetailItemView) convertView;
|
||||||
|
|
||||||
String name = getName(mContext, item);
|
String name = getName(mContext, item);
|
||||||
Drawable drawable;
|
|
||||||
if (item.picture == null) {
|
if (item.picture == null) {
|
||||||
drawable = getDrawable(mContext, item).mutate();
|
v.bind(name, getDrawable(mContext, item).mutate(), item.resolveId());
|
||||||
} else {
|
} else {
|
||||||
drawable = new BitmapDrawable(mContext.getResources(), item.picture);
|
v.bind(name, item.picture, item.info.id);
|
||||||
}
|
}
|
||||||
// Disable the icon if switching is disabled
|
// Disable the icon if switching is disabled
|
||||||
if (!item.isSwitchToEnabled) {
|
v.setAvatarEnabled(item.isSwitchToEnabled);
|
||||||
drawable.setTint(mContext.getColor(R.color.qs_tile_disabled_color));
|
|
||||||
}
|
|
||||||
v.bind(name, drawable);
|
|
||||||
convertView.setActivated(item.isCurrent);
|
convertView.setActivated(item.isCurrent);
|
||||||
convertView.setTag(item);
|
convertView.setTag(item);
|
||||||
return convertView;
|
return convertView;
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ import android.content.pm.UserInfo;
|
|||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.drawable.BitmapDrawable;
|
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
@@ -37,7 +36,7 @@ import android.util.Log;
|
|||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
|
|
||||||
import com.android.internal.util.UserIcons;
|
import com.android.internal.util.UserIcons;
|
||||||
import com.android.systemui.BitmapHelper;
|
import com.android.settingslib.drawable.UserIconDrawable;
|
||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -155,8 +154,8 @@ public final class UserInfoController {
|
|||||||
Drawable avatar = null;
|
Drawable avatar = null;
|
||||||
Bitmap rawAvatar = um.getUserIcon(userId);
|
Bitmap rawAvatar = um.getUserIcon(userId);
|
||||||
if (rawAvatar != null) {
|
if (rawAvatar != null) {
|
||||||
avatar = new BitmapDrawable(mContext.getResources(),
|
avatar = new UserIconDrawable(avatarSize)
|
||||||
BitmapHelper.createCircularClip(rawAvatar, avatarSize, avatarSize));
|
.setIcon(rawAvatar).setBadgeIfManagedUser(mContext, userId).bake();
|
||||||
} else {
|
} else {
|
||||||
avatar = UserIcons.getDefaultUserIcon(isGuest? UserHandle.USER_NULL : userId,
|
avatar = UserIcons.getDefaultUserIcon(isGuest? UserHandle.USER_NULL : userId,
|
||||||
/* light= */ true);
|
/* light= */ true);
|
||||||
|
|||||||
@@ -50,7 +50,6 @@ import android.widget.BaseAdapter;
|
|||||||
import com.android.internal.logging.MetricsProto.MetricsEvent;
|
import com.android.internal.logging.MetricsProto.MetricsEvent;
|
||||||
import com.android.internal.util.UserIcons;
|
import com.android.internal.util.UserIcons;
|
||||||
import com.android.settingslib.RestrictedLockUtils;
|
import com.android.settingslib.RestrictedLockUtils;
|
||||||
import com.android.systemui.BitmapHelper;
|
|
||||||
import com.android.systemui.GuestResumeSessionReceiver;
|
import com.android.systemui.GuestResumeSessionReceiver;
|
||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
import com.android.systemui.SystemUISecondaryUserService;
|
import com.android.systemui.SystemUISecondaryUserService;
|
||||||
@@ -197,8 +196,6 @@ public class UserSwitcherController {
|
|||||||
boolean canSwitchUsers = mUserManager.canSwitchUsers();
|
boolean canSwitchUsers = mUserManager.canSwitchUsers();
|
||||||
UserInfo currentUserInfo = null;
|
UserInfo currentUserInfo = null;
|
||||||
UserRecord guestRecord = null;
|
UserRecord guestRecord = null;
|
||||||
int avatarSize = mContext.getResources()
|
|
||||||
.getDimensionPixelSize(R.dimen.max_avatar_size);
|
|
||||||
|
|
||||||
for (UserInfo info : infos) {
|
for (UserInfo info : infos) {
|
||||||
boolean isCurrent = currentId == info.id;
|
boolean isCurrent = currentId == info.id;
|
||||||
@@ -219,8 +216,10 @@ public class UserSwitcherController {
|
|||||||
picture = mUserManager.getUserIcon(info.id);
|
picture = mUserManager.getUserIcon(info.id);
|
||||||
|
|
||||||
if (picture != null) {
|
if (picture != null) {
|
||||||
picture = BitmapHelper.createCircularClip(
|
int avatarSize = mContext.getResources()
|
||||||
picture, avatarSize, avatarSize);
|
.getDimensionPixelSize(R.dimen.max_avatar_size);
|
||||||
|
picture = Bitmap.createScaledBitmap(
|
||||||
|
picture, avatarSize, avatarSize, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int index = isCurrent ? 0 : records.size();
|
int index = isCurrent ? 0 : records.size();
|
||||||
@@ -664,8 +663,7 @@ public class UserSwitcherController {
|
|||||||
if (item.isAddUser) {
|
if (item.isAddUser) {
|
||||||
return context.getDrawable(R.drawable.ic_add_circle_qs);
|
return context.getDrawable(R.drawable.ic_add_circle_qs);
|
||||||
}
|
}
|
||||||
return UserIcons.getDefaultUserIcon(item.isGuest ? UserHandle.USER_NULL : item.info.id,
|
return UserIcons.getDefaultUserIcon(item.resolveId(), /* light= */ true);
|
||||||
/* light= */ true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void refresh() {
|
public void refresh() {
|
||||||
@@ -718,6 +716,13 @@ public class UserSwitcherController {
|
|||||||
isSwitchToEnabled);
|
isSwitchToEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int resolveId() {
|
||||||
|
if (isGuest || info == null) {
|
||||||
|
return UserHandle.USER_NULL;
|
||||||
|
}
|
||||||
|
return info.id;
|
||||||
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
sb.append("UserRecord(");
|
sb.append("UserRecord(");
|
||||||
|
|||||||
Reference in New Issue
Block a user