1. 程式人生 > >Android圓形圖片CircleImageView的使用和分析

Android圓形圖片CircleImageView的使用和分析

在專案開發中,我們經常需要用到圓形圖片效果,典型案例是使用者頭像的顯示。

如圖所示。


下面我們使用開源控制元件CircleImageView來實現該效果。

CircleImageView專案下載地址:
https://github.com/hdodenhof/CircleImageView

(1).CircleImageView的使用

首先我們將CircleImageView新增到gradle。

  1. dependencies {  
  2.     compile 'de.hdodenhof:circleimageview:2.1.0'  
  3. }  

然後看一下自定義屬性attrs:

  1. <declare-styleable
    name="CircleImageView">
  2.         <attrname="civ_border_width"format="dimension"/>
  3.         <attrname="civ_border_color"format="color"/>
  4.         <attrname="civ_border_overlay"format="boolean"/>
  5.         <attrname="civ_fill_color"format="color"/>
  6.     </declare-styleable>
屬性介紹:civ_border_width:   設定邊框的寬度,預設為0,即無邊框。

civ_border_color:    設定邊框的顏色,預設為黑色。
civ_border_overlay:設定邊框是否覆蓋在圖片上,預設為false,即邊框在圖片外圈。
civ_fill_color:           設定圖片的底色,預設透明。

接下來在佈局檔案中引入CircleImageView。
  1. <de.hdodenhof.circleimageview.CircleImageView
  2.         xmlns:circleimageview="http://schemas.android.com/apk/res-auto"
  3.         android:id="@+id/imageview"
  4.         android:layout_width="wrap_content"
  5.         android:layout_height="wrap_content"
  6.         android:src="@drawable/profile"
  7.         circleimageview:civ_border_color="@android:color/holo_red_light"
  8.         circleimageview:civ_border_overlay="false"
  9.         circleimageview:civ_border_width="2dp"
  10.         circleimageview:civ_fill_color="@android:color/holo_blue_light"/>

注意:CircleImageView的預設ScaleType為CENTER_CROP,且只能為CENTER_CROP。

(2).CircleImageView的原始碼分析

通過檢視原始碼可以看到,內部核心方法主要是對Paint、Canvas、BitmapShader、Matrix、RectF類的使用。

我們分析一下程式碼的執行流程。首先可以通過佈局檔案中的src屬性或者java程式碼的setImageXxx()方法來設定圖片,控制元件在構造方法中獲取到自定義屬性的引數值,然後會執行到setup()這個方法。

我們來分析一下setup()方法,該方法是CircleImageView的核心。

  1. privatevoid setup() {  
  2.         // mReady和mSetupPending屬性,在構造方法和setup()方法都有引用和賦值
  3.         // 目的是確保setup()內部邏輯的執行是在構造方法執行完畢之後,即獲取到自定義屬性引數之後
  4.         if (!mReady) {  
  5.             mSetupPending = true;  
  6.             return;  
  7.         }  
  8.         // 圖片寬高為0,不往下執行
  9.         if (getWidth() == 0 && getHeight() == 0) {  
  10.             return;  
  11.         }  
  12.         // 只有傳入了圖片,才會往下執行
  13.         if (mBitmap == null) {  
  14.             invalidate();  
  15.             return;  
  16.         }  
  17.         // BitmapShader類用來渲染頭像
  18.         // 引數1:要處理的bitmap物件,引數2和3:指定模式為對圖片的邊緣進行拉伸
  19.         mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);  
  20.         // 圖片畫筆:設定抗鋸齒
  21.         mBitmapPaint.setAntiAlias(true);  
  22.         // 圖片畫筆:設定渲染器
  23.         mBitmapPaint.setShader(mBitmapShader);  
  24.         // 邊框畫筆:設定樣式為描邊
  25.         mBorderPaint.setStyle(Paint.Style.STROKE);  
  26.         // 邊框畫筆:設定抗鋸齒
  27.         mBorderPaint.setAntiAlias(true);  
  28.         // 邊框畫筆:設定顏色值
  29.         mBorderPaint.setColor(mBorderColor);  
  30.         // 邊框畫筆:設定寬度
  31.         mBorderPaint.setStrokeWidth(mBorderWidth);  
  32.         // 底色畫筆:設定樣式為填充
  33.         mFillPaint.setStyle(Paint.Style.FILL);  
  34.         // 底色畫筆:設定抗鋸齒
  35.         mFillPaint.setAntiAlias(true);  
  36.         // 底色畫筆:設定顏色
  37.         mFillPaint.setColor(mFillColor);  
  38.         // 獲取原圖的高度
  39.         mBitmapHeight = mBitmap.getHeight();  
  40.         // 獲取原圖的寬度
  41.         mBitmapWidth = mBitmap.getWidth();  
  42.         // 設定邊框的顯示區域
  43.         mBorderRect.set(calculateBounds());  
  44.         // 計算邊框的半徑
  45.         mBorderRadius = Math.min((mBorderRect.height() - mBorderWidth) / 2.0f, (mBorderRect.width() - mBorderWidth) / 2.0f);  
  46.         // 設定圖片的顯示區域為上面計算出來的mBorderRect
  47.         mDrawableRect.set(mBorderRect);  
  48.         // 如果邊框不是覆蓋在圖片之上,並且邊框寬度大於0,擴大圖片的顯示區域,增加mBorderWidth-1
  49.         if (!mBorderOverlay && mBorderWidth > 0) {  
  50.             mDrawableRect.inset(mBorderWidth - 1.0f, mBorderWidth - 1.0f);  
  51.         }  
  52.         // 計算圖片的半徑
  53.         mDrawableRadius = Math.min(mDrawableRect.height() / 2.0f, mDrawableRect.width() / 2.0f);  
  54.         // 該方法內部只有一行程式碼,mBitmapPaint.setColorFilter(mColorFilter),給bitmap新增濾鏡
  55.         applyColorFilter();  
  56.         updateShaderMatrix();// 下文會介紹
  57.         invalidate();// 下文會介紹
  58.     }  

上述setup()方法中使用到了updateShaderMatrix()方法。
  1. privatevoid updateShaderMatrix() {  
  2.         float scale;  
  3.         float dx = 0;  
  4.         float dy = 0;  
  5.         mShaderMatrix.set(null);  
  6.         // 這裡取最小的縮放比例,以儘量保證圖片的質量
  7.         // 判斷如果寬度的比例大於高度的比例,取高度的縮放比,平移x軸方向
  8.         // 否則取寬度的縮放比,平移y軸方向
  9.         if (mBitmapWidth * mDrawableRect.height() > mDrawableRect.width() * mBitmapHeight) {  
  10.             scale = mDrawableRect.height() / (float) mBitmapHeight;  
  11.             dx = (mDrawableRect.width() - mBitmapWidth * scale) * 0.5f;  
  12.         } else {  
  13.             scale = mDrawableRect.width() / (float) mBitmapWidth;  
  14.             dy = (mDrawableRect.height() - mBitmapHeight * scale) * 0.5f;  
  15.         }  
  16.         // 設定mShaderMatrix:縮放
  17.         mShaderMatrix.setScale(scale, scale);  
  18.         // 設定mShaderMatrix:平移
  19.         mShaderMatrix.postTranslate((int) (dx + 0.5f) + mDrawableRect.left, (int) (dy + 0.5f) + mDrawableRect.top);  
  20.         // 將mShaderMatrix設定到mBitmapShader
  21.         mBitmapShader.setLocalMatrix(mShaderMatrix);  
  22.     }  

該方法的作用是設定mBitmapShader變數的mShaderMatrix引數,對圖片進行縮放setScale()和平移postTranslate(),使圖片的顯示區域縮放到與mDrawableRect一致,並通過平移確保顯示圖片的中心位置。

在setup()方法中最後一行執行invalidate(),觸發View的onDraw()方法。

  1. @Override
  2.     protectedvoid onDraw(Canvas canvas) {  
  3.         // 如果禁止顯示圓形(setDisableCircularTransformation()方法可設定),則不往下執行。
  4.         if (mDisableCircularTransformation) {  
  5.             super.onDraw(canvas);  
  6.             return;  
  7.         }  
  8.         // 未設定圖片,不往下執行
  9.         if (mBitmap == null) {  
  10.             return;  
  11.         }  
  12.         // 如果底色不是透明,繪製底色
  13.         if (mFillColor != Color.TRANSPARENT) {  
  14.             canvas.drawCircle(mDrawableRect.centerX(), mDrawableRect.centerY(), mDrawableRadius, mFillPaint);  
  15.         }  
  16.         // 使用上面設定好的mDrawableRect、mDrawableRadius、mBitmapPaint,繪製圓形圖片,即內圓
  17.         canvas.drawCircle(mDrawableRect.centerX(), mDrawableRect.centerY(), mDrawableRadius, mBitmapPaint);  
  18.         // 如果邊框寬度大於0,使用上面設定好的mBorderRect、mBorderRadius、mBorderPaint,繪製圓形邊框,即外圓
  19.         if (mBorderWidth > 0) {  
  20.             canvas.drawCircle(mBorderRect.centerX(), mBorderRect.centerY(), mBorderRadius, mBorderPaint);  
  21. 相關推薦

    Android圓形圖片CircleImageView的使用分析

    在專案開發中,我們經常需要用到圓形圖片效果,典型案例是使用者頭像的顯示。如圖所示。下面我們使用開源控制元件CircleImageView來實現該效果。CircleImageView專案下載地址:https://github.com/hdodenhof/CircleImage

    Android圓形圖片控制元件CircleImageView的使用

    自定義CircleImageView繼承ImageView package com.zhoujian.circleimageview.view; import android.content.Context; import android.conten

    Android Systrace的使用分析

    Systrace的使用和分析 概述 Systrace是分析Android效能問題的神器,Google IO 2017上更是對其各種強推。Systrace其實和TraceView很像,都是統計一些方法(或者是一個執行階段)的耗時,然後在一個有時間軸的圖表上展示出來。不同的是

    圓形圖片CircleImageView(解決記憶體溢位)

    一、前言 專案已經做完了,目前測試那邊還沒有提交什麼bug,所以目前對程式碼進行重構和優化。有一個很頭疼的問題就是圓形影象引起GC記憶體溢位,logcat老列印:Grow heap (frag case) to 20.982MB for 1542416-byt

    Android平滑圖片載入快取庫 Glide 使用詳解

    一、簡介在泰國舉行的谷歌開發者論壇上,谷歌為我們介紹了一個名叫 Glide的圖片載入庫,作者是bumptech。這個庫被廣泛的運用在google的開源專案中,包括2014年google I/O大會上釋出的官方app。二、 使用dependencies {    compile

    android 圓形ImageView CircleImageView

    原文 package com.example.administrator.spchain; import android.content.Context; import android.content.res.TypedArray; import android.gr

    Android平滑圖片載入快取庫Glide使用詳解

    在圖片載入庫爛大街的今天,選擇一個適合自己使用的圖片載入庫已經成為了每一個Android開發者的必經之路。現在市面上知名的圖片載入庫有UIL,Picasso,Volley ImageLoader,Fresco以及我們今天的主角Glide。它們各有千秋,不能評定誰

    android圓形圖片裁剪demo以及實現

    Bitmap getBitmap() { try { // srcPic.getDrawingCache()獲取View截圖在某些情況下報錯了。 // 現在用一種新的獲取view中影象的方法取代getDrawingCache()方法. // 另:在使用createBi

    Android國際化-圖片國際化文字字元國際化

    en 英文en_US 英文 (美國)ar 阿拉伯文ar_AE阿拉伯文 (阿拉伯聯合大公國)ar_BH 阿拉伯文 (巴林)ar_DZ 阿拉伯文 (阿爾及利亞)ar_EG 阿拉伯文 (埃及)ar_IQ 阿拉伯文 (伊拉克)ar_JO 阿拉伯文 (約旦)ar_KW 阿拉伯文 (科威特)ar_LB 阿拉伯文 (黎

    Android圓形圖片不求人,自定義View實現(BitmapShader使用)

    在很多APP當中,圓形的圖片是必不可少的元素,美觀大方。本文將帶領讀者去實現一個圓形圖片自定View,力求只用一個Java類來完成這件事情。 一、先上效果圖 二、實現思路 在定義View 的onMeasure()方法裡設定View的寬高相等,應該取寬高中的最小值。

    Android 完美實現圖片圓角圓形 對實現進行分析

                    轉載請標明出處:http://blog.csdn.net/lmj623565791/article/details/24555655本來想在網上找個圓角的例子看一看,不盡人意啊,基本都是官方的Demo的那張原理圖,稍後會貼出。於是自己自定義了個View,實現圖片的圓角以及圓形效

    圓形圖片(或者給頭像加個描邊)CircleImageView的使用分析

    在專案開發中,我們經常需要用到圓形圖片效果,典型案例是使用者頭像的顯示。如圖所示。下面我們使用開源控制元件CircleImageView來實現該效果。CircleImageView專案下載地址:https://github.com/hdodenhof/CircleImageV

    Android 使用Glide動態載入圓形圖片圓角圖片

    Glide我們都不陌生了,有時我們需要把載入下來的圖片轉成圓角或者圓形的圖片,怎麼處理呢,Glide原生沒有這個方法,於是我拓展了BitmapTransformation來實現這個功能。 效果圖: Glide是預設本地儲存的,但重複載入的時候,是不需要重

    android 自己定義水平圓形progressbar 僅僅定義一些style就能夠

    mod type 動畫 encoding pop load degree fcm 就會 效果圖: 改動progressbar 讓他滿足自己的需求一般來說僅僅改動一下,progressbar的style就能夠滿足需求了: activity代碼:只顯

    android中畫圓形圖片的幾種辦法

    http hub image art 鋸齒 tar ets oid tex 在開發中常常會有一些需求,比方顯示頭像,顯示一些特殊的需求,將圖片顯示成圓角或者圓形或者其它的一些形狀。可是往往我們手上的圖片或者從server獲取到的圖片都是方形的。這時候就須要我們自

    unity優化《二》--Texture圖片空間記憶體佔用分析

    打包多種型別的專案,空專案和10張放在Resources資料夾中的圖為比較案例。以下是比較資料。 IPHONE: 1.空專案----空間佔用量42.3MB----IPA大小10MB 2.10張1200*520無壓縮Texure 單張圖佔用量2.8MB----空間佔用量70.2MB

    Android神話級圓形圖片控制元件RoundImageView

    原文地址:https://blog.csdn.net/u011192530/article/details/53836546   RoundImageView是在不修改ImageView原有繪圖邏輯的情況下實現的圓形特性,完全相容ImageView的所有特性。 無論你的影象控制元件

    Glide 圓形圖片圓角圖片的實現

    一、背景前言 在Android APP的設計中圓角和圓形圖片的設計是必須的,網上關於圓形和圓角圖片的實現方案也已經有很多,但是那都是人家的,因此在此總結一下,方便後續設計中的查閱,希望對需要幫助的你也有用。 二、方案的實現 2.1 方案一 使用RoundedBitmapDraw

    Android之測量APP效能-分析除錯 APK(二)

    分析和除錯預構建 APK Android Studio 3.0 允許您分析和除錯 APK,無需先從 Android Studio 專案構建這些 APK。 不過,您需要確保使用可除錯版本的 APK。 要開始除錯 APK,請在 Android Studio Welcome 歡迎螢幕中點選&nbs

    Android之Glide獲取圖片PathGlide獲取圖片Bitmap

    今天主要研究了Glide獲取圖片Path、Bitmap用法,相信也困擾了大家很久,我在網上也找了很久,基本沒有,後來研究了下,也參考了下api文件,總結了以下幾個方式: 獲取Bitmap: 1)在圖片下載快取好之後獲取 Glide.with(mContext).load