1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings.drawable; 18 19 import android.content.Context; 20 import android.content.res.Resources; 21 import android.graphics.Bitmap; 22 import android.graphics.Canvas; 23 import android.graphics.Color; 24 import android.graphics.ColorFilter; 25 import android.graphics.Paint; 26 import android.graphics.Path; 27 import android.graphics.PixelFormat; 28 import android.graphics.PorterDuff; 29 import android.graphics.PorterDuffXfermode; 30 import android.graphics.Rect; 31 import android.graphics.RectF; 32 import android.graphics.drawable.Drawable; 33 34 import com.android.settings.R; 35 36 /** 37 * Converts the user avatar icon to a circularly clipped one. 38 * TODO: Move this to an internal framework class and share with the one in Keyguard. 39 */ 40 public class CircleFramedDrawable extends Drawable { 41 42 private final Bitmap mBitmap; 43 private final int mSize; 44 private final Paint mPaint; 45 private final float mShadowRadius; 46 private final float mStrokeWidth; 47 private final int mFrameColor; 48 private final int mHighlightColor; 49 private final int mFrameShadowColor; 50 51 private float mScale; 52 private Path mFramePath; 53 private Rect mSrcRect; 54 private RectF mDstRect; 55 private RectF mFrameRect; 56 private boolean mPressed; 57 58 public static CircleFramedDrawable getInstance(Context context, Bitmap icon) { 59 Resources res = context.getResources(); 60 float iconSize = res.getDimension(R.dimen.circle_avatar_size); 61 float strokeWidth = res.getDimension(R.dimen.circle_avatar_frame_stroke_width); 62 float shadowRadius = res.getDimension(R.dimen.circle_avatar_frame_shadow_radius); 63 int frameColor = res.getColor(R.color.circle_avatar_frame_color); 64 int frameShadowColor = res.getColor(R.color.circle_avatar_frame_shadow_color); 65 int highlightColor = res.getColor(R.color.circle_avatar_frame_pressed_color); 66 67 CircleFramedDrawable instance = new CircleFramedDrawable(icon, 68 (int) iconSize, frameColor, strokeWidth, frameShadowColor, shadowRadius, 69 highlightColor); 70 return instance; 71 } 72 73 public CircleFramedDrawable(Bitmap icon, int size, 74 int frameColor, float strokeWidth, 75 int frameShadowColor, float shadowRadius, 76 int highlightColor) { 77 super(); 78 mSize = size; 79 mShadowRadius = shadowRadius; 80 mFrameColor = frameColor; 81 mFrameShadowColor = frameShadowColor; 82 mStrokeWidth = strokeWidth; 83 mHighlightColor = highlightColor; 84 85 mBitmap = Bitmap.createBitmap(mSize, mSize, Bitmap.Config.ARGB_8888); 86 final Canvas canvas = new Canvas(mBitmap); 87 88 final int width = icon.getWidth(); 89 final int height = icon.getHeight(); 90 final int square = Math.min(width, height); 91 92 final Rect cropRect = new Rect((width - square) / 2, (height - square) / 2, square, square); 93 final RectF circleRect = new RectF(0f, 0f, mSize, mSize); 94 circleRect.inset(mStrokeWidth / 2f, mStrokeWidth / 2f); 95 circleRect.inset(mShadowRadius, mShadowRadius); 96 97 final Path fillPath = new Path(); 98 fillPath.addArc(circleRect, 0f, 360f); 99 100 canvas.drawColor(0, PorterDuff.Mode.CLEAR); 101 102 // opaque circle matte 103 mPaint = new Paint(); 104 mPaint.setAntiAlias(true); 105 mPaint.setColor(Color.BLACK); 106 mPaint.setStyle(Paint.Style.FILL); 107 canvas.drawPath(fillPath, mPaint); 108 109 // mask in the icon where the bitmap is opaque 110 mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); 111 canvas.drawBitmap(icon, cropRect, circleRect, mPaint); 112 113 // prepare paint for frame drawing 114 mPaint.setXfermode(null); 115 116 mScale = 1f; 117 118 mSrcRect = new Rect(0, 0, mSize, mSize); 119 mDstRect = new RectF(0, 0, mSize, mSize); 120 mFrameRect = new RectF(mDstRect); 121 mFramePath = new Path(); 122 } 123 124 @Override 125 public void draw(Canvas canvas) { 126 final float inside = mScale * mSize; 127 final float pad = (mSize - inside) / 2f; 128 129 mDstRect.set(pad, pad, mSize - pad, mSize - pad); 130 canvas.drawBitmap(mBitmap, mSrcRect, mDstRect, null); 131 132 mFrameRect.set(mDstRect); 133 mFrameRect.inset(mStrokeWidth / 2f, mStrokeWidth / 2f); 134 mFrameRect.inset(mShadowRadius, mShadowRadius); 135 136 mFramePath.reset(); 137 mFramePath.addArc(mFrameRect, 0f, 360f); 138 139 // white frame 140 if (mPressed) { 141 mPaint.setStyle(Paint.Style.FILL); 142 mPaint.setColor(Color.argb((int) (0.33f * 255), 143 Color.red(mHighlightColor), 144 Color.green(mHighlightColor), 145 Color.blue(mHighlightColor))); 146 canvas.drawPath(mFramePath, mPaint); 147 } 148 mPaint.setStrokeWidth(mStrokeWidth); 149 mPaint.setStyle(Paint.Style.STROKE); 150 mPaint.setColor(mPressed ? mHighlightColor : mFrameColor); 151 mPaint.setShadowLayer(mShadowRadius, 0f, 0f, mFrameShadowColor); 152 canvas.drawPath(mFramePath, mPaint); 153 } 154 155 public void setScale(float scale) { 156 mScale = scale; 157 } 158 159 public float getScale() { 160 return mScale; 161 } 162 163 public void setPressed(boolean pressed) { 164 mPressed = pressed; 165 } 166 167 @Override 168 public int getOpacity() { 169 return PixelFormat.TRANSLUCENT; 170 } 171 172 @Override 173 public void setAlpha(int alpha) { 174 } 175 176 @Override 177 public void setColorFilter(ColorFilter cf) { 178 } 179 180 @Override 181 public int getIntrinsicWidth() { 182 return mSize; 183 } 184 185 @Override 186 public int getIntrinsicHeight() { 187 return mSize; 188 } 189 } 190