UserAvatarView.java revision 8ddb2da8759c29b3968b4d6bb9488f59a19f0ff2
1/* 2 * Copyright (C) 2014 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 17package com.android.systemui.statusbar.phone; 18 19import com.android.systemui.R; 20 21import android.content.Context; 22import android.content.res.TypedArray; 23import android.graphics.Bitmap; 24import android.graphics.BitmapShader; 25import android.graphics.Canvas; 26import android.graphics.Matrix; 27import android.graphics.Paint; 28import android.graphics.Shader; 29import android.graphics.drawable.Drawable; 30import android.util.AttributeSet; 31import android.view.View; 32 33/** 34 * A view that displays a user image cropped to a circle with a frame. 35 */ 36public class UserAvatarView extends View { 37 38 private int mActiveFrameColor; 39 private int mFrameColor; 40 private float mFrameWidth; 41 private Bitmap mBitmap; 42 private Drawable mDrawable; 43 44 private final Paint mFramePaint = new Paint(); 45 private final Paint mBitmapPaint = new Paint(); 46 private final Matrix mDrawMatrix = new Matrix(); 47 48 private float mScale = 1; 49 50 public UserAvatarView(Context context, AttributeSet attrs, 51 int defStyleAttr, 52 int defStyleRes) { 53 super(context, attrs, defStyleAttr, defStyleRes); 54 final TypedArray a = context.obtainStyledAttributes( 55 attrs, R.styleable.UserAvatarView, defStyleAttr, defStyleRes); 56 final int N = a.getIndexCount(); 57 for (int i = 0; i < N; i++) { 58 int attr = a.getIndex(i); 59 switch (attr) { 60 case R.styleable.UserAvatarView_frameWidth: 61 setFrameWidth(a.getDimension(attr, 0)); 62 break; 63 case R.styleable.UserAvatarView_activeFrameColor: 64 setActiveFrameColor(a.getColor(attr, 0)); 65 break; 66 case R.styleable.UserAvatarView_frameColor: 67 setFrameColor(a.getColor(attr, 0)); 68 break; 69 } 70 } 71 a.recycle(); 72 73 mFramePaint.setAntiAlias(true); 74 mFramePaint.setStyle(Paint.Style.STROKE); 75 mBitmapPaint.setAntiAlias(true); 76 } 77 78 public UserAvatarView(Context context, AttributeSet attrs, int defStyleAttr) { 79 this(context, attrs, defStyleAttr, 0); 80 } 81 82 public UserAvatarView(Context context, AttributeSet attrs) { 83 this(context, attrs, 0); 84 } 85 86 public UserAvatarView(Context context) { 87 this(context, null); 88 } 89 90 public void setBitmap(Bitmap bitmap) { 91 setDrawable(null); 92 mBitmap = bitmap; 93 mBitmapPaint.setShader(new BitmapShader( 94 bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)); 95 configureBounds(); 96 invalidate(); 97 } 98 99 public void setFrameColor(int frameColor) { 100 mFrameColor = frameColor; 101 invalidate(); 102 } 103 104 public void setActiveFrameColor(int activeFrameColor) { 105 mActiveFrameColor = activeFrameColor; 106 invalidate(); 107 } 108 109 public void setFrameWidth(float frameWidth) { 110 mFrameWidth = frameWidth; 111 invalidate(); 112 } 113 114 @Override 115 protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 116 super.onLayout(changed, left, top, right, bottom); 117 configureBounds(); 118 } 119 120 public void configureBounds() { 121 int vwidth = getWidth() - mPaddingLeft - mPaddingRight; 122 int vheight = getHeight() - mPaddingTop - mPaddingBottom; 123 124 int dwidth; 125 int dheight; 126 if (mBitmap != null) { 127 dwidth = mBitmap.getWidth(); 128 dheight = mBitmap.getHeight(); 129 } else if (mDrawable != null) { 130 dwidth = mDrawable.getIntrinsicWidth(); 131 dheight = mDrawable.getIntrinsicHeight(); 132 mDrawable.setBounds(0, 0, dwidth, dheight); 133 vwidth -= 2 * (mFrameWidth - 1); 134 vheight -= 2 * (mFrameWidth - 1); 135 } else { 136 return; 137 } 138 139 float scale; 140 float dx; 141 float dy; 142 143 scale = Math.min((float) vwidth / (float) dwidth, 144 (float) vheight / (float) dheight); 145 146 dx = (int) ((vwidth - dwidth * scale) * 0.5f + 0.5f); 147 dy = (int) ((vheight - dheight * scale) * 0.5f + 0.5f); 148 149 mDrawMatrix.setScale(scale, scale); 150 mDrawMatrix.postTranslate(dx, dy); 151 mScale = scale; 152 } 153 154 @Override 155 protected void onDraw(Canvas canvas) { 156 int frameColor = isActivated() ? mActiveFrameColor : mFrameColor; 157 float halfW = getWidth() / 2f; 158 float halfH = getHeight() / 2f; 159 float halfSW = Math.min(halfH, halfW); 160 if (mBitmap != null && mScale > 0) { 161 int saveCount = canvas.getSaveCount(); 162 canvas.save(); 163 canvas.translate(mPaddingLeft, mPaddingTop); 164 canvas.concat(mDrawMatrix); 165 float halfBW = mBitmap.getWidth() / 2f; 166 float halfBH = mBitmap.getHeight() / 2f; 167 float halfBSW = Math.min(halfBH, halfBW); 168 canvas.drawCircle(halfBW, halfBH, halfBSW - mFrameWidth / mScale + 1, mBitmapPaint); 169 canvas.restoreToCount(saveCount); 170 } else if (mDrawable != null && mScale > 0) { 171 int saveCount = canvas.getSaveCount(); 172 canvas.save(); 173 canvas.translate(mPaddingLeft, mPaddingTop); 174 canvas.translate(mFrameWidth - 1, mFrameWidth - 1); 175 canvas.concat(mDrawMatrix); 176 mDrawable.draw(canvas); 177 canvas.restoreToCount(saveCount); 178 } 179 if (frameColor != 0) { 180 mFramePaint.setColor(frameColor); 181 mFramePaint.setStrokeWidth(mFrameWidth); 182 canvas.drawCircle(halfW, halfH, halfSW - mFrameWidth / 2f, mFramePaint); 183 } 184 } 185 186 public void setDrawable(Drawable d) { 187 if (mDrawable != null) { 188 mDrawable.setCallback(null); 189 unscheduleDrawable(mDrawable); 190 } 191 mDrawable = d; 192 if (d != null) { 193 d.setCallback(this); 194 if (d.isStateful()) { 195 d.setState(getDrawableState()); 196 } 197 d.setLayoutDirection(getLayoutDirection()); 198 configureBounds(); 199 } 200 if (d != null) { 201 mBitmap = null; 202 } 203 configureBounds(); 204 invalidate(); 205 } 206 207 @Override 208 public void invalidateDrawable(Drawable dr) { 209 if (dr == mDrawable) { 210 invalidate(); 211 } else { 212 super.invalidateDrawable(dr); 213 } 214 } 215} 216