Android基于Fresco實(shí)現(xiàn)圓角和圓形圖片
Fresco是FaceBook開(kāi)源的Android平臺(tái)圖片加載庫(kù),可以從網(wǎng)絡(luò),從本地文件系統(tǒng),本地資源加載圖片
Fresco本身已經(jīng)實(shí)現(xiàn)了圓角以及圓形圖片的功能。
<!--圓形圖片,一般用作頭像--> <com.facebook.drawee.view.SimpleDraweeView ? ? android:id="@+id/iv_avatar" ? ? android:layout_width="40dp" ? ? android:layout_height="40dp" ? ? app:placeholderImage="@drawable/ic_avatar_default" ? ? app:roundAsCircle="true"/>
<!--圓角圖片,為了美觀(guān)大多數(shù)圖片都會(huì)有這樣的處理。--> <!--當(dāng)圖片為正方形的時(shí)候,將roundedCornerRadius設(shè)置為邊長(zhǎng)的一半,也可以形成圓形圖片的效果--> <com.facebook.drawee.view.SimpleDraweeView ? ? android:id="@+id/iv_avatar" ? ? android:layout_width="40dp" ? ? android:layout_height="40dp" ? ? app:placeholderImage="@drawable/ic_avatar_default" ? ? app:roundedCornerRadius="5dp"/>
工作中,遇到圓形頭像的時(shí)候,UI通常會(huì)給我們這樣一張圖作為默認(rèn)圖片

理論上來(lái)講,只需要加入下列這行代碼,就可以完成這部分工作了
app:placeholderImage="@drawable/ic_avatar_default"
然而圓形圖片本身已經(jīng)是圓形的了,在有些機(jī)型上就出現(xiàn)了這個(gè)樣式。

搜索了一波,自帶的屬性都不能解決這個(gè)問(wèn)題,干脆自己來(lái)定義這個(gè)圓形的實(shí)現(xiàn)吧,同時(shí)Fresco自帶的圓角效果只能保證使用統(tǒng)一的半徑,想要讓四個(gè)圓角的半徑不同,只能在java文件中設(shè)置,不夠靈活,定義圓角半徑的屬性也需要做些變更。
思路:自定義RoundImageView繼承自 SimpleDraweeVie,具備其所有的功能。
Canvas的clipPath(Path path)可以根據(jù)Path,將Canvas剪裁成我們想要的圖形。
public class RoundImageView extends SimpleDraweeView {
? ??
? ? private final static int DEFAULT_VALUE = 0;
? ? private float mWidth;
? ? private float mHeight;
? ? private Path mPath;
? ? // 圓角角度
? ? private float mCornerRadius;
? ? // 左上角圓角角度
? ? private float mLeftTopRadius;
? ? // 右上角圓角角度
? ? private float mRightTopRadius;
? ? // 右下角圓角角度
? ? private float mRightBottomRadius;
? ? // 左下角圓角角度
? ? private float mLeftBottomRadius;
? ? // 是否使用圓形圖片
? ? private boolean mAsCircle;
? ? // 圓形圖片半徑
? ? private float mRadius;
? ??
? ? public RoundImageView(Context context) {
? ? ? ? this(context, null);
? ? }
? ? public RoundImageView(Context context, AttributeSet attrs) {
? ? ? ? this(context, attrs, 0);
? ? }
? ? public RoundImageView(Context context, AttributeSet attrs, int defStyleAttr) {
? ? ? ? super(context, attrs, defStyleAttr);
? ? ? ? initData();
? ? ? ? initAttrs(context, attrs);
? ? }
? ??
? ? private void initData() {
? ? ? ? mPath = new Path();
? ? }
? ? private void initAttrs(Context context, AttributeSet attrs) {
? ? ? ? TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RoundImageView);
? ? ? ? mCornerRadius = typedArray.getDimension(R.styleable.RoundImageView_cornerRadius, DEFAULT_VALUE);
? ? ? ? mAsCircle = typedArray.getBoolean(R.styleable.RoundImageView_asCircle, false);
? ? ? ? if (mCornerRadius <= 0) {
? ? ? ? ? ? // 說(shuō)明用戶(hù)沒(méi)有設(shè)置四個(gè)圓角的有效值,此時(shí)四個(gè)圓角各自使用自己的值
? ? ? ? ? ? mLeftTopRadius = typedArray.getDimension(R.styleable.RoundImageView_leftTopRadius, DEFAULT_VALUE);
? ? ? ? ? ? mRightTopRadius = typedArray.getDimension(R.styleable.RoundImageView_rightTopRadius, DEFAULT_VALUE);
? ? ? ? ? ? mRightBottomRadius = typedArray.getDimension(R.styleable.RoundImageView_rightBottomRadius, DEFAULT_VALUE);
? ? ? ? ? ? mLeftBottomRadius = typedArray.getDimension(R.styleable.RoundImageView_leftBottomRadius, DEFAULT_VALUE);
? ? ? ? } else {
? ? ? ? ? ? // 使用了統(tǒng)一的圓角,因此使用mCornerRadius統(tǒng)一的值
? ? ? ? ? ? mLeftTopRadius = mCornerRadius;
? ? ? ? ? ? mRightTopRadius = mCornerRadius;
? ? ? ? ? ? mRightBottomRadius = mCornerRadius;
? ? ? ? ? ? mLeftBottomRadius = mCornerRadius;
? ? ? ? }
? ? ? ??
? ? ? ? typedArray.recycle();
? ? }
? ? @Override
? ? protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
? ? ? ? super.onLayout(changed, left, top, right, bottom);
? ? ? ? mWidth = getWidth();
? ? ? ? mHeight = getHeight();
? ? ? ? // 如果開(kāi)啟了圓形標(biāo)記
? ? ? ? if (mAsCircle) {
? ? ? ? ? ? mRadius = Math.min(mWidth / 2, mHeight / 2);
? ? ? ? }
? ? }
? ? @Override
? ? protected void onDraw(Canvas canvas) {
? ? ? ? // 如果開(kāi)啟了圓形標(biāo)記,圓形圖片的優(yōu)先級(jí)高于圓角圖片
? ? ? ? if(mAsCircle) {
? ? ? ? ? ? drawCircleImage(canvas);
? ? ? ? } else {
? ? ? ? ? ? drawCornerImage(canvas);
? ? ? ? }
? ? ? ? super.onDraw(canvas);
? ? }
? ? /**
? ? ?* 畫(huà)中間圓形
? ? ?* @param canvas
? ? ?*/
? ? private void drawCircleImage(Canvas canvas) {
? ? ? ? mPath.addCircle(mWidth / 2, mHeight / 2, mRadius, Path.Direction.CW);
? ? ? ? canvas.clipPath(mPath);
? ? }
? ? /**
? ? ?* 畫(huà)圓角
? ? ?* @param canvas
? ? ?*/
? ? private void drawCornerImage(Canvas canvas) {
? ? ? ? if (mWidth > mCornerRadius && mHeight > mCornerRadius) {
? ? ? ? ? ? // 設(shè)置四個(gè)角的x,y半徑值
? ? ? ? ? ? float[] radius = {mLeftTopRadius, mLeftTopRadius, mRightTopRadius, mRightTopRadius, mRightBottomRadius, mRightBottomRadius, mLeftBottomRadius, mLeftBottomRadius};
? ? ? ? ? ? mPath.addRoundRect(new RectF(0,0, mWidth, mHeight), radius, Path.Direction.CW);
? ? ? ? ? ? canvas.clipPath(mPath);
? ? ? ? }
? ? }
}attr屬性如下
<!--適配android10的圖片控件--> ? ? <declare-styleable name="RoundImageView"> ? ? ? ? <!--圓形圖片--> ? ? ? ? <attr name="asCircle" format="boolean"/> ? ? ? ? <!--左上角圓角半徑--> ? ? ? ? <attr name="leftTopRadius" format="dimension"/> ? ? ? ? <!--右上角圓角半徑--> ? ? ? ? <attr name="rightTopRadius" format="dimension"/> ? ? ? ? <!--右下角圓角半徑--> ? ? ? ? <attr name="rightBottomRadius" format="dimension"/> ? ? ? ? <!--左下角圓角半徑--> ? ? ? ? <attr name="leftBottomRadius" format="dimension"/> ? ? ? ? <!--四個(gè)圓角半徑,會(huì)覆蓋上邊四個(gè)圓角值--> ? ? ? ? <attr name="cornerRadius" format="dimension"/> </declare-styleable>
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android實(shí)現(xiàn)圓形圖片或者圓角圖片
- Android將Glide動(dòng)態(tài)加載不同大小的圖片切圓角與圓形的方法
- Android開(kāi)發(fā)使用Drawable繪制圓角與圓形圖案功能示例
- Android自定義Drawable實(shí)現(xiàn)圓形和圓角
- Android中Glide加載圓形圖片和圓角圖片實(shí)例代碼
- Android自定義控件之圓形、圓角ImageView
- Android實(shí)現(xiàn)圓角矩形和圓形ImageView的方式
- Android自定義view實(shí)現(xiàn)圓形、圓角和橢圓圖片(BitmapShader圖形渲染)
- Android自定義控件之圓形/圓角的實(shí)現(xiàn)代碼
- android 實(shí)現(xiàn)圓角圖片解決方案
相關(guān)文章
android使用PopupWindow實(shí)現(xiàn)頁(yè)面點(diǎn)擊頂部彈出下拉菜單
這篇文章主要給大家介紹android使用PopupWindow實(shí)現(xiàn)頁(yè)面點(diǎn)擊頂部彈出下拉菜單,實(shí)現(xiàn)此功能主要通過(guò)PopupWindow方法,代碼也很簡(jiǎn)單,需要的朋友可以參考下2015-08-08
Android 使用AsyncTask實(shí)現(xiàn)多線(xiàn)程斷點(diǎn)續(xù)傳
本文將詳細(xì)講解如何使用AsyncTask來(lái)實(shí)現(xiàn)多線(xiàn)程的斷點(diǎn)續(xù)傳下載功能,感興趣的朋友跟隨腳本之家小編一起學(xué)習(xí)吧2018-05-05
Android 開(kāi)發(fā)系統(tǒng)自帶語(yǔ)音模塊應(yīng)用
本篇文章 主要介紹 Android 開(kāi)發(fā)自帶語(yǔ)音模塊實(shí)例,在開(kāi)發(fā)Android系統(tǒng)中會(huì)用到系統(tǒng)語(yǔ)音搜索模塊,這里給大家一個(gè)參考實(shí)例2016-07-07
Android提高之MediaPlayer播放網(wǎng)絡(luò)視頻的實(shí)現(xiàn)方法
這篇文章主要介紹了Android的MediaPlayer播放網(wǎng)絡(luò)視頻的實(shí)現(xiàn)方法,是一個(gè)非常實(shí)用的功能,需要的朋友可以參考下2014-08-08
android自定義view用path畫(huà)長(zhǎng)方形
這篇文章主要為大家詳細(xì)介紹了android自定義view用path畫(huà)長(zhǎng)方形,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-04-04
關(guān)于Android Fragment對(duì)回退棧的詳細(xì)理解
這篇文章主要介紹了Android Fragment的回退棧示例詳細(xì)介紹的相關(guān)資料,在Android中Fragment回退棧是由Activity管理的,每個(gè)Activity都有自己的回退棧,其中保存了已經(jīng)停止(處于后臺(tái))的Fragment實(shí)例,需要的朋友可以參考下2016-12-12
Android sqlite cursor的遍歷實(shí)例詳解
在本篇內(nèi)容里小編給大家整理的是一篇關(guān)于Android sqlite cursor的遍歷的相關(guān)實(shí)例及知識(shí)點(diǎn),需要的朋友們可以學(xué)習(xí)下。2021-06-06

