1. 程式人生 > >Android自定義控制元件之圓形頭像

Android自定義控制元件之圓形頭像

重寫ImageView

public class CircleImageView extends ImageView {

   private static final ScaleType SCALE_TYPE = ScaleType.CENTER_CROP;
   private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888;
   private static final int COLORDRAWABLE_DIMENSION = 1;
   private static final int DEFAULT_BORDER_WIDTH 
= 0; private static final int DEFAULT_BORDER_COLOR = Color.BLACK; private final RectF mDrawableRect = new RectF(); private final RectF mBorderRect = new RectF(); private final Matrix mShaderMatrix = new Matrix(); private final Paint mBitmapPaint = new Paint(); private final Paint mBorderPaint
= new Paint(); private int mBorderColor = DEFAULT_BORDER_COLOR; private int mBorderWidth = DEFAULT_BORDER_WIDTH; private Bitmap mBitmap; private BitmapShader mBitmapShader; private int mBitmapWidth; private int mBitmapHeight; private float mDrawableRadius; private float mBorderRadius
; private boolean mReady; private boolean mSetupPending; public CircleImageView(final Context context) { super(context); } public CircleImageView(final Context context, final AttributeSet attrs) { this(context, attrs, 0); } public CircleImageView(final Context context, final AttributeSet attrs, final int defStyle) { super(context, attrs, defStyle); super.setScaleType(SCALE_TYPE); final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CircleImageView, defStyle, 0); mBorderWidth = a.getDimensionPixelSize( R.styleable.CircleImageView_border_width, DEFAULT_BORDER_WIDTH); mBorderColor = a.getColor(R.styleable.CircleImageView_border_color, DEFAULT_BORDER_COLOR); a.recycle(); mReady = true; if (mSetupPending) { setup(); mSetupPending = false; } } @Override public ScaleType getScaleType() { return SCALE_TYPE; } @Override public void setScaleType(final ScaleType scaleType) { if (scaleType != SCALE_TYPE) { throw new IllegalArgumentException(String.format( "ScaleType %s not supported.", scaleType)); } } @Override protected void onDraw(final Canvas canvas) { if (getDrawable() == null) { return; } canvas.drawCircle(getWidth() / 2, getHeight() / 2, mDrawableRadius, mBitmapPaint); if (mBorderWidth != 0) { canvas.drawCircle(getWidth() / 2, getHeight() / 2, mBorderRadius, mBorderPaint); } } @Override protected void onSizeChanged(final int w, final int h, final int oldw, final int oldh) { super.onSizeChanged(w, h, oldw, oldh); setup(); } public int getBorderColor() { return mBorderColor; } public void setBorderColor(final int borderColor) { if (borderColor == mBorderColor) { return; } mBorderColor = borderColor; mBorderPaint.setColor(mBorderColor); invalidate(); } public int getBorderWidth() { return mBorderWidth; } public void setBorderWidth(final int borderWidth) { if (borderWidth == mBorderWidth) { return; } mBorderWidth = borderWidth; setup(); } @Override public void setImageBitmap(final Bitmap bm) { super.setImageBitmap(bm); mBitmap = bm; setup(); } @Override public void setImageDrawable(final Drawable drawable) { super.setImageDrawable(drawable); mBitmap = getBitmapFromDrawable(drawable); setup(); } @Override public void setImageResource(final int resId) { super.setImageResource(resId); mBitmap = getBitmapFromDrawable(getDrawable()); setup(); } private Bitmap getBitmapFromDrawable(final Drawable drawable) { if (drawable == null) { return null; } if (drawable instanceof BitmapDrawable) { return ((BitmapDrawable) drawable).getBitmap(); } try { Bitmap bitmap; if (drawable instanceof ColorDrawable) { bitmap = Bitmap.createBitmap(COLORDRAWABLE_DIMENSION, COLORDRAWABLE_DIMENSION, BITMAP_CONFIG); } else { bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), BITMAP_CONFIG); } final Canvas canvas = new Canvas(bitmap); drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); drawable.draw(canvas); return bitmap; } catch (final OutOfMemoryError e) { return null; } } private void setup() { if (!mReady) { mSetupPending = true; return; } if (mBitmap == null) { return; } mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); mBitmapPaint.setAntiAlias(true); mBitmapPaint.setShader(mBitmapShader); mBorderPaint.setStyle(Paint.Style.STROKE); mBorderPaint.setAntiAlias(true); mBorderPaint.setColor(mBorderColor); mBorderPaint.setStrokeWidth(mBorderWidth); mBitmapHeight = mBitmap.getHeight(); mBitmapWidth = mBitmap.getWidth(); mBorderRect.set(0, 0, getWidth(), getHeight()); mBorderRadius = Math.min((mBorderRect.height() - mBorderWidth) / 2, (mBorderRect.width() - mBorderWidth) / 2); mDrawableRect.set(mBorderWidth, mBorderWidth, mBorderRect.width() - mBorderWidth, mBorderRect.height() - mBorderWidth); mDrawableRadius = Math.min(mDrawableRect.height() / 2, mDrawableRect.width() / 2); updateShaderMatrix(); invalidate(); } private void updateShaderMatrix() { float scale; float dx = 0; float dy = 0; mShaderMatrix.set(null); if (mBitmapWidth * mDrawableRect.height() > mDrawableRect.width() * mBitmapHeight) { scale = mDrawableRect.height() / mBitmapHeight; dx = (mDrawableRect.width() - mBitmapWidth * scale) * 0.5f; } else { scale = mDrawableRect.width() / mBitmapWidth; dy = (mDrawableRect.height() - mBitmapHeight * scale) * 0.5f; } mShaderMatrix.setScale(scale, scale); mShaderMatrix.postTranslate((int) (dx + 0.5f) + mBorderWidth, (int) (dy + 0.5f) + mBorderWidth); mBitmapShader.setLocalMatrix(mShaderMatrix); } }

使用方法:

在佈局檔案中

<cn.XXX.view.CircleImageView
android:id="@+id/iv_avatar"
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@drawable/avatar"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"/>

效果圖 


相關推薦

Android定義控制元件圓形頭像

重寫ImageView public class CircleImageView extends ImageView { private static final ScaleType SCALE_TYPE = ScaleType.CENTER_CROP; p

android定義控制元件圓形進度條(帶動畫)

首先貼上圖片: 額,感覺還行吧,就是進度條的顏色醜了點,不過咱是程式設計師,不是美工,配色這種問題當然不在考慮範圍之內了 下面說重點,如何來寫一個這樣的自定義控制元件。 首先,需要有一個灰色的底圖,來作為未填充時的進度條; 然後,根據傳入的當前進度值,繪製填充時的進度圓

Android定義控制元件區域性圖片放大鏡--BiggerView

零、前言: 本文的知識點一覽 1.自定義控制元件及自定義屬性的寫法,你也將對onMesure有更深的認識 2.關於bitmap的簡單處理,及canvas區域裁剪 3.本文會實現兩個自定義控制元件:FitImageView(圖片自適應)和BiggerView(放大鏡),前者為後者作為鋪墊。 4.最後會

Android定義控制元件仿汽車家下拉重新整理

關於下拉重新整理的實現原理我在上篇文章Android自定義控制元件之仿美團下拉重新整理中已經詳細介紹過了,這篇文章主要介紹錶盤的動畫實現原理 汽車之家的下拉重新整理分為三個狀態: 第一個狀態為下拉重新整理狀態(pull to refresh),在這個狀

Android定義控制元件《折線圖的繪製》

金融軟體裡的行情分時圖,這是我們最常見的折線圖,當然了,折線圖的用途並不僅僅侷限於此,像一般在一定區間內,為了更好的能顯示出幅度的變化,那麼用折線圖來展示無疑是最符合效果的,當然了,網上也有很多的第

Android定義控制元件實現滑動選擇開關

前言:今天我們仿照著Google給我們提供的Switch控制元件來進行一次模仿,自己動手打造一個可以換滑動圖片以及背景的圖片。 -----------------分割線--------------- 先看一下google提供的Switc控制元件: 其實用法很簡單就當普通的

Android 定義控制元件繼承view

一.自定義控制元件的型別:            1.繼承view(自繪檢視:view中的內容是我們自己繪製出來的,需要重寫onDraw方法)            2.繼承已有原生控制元件            3.自定義組合控制元件(將系統原生的控制元件組合到一起) 本

Android定義控制元件百分比圓環進度條

首先我們先來看一下效果 分析 我們來看這個進度條應該分為3個小部分 1.中間的圓 2.外邊的圓環 3.中間的文字 分開畫 這3部分就是需要我們自己畫出來的,因此我們需要3根畫筆 //設定中心園的畫筆

Android定義控制元件NumberCircleProgressBar(圓形進度條)的實現

Mode Rotate 實現方式 1.使用unreachedarea的顏色繪製Circle,作為底層; canvas.drawCircle(centerX, centerY,mCircleRadius, mCirclePaint); 2.使用reacherarea的顏色繪製扇形,作為中間層; canvas.

Android 定義控制元件命運輪(抽獎轉盤)

1 思路 首先肯定是要繪製扇形的,每一個獎品為一個扇形區分開,然後在扇形中得有當前獎品的說明,最後讓這個輪盤轉起來就行了。說起來很簡單,但是在繪製的時候,特別是繪製文字的時候還有有一些細節需要注意的,也不是難點,只是要理清楚那些地方應該怎麼去畫,怎麼獲取需要繪製的座標。  

Android 定義控制元件ViewPager Indicator實現方式

介紹 ViewPager 的Indicator實現兩種效果 如下圖所示: 效果一 效果二 佈局檔案: <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmln

Android定義控制元件掃描動畫UI

前言 最近有一個需求,就是做一個掃描的UI,看了很多掃描動畫,發現酷狗的掃描動畫挺漂亮的,所以就做了一個相似的掃描動畫,廢話不多說,先看一下最終的效果吧。 最終效果圖 介紹 首先我們看一下這個效果,它由以下幾部分組成: 1.中間一個音符圖片

Android定義控制元件測量onMeasure

由上圖可知,語法角度:子類可以重寫onMeasure,只能繼承View的measure,setMeasuredDimension方法。測量流程分為兩種情況討論:容器控制元件ViewGroup,原始的View(非容器控制元件)。原始的View測量,只需要測量自己的寬高;而容器控制元件需要先測量所有的子View

Android 定義控制元件 繼承佈局檔案

首先定義一個layout實現按鈕內部佈局: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:andr

Android定義控制元件入門篇---整理網路上的資源

前言, 我的視訊系列 http://edu.csdn.net/course/detail/2741, 一起來學習Android… 本篇部落格主要是想要講解一下自定義控制元件如何入門,其中有好多資料資源來源自網路,綜合了網路上一些有些的博文

Android定義控制元件畫圓,並且修改其填充色

畫圓就是簡答呼叫了drawCircle的api public class Dot extends View { public Dot(Context context) { s

Android 定義控制元件打造流佈局實現熱門搜尋標籤

最終效果 首先來看看效果圖: 其他地方很好實現,就是熱門搜尋有點麻煩,由於資料的不確定性,那麼像GridView明顯不能滿足了,這時候就只能自己來定義一個佈局了。 最終實現後的效果: 具體實現 1,自定義一個類繼承

Android定義控制元件定義TextView,實現drawableLeft可以和文字一起居中

LZ-Says:給大家推薦一個網站,有興趣可以查閱,想為大家貢獻一點自己的力量也可以投稿,老大稽核通過會發表,更好的幫助有需要的人~歡迎大家踴躍投稿~地址如下: http://ww

Android 定義控制元件基礎幾何圖形繪製詳解

前言 距離寫上一篇自定義View文章已經大半年過去了,一直想繼續寫,但是無奈技術有限,生怕誤人子弟。這段時間專案剛剛完成,有點時間,跟著大神的腳步,鞏固下自定義View的相關基礎知識。 Canvas&Paint Canvas和Pa

定義控制元件圓形顏色漸變進度條--SweepGradient

前幾天在群裡面有人找圓形可顏色漸變進度條,其中主要的知識點是SweepGradient;(要看具體需要的漸變效果,LinearGradient線性漸變也是可以的,例如Settings內的電量介面的圓形電量進度WrapCircleVIew) mSweepGradient = n