UserAvatarView.java revision b325ce8203a751b0223e737be1469c42907e6cd5
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 if (mBitmap != null) { 94 mBitmapPaint.setShader(new BitmapShader( 95 bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)); 96 } else { 97 mBitmapPaint.setShader(null); 98 } 99 configureBounds(); 100 invalidate(); 101 } 102 103 public void setFrameColor(int frameColor) { 104 mFrameColor = frameColor; 105 invalidate(); 106 } 107 108 public void setActiveFrameColor(int activeFrameColor) { 109 mActiveFrameColor = activeFrameColor; 110 invalidate(); 111 } 112 113 public void setFrameWidth(float frameWidth) { 114 mFrameWidth = frameWidth; 115 invalidate(); 116 } 117 118 @Override 119 protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 120 super.onLayout(changed, left, top, right, bottom); 121 configureBounds(); 122 } 123 124 public void configureBounds() { 125 int vwidth = getWidth() - mPaddingLeft - mPaddingRight; 126 int vheight = getHeight() - mPaddingTop - mPaddingBottom; 127 128 int dwidth; 129 int dheight; 130 if (mBitmap != null) { 131 dwidth = mBitmap.getWidth(); 132 dheight = mBitmap.getHeight(); 133 } else if (mDrawable != null) { 134 dwidth = mDrawable.getIntrinsicWidth(); 135 dheight = mDrawable.getIntrinsicHeight(); 136 mDrawable.setBounds(0, 0, dwidth, dheight); 137 vwidth -= 2 * (mFrameWidth - 1); 138 vheight -= 2 * (mFrameWidth - 1); 139 } else { 140 return; 141 } 142 143 float scale; 144 float dx; 145 float dy; 146 147 scale = Math.min((float) vwidth / (float) dwidth, 148 (float) vheight / (float) dheight); 149 150 dx = (int) ((vwidth - dwidth * scale) * 0.5f + 0.5f); 151 dy = (int) ((vheight - dheight * scale) * 0.5f + 0.5f); 152 153 mDrawMatrix.setScale(scale, scale); 154 mDrawMatrix.postTranslate(dx, dy); 155 mScale = scale; 156 } 157 158 @Override 159 protected void onDraw(Canvas canvas) { 160 int frameColor = isActivated() ? mActiveFrameColor : mFrameColor; 161 float halfW = getWidth() / 2f; 162 float halfH = getHeight() / 2f; 163 float halfSW = Math.min(halfH, halfW); 164 if (mBitmap != null && mScale > 0) { 165 int saveCount = canvas.getSaveCount(); 166 canvas.save(); 167 canvas.translate(mPaddingLeft, mPaddingTop); 168 canvas.concat(mDrawMatrix); 169 float halfBW = mBitmap.getWidth() / 2f; 170 float halfBH = mBitmap.getHeight() / 2f; 171 float halfBSW = Math.min(halfBH, halfBW); 172 canvas.drawCircle(halfBW, halfBH, halfBSW - mFrameWidth / mScale + 1, mBitmapPaint); 173 canvas.restoreToCount(saveCount); 174 } else if (mDrawable != null && mScale > 0) { 175 int saveCount = canvas.getSaveCount(); 176 canvas.save(); 177 canvas.translate(mPaddingLeft, mPaddingTop); 178 canvas.translate(mFrameWidth - 1, mFrameWidth - 1); 179 canvas.concat(mDrawMatrix); 180 mDrawable.draw(canvas); 181 canvas.restoreToCount(saveCount); 182 } 183 if (frameColor != 0) { 184 mFramePaint.setColor(frameColor); 185 mFramePaint.setStrokeWidth(mFrameWidth); 186 canvas.drawCircle(halfW, halfH, halfSW - mFrameWidth / 2f, mFramePaint); 187 } 188 } 189 190 public void setDrawable(Drawable d) { 191 if (mDrawable != null) { 192 mDrawable.setCallback(null); 193 unscheduleDrawable(mDrawable); 194 } 195 mDrawable = d; 196 if (d != null) { 197 d.setCallback(this); 198 if (d.isStateful()) { 199 d.setState(getDrawableState()); 200 } 201 d.setLayoutDirection(getLayoutDirection()); 202 configureBounds(); 203 } 204 if (d != null) { 205 mBitmap = null; 206 } 207 configureBounds(); 208 invalidate(); 209 } 210 211 @Override 212 public void invalidateDrawable(Drawable dr) { 213 if (dr == mDrawable) { 214 invalidate(); 215 } else { 216 super.invalidateDrawable(dr); 217 } 218 } 219} 220