亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Android實(shí)現(xiàn)圓角矩形和圓形ImageView的方式

 更新時(shí)間:2022年05月19日 08:19:47   作者:huaxun66  
這篇文章主要為大家詳細(xì)介紹了Android中實(shí)現(xiàn)圓角矩形和圓形的方式,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

Android中實(shí)現(xiàn)圓角矩形和圓形有很多種方式,其中最常見(jiàn)的方法有ImageLoader設(shè)置Option和自定義View。

1.ImageLoader加載圖片

public static DisplayImageOptions getRoundOptions() {
 DisplayImageOptions options = new DisplayImageOptions.Builder()
 // 是否設(shè)置為圓角,弧度為多少,當(dāng)弧度為90時(shí)顯示的是一個(gè)圓
 .displayer(new RoundedBitmapDisplayer(30))
 .build();
 return options;
 }

ImageLoader.getInstance().displayImage(imageURL, imageView, Options.getRoundOptions());

2.自定義View實(shí)現(xiàn)

自定義View實(shí)現(xiàn)圓角矩形和圓形也有很多方法,其中最常見(jiàn)的就是利用Xfermode,Shader。本文就是使用BitmapShader實(shí)現(xiàn)圓角的繪制。

自定義CircleImageView
 •淺談BitmapShader
BitmapShader是Shader的子類(lèi),可以通過(guò)Paint.setShader(Shader shader)進(jìn)行設(shè)置,這里我們只關(guān)注BitmapShader,構(gòu)造方法:
mBitmapShader = new BitmapShader(bitmap,TileMode.CLAMP, TileMode.CLAMP);
參數(shù)1:bitmap
參數(shù)2,參數(shù)3:TileMode;
TileMode的取值有三種:
CLAMP 拉伸
REPEAT 重復(fù)
MIRROR 鏡像
 

重復(fù):就是橫向、縱向不斷重復(fù)這個(gè)bitmap
鏡像:橫向不斷翻轉(zhuǎn)重復(fù),縱向不斷翻轉(zhuǎn)重復(fù);
拉伸:重復(fù)圖片最后的那一個(gè)像素;橫向的最后一個(gè)橫行像素,不斷的重復(fù),縱項(xiàng)的那一列像素,不斷的重復(fù);
現(xiàn)在大概明白了,BitmapShader通過(guò)設(shè)置給mPaint,然后用這個(gè)mPaint繪圖時(shí),就會(huì)根據(jù)你設(shè)置的TileMode,對(duì)繪制區(qū)域進(jìn)行著色。
對(duì)于我們的圓角,以及圓形,我們?cè)O(shè)置的模式都是CLAMP,但是你會(huì)不會(huì)會(huì)有一個(gè)疑問(wèn):
view的寬或者高大于我們的bitmap寬或者高豈不是會(huì)拉伸?
嗯,我們會(huì)為BitmapShader設(shè)置一個(gè)matrix,去適當(dāng)?shù)姆糯蠡蛘呖s小圖片,不會(huì)讓“ view的寬或者高大于我們的bitmap寬或者高 ”此條件成立的。

 •自定義屬性 

<?xml version="1.0" encoding="utf-8"?>
<resources> 
 <declare-styleable name="CircleImageView">
 <attr name="type" format="enum">
 <enum name="circle" value="0"/>
 <enum name="round" value="1"/>
 </attr>
 <attr name="round_Radius" format="dimension" /> 
 <attr name="border_width" format="dimension" />
 <attr name="border_color" format="color" />
 </declare-styleable>
</resources>

 •獲取自定義屬性

public CircleImageView(Context context, AttributeSet attrs, int defStyle) {
 super(context, attrs, defStyle);

 TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CircleImageView, defStyle, 0);
 // 獲取類(lèi)型
 type = a.getInt(R.styleable.CircleImageView_type, TYPE_CIRCLE);
 // 獲取圓角半徑
 mRoundRadius = a.getDimensionPixelSize(R.styleable.CircleImageView_round_Radius, DEFAULT_ROUND_RADIUS);
 // 獲取邊界的寬度
 mBorderWidth = a.getDimensionPixelSize(R.styleable.CircleImageView_border_width, DEFAULT_BORDER_WIDTH);
 // 獲取邊緣的顏色
 mBorderColor = a.getColor(R.styleable.CircleImageView_border_color,DEFAULT_BORDER_COLOR);
 //調(diào)用 recycle() 回收TypedArray,以便后面重用
 a.recycle();

 init();
 }

•onMeasure

@Override 
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
 super.onMeasure(widthMeasureSpec, heightMeasureSpec); 
 /** 
 * 如果類(lèi)型是圓形,則強(qiáng)制改變view的寬高一致,以小值為準(zhǔn) 
 */ 
 if (type == TYPE_CIRCLE) { 
 mWidth = Math.min(getMeasuredWidth(), getMeasuredHeight()); 
 setMeasuredDimension(mWidth, mWidth); 
 }
 }

•設(shè)置初始化參數(shù)

/**
 * 作用就是保證第一次執(zhí)行setup函數(shù)里下面代碼要在構(gòu)造函數(shù)執(zhí)行完畢時(shí)調(diào)用 
 */
 private void init() {
 //在這里ScaleType被強(qiáng)制設(shè)定為CENTER_CROP,就是將圖片水平垂直居中,進(jìn)行縮放
 super.setScaleType(SCALE_TYPE);
 mReady = true;
 if (mSetupPending) {
 setup();
 mSetupPending = false;
 }
 }

 /**
 * 這個(gè)函數(shù)很關(guān)鍵,進(jìn)行圖片畫(huà)筆和邊界畫(huà)筆(Paint)一些重繪參數(shù)初始化:
 * 構(gòu)建渲染器BitmapShader用Bitmap來(lái)填充繪制區(qū)域,設(shè)置樣式以及內(nèi)外圓半徑計(jì)算等,以及調(diào)用updateShaderMatrix()函數(shù)和 invalidate()函數(shù);
 */
 private void setup() {
 //因?yàn)閙Ready默認(rèn)值為false,所以第一次進(jìn)這個(gè)函數(shù)的時(shí)候if語(yǔ)句為真進(jìn)入括號(hào)體內(nèi)
 //設(shè)置mSetupPending為true然后直接返回,后面的代碼并沒(méi)有執(zhí)行。
 if (!mReady) {
 mSetupPending = true;
 return;
 }
 //防止空指針異常
 if (mBitmap == null) {
 return;
 }
 // 構(gòu)建渲染器,用mBitmap來(lái)填充繪制區(qū)域 ,參數(shù)值代表如果圖片太小的話 就直接拉伸
 mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
 // 設(shè)置圖片畫(huà)筆反鋸齒
 mBitmapPaint.setAntiAlias(true);
 // 設(shè)置圖片畫(huà)筆渲染器
 mBitmapPaint.setShader(mBitmapShader);
 // 設(shè)置邊界畫(huà)筆樣式
 mBorderPaint.setStyle(Paint.Style.STROKE);
 mBorderPaint.setAntiAlias(true);
 mBorderPaint.setColor(mBorderColor);
 mBorderPaint.setStrokeWidth(mBorderWidth);
 //這個(gè)地方是取的原圖片的寬高
 mBitmapHeight = mBitmap.getHeight();
 mBitmapWidth = mBitmap.getWidth();
 //設(shè)置含邊界顯示區(qū)域,取的是CircleImageView的布局實(shí)際大小
 mBorderRect.set(0, 0, getWidth(), getHeight());
 //初始圖片顯示區(qū)域?yàn)閙BorderRect減去邊緣部分
 mDrawableRect.set(mBorderWidth, mBorderWidth, mBorderRect.width() - mBorderWidth, mBorderRect.height() - mBorderWidth);

 //下面計(jì)算的值都是為onDraw中畫(huà)圖做準(zhǔn)備
 if (type == TYPE_CIRCLE) {
 //計(jì)算 圓形帶邊界部分(外圓)的半徑,取mBorderRect的寬高減去一個(gè)邊緣大小的一半的較小值
 mBorderRadius = (mBorderRect.width() - mBorderWidth)/2;
 //這里計(jì)算的是內(nèi)圓的半徑,也即去除邊界寬度的半徑
 mDrawableRadius = mDrawableRect.width()/2;
 } else if (type == TYPE_ROUND) {
 //如果是圓角矩形,重新計(jì)算邊緣區(qū)域,使處于邊緣正中央
 mBorderRect.set(mBorderWidth/2, mBorderWidth/2, getWidth() - mBorderWidth/2, getHeight() - mBorderWidth/2);
 }

 //設(shè)置渲染器的變換矩陣也即是mBitmap用何種縮放形式填充
 updateShaderMatrix();
 //手動(dòng)觸發(fā)ondraw()函數(shù) 完成最終的繪制
 invalidate();
 }

•設(shè)置渲染器的變換矩陣

/**
 * 這個(gè)函數(shù)為設(shè)置BitmapShader的Matrix參數(shù),設(shè)置最小縮放比例,平移參數(shù)。
 * 作用:保證圖片損失度最小和始終繪制圖片正中央的那部分
 */
 private void updateShaderMatrix() {
 float scaleX = 1.0f;
 float scaleY = 1.0f;
 float scale = 1.0f;
 float dx = 0;
 float dy = 0;
 // 如果圖片的寬或者高與view的寬高不匹配,計(jì)算出需要縮放的比例;縮放后的圖片的寬高,一定要大于我們view的寬高;所以我們這里取大值
 if (type == TYPE_CIRCLE) {
 scaleX = mWidth * 1.0f / mBitmapWidth;
 scaleY = mWidth * 1.0f / mBitmapHeight;
 scale = Math.max(scaleX, scaleY);
 } else if (type == TYPE_ROUND) {
 scaleX = getWidth() * 1.0f / mBitmapWidth;
 scaleY = getHeight() * 1.0f / mBitmapHeight;
 scale = Math.max(scaleX, scaleY);
 } 
 if (scaleX > scaleY) {
 // x軸縮放 y軸平移 使得圖片的x軸方向的邊的尺寸縮放到圖片顯示區(qū)域(mDrawableRect)一樣)
 dy = (mDrawableRect.height() - mBitmapHeight * scale) * 0.5f;
 } else {
 // y軸縮放 x軸平移 使得圖片的y軸方向的邊的尺寸縮放到圖片顯示區(qū)域(mDrawableRect)一樣)
 dx = (mDrawableRect.width() - mBitmapWidth * scale) * 0.5f;
 }

 mShaderMatrix.set(null);
 //縮放
 mShaderMatrix.setScale(scale, scale);
 // 平移
 mShaderMatrix.postTranslate((int) (dx + 0.5f) + mBorderWidth, (int) (dy + 0.5f) + mBorderWidth);
 // 設(shè)置變換矩陣
 mBitmapShader.setLocalMatrix(mShaderMatrix);
 }

 •onDraw

@Override
 protected void onDraw(Canvas canvas) {
 //如果圖片不存在就不畫(huà)
 if (getDrawable() == null)
 return;

 if (type == TYPE_ROUND) {
 //繪制內(nèi)圓角矩形,參數(shù)矩形區(qū)域,圓角半徑,圖片畫(huà)筆為mBitmapPaint
 canvas.drawRoundRect(mDrawableRect, mRoundRadius, mRoundRadius, mBitmapPaint);
 if (mBorderWidth != 0) {
 //如果圓形邊緣的寬度不為0 我們還要繪制帶邊界的外圓角矩形 參數(shù)矩形區(qū)域,圓角半徑,邊界畫(huà)筆為mBorderPaint
 canvas.drawRoundRect(mBorderRect , mRoundRadius + mBorderWidth / 2, mRoundRadius + mBorderWidth / 2, mBorderPaint);
 }
 } else if (type == TYPE_CIRCLE) {
 //繪制內(nèi)圓形,參數(shù)圓心坐標(biāo),內(nèi)圓半徑,圖片畫(huà)筆為mBitmapPaint
 canvas.drawCircle(getWidth() / 2, getHeight() / 2, mDrawableRadius, mBitmapPaint);
 //如果圓形邊緣的寬度不為0 我們還要繪制帶邊界的外圓形 參數(shù)圓心坐標(biāo),外圓半徑,邊界畫(huà)筆為mBorderPaint
 if (mBorderWidth != 0) {
 canvas.drawCircle(getWidth() / 2, getHeight() / 2, mBorderRadius, mBorderPaint);
 } 
 } 
 }

而且,我們給自定義View添加了幾個(gè)接口,可以用來(lái)直接設(shè)置類(lèi)型、邊緣顏色、邊緣寬度和圖片信息等。

使用CircleImageView
布局文件:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 xmlns:attr="http://schemas.android.com/apk/res/com.hx.circleimageview"
 android:id="@+id/container"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:background="#CDCDC1"
 android:orientation="vertical" >

 <com.hx.circleimageview.CircleImageView
 android:id="@+id/image1"
 android:layout_width="150dp"
 android:layout_height="150dp"
 android:layout_margin="10dp"
 android:src="@drawable/crazy_1"
 attr:type="circle"
 attr:border_color="#FFffffff"
 attr:border_width="2dp" />

 <com.hx.circleimageview.CircleImageView
 android:id="@+id/image2"
 android:layout_width="150dp"
 android:layout_height="150dp"
 android:layout_margin="10dp"
 android:src="@drawable/crazy_2"
 attr:type="round"
 attr:border_width="2dp" />

 <com.hx.circleimageview.CircleImageView
 android:id="@+id/image3"
 android:layout_width="250dp"
 android:layout_height="150dp"
 android:layout_margin="10dp"
 android:src="@drawable/crazy_3"
 attr:type="round"
 attr:round_Radius="20dp"
 attr:border_color="#9400D3"
 attr:border_width="5dp" />
</LinearLayout>

我們?cè)贘AVA中對(duì)三個(gè)ImageView添加點(diǎn)擊事件

@Override
 public void onClick(View v) {
 switch (v.getId()) {
 case R.id.image1:
 image1.setBorderColor(Color.BLACK);
 break;
 case R.id.image2:
 image2.setImageResource(R.drawable.crazy_3);
 break;
 case R.id.image3:
 int type = image3.getType() == CircleImageView.TYPE_CIRCLE ? CircleImageView.TYPE_ROUND : CircleImageView.TYPE_CIRCLE;
 image3.setType(type);
 break;
 }

運(yùn)行后效果圖如下:

源碼下載:http://xiazai.jb51.net/201609/yuanma/Android-ImageView(jb51.net).rar

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

最新評(píng)論