Loading core/res/res/drawable/ic_corp_user_badge.xml 0 → 100644 +24 −0 Original line number Diff line number Diff line <!-- 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> core/res/res/values/symbols.xml +1 −0 Original line number Diff line number Diff line Loading @@ -1265,6 +1265,7 @@ <java-symbol type="drawable" name="ic_corp_badge" /> <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_user_badge" /> <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_statusbar_icon" /> Loading packages/SettingsLib/src/com/android/settingslib/Utils.java +7 −6 Original line number Diff line number Diff line Loading @@ -15,7 +15,7 @@ import android.net.ConnectivityManager; import android.os.BatteryManager; import android.os.UserManager; import com.android.internal.util.UserIcons; import com.android.settingslib.drawable.CircleFramedDrawable; import com.android.settingslib.drawable.UserIconDrawable; import java.text.NumberFormat; Loading Loading @@ -73,21 +73,22 @@ public class Utils { /** * 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()) { // We use predefined values for managed profiles Bitmap b = BitmapFactory.decodeResource(context.getResources(), com.android.internal.R.drawable.ic_corp_icon); return CircleFramedDrawable.getInstance(context, b); return new UserIconDrawable(iconSize).setIcon(b).bake(); } if (user.iconPath != null) { Bitmap icon = um.getUserIcon(user.id); if (icon != null) { return CircleFramedDrawable.getInstance(context, icon); return new UserIconDrawable(iconSize).setIcon(icon).bake(); } } return CircleFramedDrawable.getInstance(context, UserIcons.convertToBitmap( UserIcons.getDefaultUserIcon(user.id, /* light= */ false))); return new UserIconDrawable(iconSize).setIconDrawable( UserIcons.getDefaultUserIcon(user.id, /* light= */ false)).bake(); } /** Formats the ratio of amount/total as a percentage. */ Loading packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java 0 → 100644 +428 −0 Original line number Diff line number Diff line /* * 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); } } packages/SettingsLib/src/com/android/settingslib/drawer/UserAdapter.java +3 −2 Original line number Diff line number Diff line Loading @@ -33,7 +33,7 @@ import android.widget.ListAdapter; import android.widget.SpinnerAdapter; import android.widget.TextView; import com.android.internal.util.UserIcons; import com.android.settingslib.drawable.CircleFramedDrawable; import com.android.settingslib.drawable.UserIconDrawable; import com.android.settingslib.R; Loading Loading @@ -71,7 +71,8 @@ public class UserAdapter implements SpinnerAdapter, ListAdapter { } 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; Loading Loading
core/res/res/drawable/ic_corp_user_badge.xml 0 → 100644 +24 −0 Original line number Diff line number Diff line <!-- 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>
core/res/res/values/symbols.xml +1 −0 Original line number Diff line number Diff line Loading @@ -1265,6 +1265,7 @@ <java-symbol type="drawable" name="ic_corp_badge" /> <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_user_badge" /> <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_statusbar_icon" /> Loading
packages/SettingsLib/src/com/android/settingslib/Utils.java +7 −6 Original line number Diff line number Diff line Loading @@ -15,7 +15,7 @@ import android.net.ConnectivityManager; import android.os.BatteryManager; import android.os.UserManager; import com.android.internal.util.UserIcons; import com.android.settingslib.drawable.CircleFramedDrawable; import com.android.settingslib.drawable.UserIconDrawable; import java.text.NumberFormat; Loading Loading @@ -73,21 +73,22 @@ public class Utils { /** * 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()) { // We use predefined values for managed profiles Bitmap b = BitmapFactory.decodeResource(context.getResources(), com.android.internal.R.drawable.ic_corp_icon); return CircleFramedDrawable.getInstance(context, b); return new UserIconDrawable(iconSize).setIcon(b).bake(); } if (user.iconPath != null) { Bitmap icon = um.getUserIcon(user.id); if (icon != null) { return CircleFramedDrawable.getInstance(context, icon); return new UserIconDrawable(iconSize).setIcon(icon).bake(); } } return CircleFramedDrawable.getInstance(context, UserIcons.convertToBitmap( UserIcons.getDefaultUserIcon(user.id, /* light= */ false))); return new UserIconDrawable(iconSize).setIconDrawable( UserIcons.getDefaultUserIcon(user.id, /* light= */ false)).bake(); } /** Formats the ratio of amount/total as a percentage. */ Loading
packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java 0 → 100644 +428 −0 Original line number Diff line number Diff line /* * 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); } }
packages/SettingsLib/src/com/android/settingslib/drawer/UserAdapter.java +3 −2 Original line number Diff line number Diff line Loading @@ -33,7 +33,7 @@ import android.widget.ListAdapter; import android.widget.SpinnerAdapter; import android.widget.TextView; import com.android.internal.util.UserIcons; import com.android.settingslib.drawable.CircleFramedDrawable; import com.android.settingslib.drawable.UserIconDrawable; import com.android.settingslib.R; Loading Loading @@ -71,7 +71,8 @@ public class UserAdapter implements SpinnerAdapter, ListAdapter { } 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; Loading