Android中实现圆角矩形和圆形有很多种方式,其中最常见的方法有ImageLoader设置Option和自定义View。

1.ImageLoader加载图片

public static DisplayImageOptions getRoundOptions() {

DisplayImageOptions options = new DisplayImageOptions.Builder()

// 是否设置为圆角,弧度为多少,当弧度为90时显示的是一个圆

.displayer(new RoundedBitmapDisplayer(30))

.build();

return options;

}

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

2.自定义View实现自定义View实现圆角矩形和圆形也有很多方法,其中最常见的就是利用Xfermode,Shader。本文就是使用BitmapShader实现圆角的绘制。

自定义CircleImageView

•浅谈BitmapShaderBitmapShader是Shader的子类,可以通过Paint.setShader(Shader shader)进行设置,这里我们只关注BitmapShader,构造方法:

mBitmapShader = new BitmapShader(bitmap,TileMode.CLAMP, TileMode.CLAMP);

参数1:bitmap

参数2,参数3:TileMode;

TileMode的取值有三种:

CLAMP 拉伸

REPEAT 重复

MIRROR 镜像

重复:就是横向、纵向不断重复这个bitmap

镜像:横向不断翻转重复,纵向不断翻转重复;

拉伸:重复图片最后的那一个像素;横向的最后一个横行像素,不断的重复,纵项的那一列像素,不断的重复;

现在大概明白了,BitmapShader通过设置给mPaint,然后用这个mPaint绘图时,就会根据你设置的TileMode,对绘制区域进行着色。

对于我们的圆角,以及圆形,我们设置的模式都是CLAMP,但是你会不会会有一个疑问:

view的宽或者高大于我们的bitmap宽或者高岂不是会拉伸?

嗯,我们会为BitmapShader设置一个matrix,去适当的放大或者缩小图片,不会让“ view的宽或者高大于我们的bitmap宽或者高 ”此条件成立的。

•自定义属性

•获取自定义属性

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

super(context, attrs, defStyle);

TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CircleImageView, defStyle, 0);

// 获取类型

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);

//调用 recycle() 回收TypedArray,以便后面重用

a.recycle();

init();

}

•onMeasure

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

/**

* 如果类型是圆形,则强制改变view的宽高一致,以小值为准

*/

if (type == TYPE_CIRCLE) {

mWidth = Math.min(getMeasuredWidth(), getMeasuredHeight());

setMeasuredDimension(mWidth, mWidth);

}

}

•设置初始化参数

/**

* 作用就是保证第一次执行setup函数里下面代码要在构造函数执行完毕时调用

*/

private void init() {

//在这里ScaleType被强制设定为CENTER_CROP,就是将图片水平垂直居中,进行缩放

super.setScaleType(SCALE_TYPE);

mReady = true;

if (mSetupPending) {

setup();

mSetupPending = false;

}

}

/**

* 这个函数很关键,进行图片画笔和边界画笔(Paint)一些重绘参数初始化:

* 构建渲染器BitmapShader用Bitmap来填充绘制区域,设置样式以及内外圆半径计算等,以及调用updateShaderMatrix()函数和 invalidate()函数;

*/

private void setup() {

//因为mReady默认值为false,所以第一次进这个函数的时候if语句为真进入括号体内

//设置mSetupPending为true然后直接返回,后面的代码并没有执行。

if (!mReady) {

mSetupPending = true;

return;

}

//防止空指针异常

if (mBitmap == null) {

return;

}

// 构建渲染器,用mBitmap来填充绘制区域 ,参数值代表如果图片太小的话 就直接拉伸

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();

//设置含边界显示区域,取的是CircleImageView的布局实际大小

mBorderRect.set(0, 0, getWidth(), getHeight());

//初始图片显示区域为mBorderRect减去边缘部分

mDrawableRect.set(mBorderWidth, mBorderWidth, mBorderRect.width() - mBorderWidth, mBorderRect.height() - mBorderWidth);

//下面计算的值都是为onDraw中画图做准备

if (type == TYPE_CIRCLE) {

//计算 圆形带边界部分(外圆)的半径,取mBorderRect的宽高减去一个边缘大小的一半的较小值

mBorderRadius = (mBorderRect.width() - mBorderWidth)/2;

//这里计算的是内圆的半径,也即去除边界宽度的半径

mDrawableRadius = mDrawableRect.width()/2;

} else if (type == TYPE_ROUND) {

//如果是圆角矩形,重新计算边缘区域,使处于边缘正中央

mBorderRect.set(mBorderWidth/2, mBorderWidth/2, getWidth() - mBorderWidth/2, getHeight() - mBorderWidth/2);

}

//设置渲染器的变换矩阵也即是mBitmap用何种缩放形式填充

updateShaderMatrix();

//手动触发ondraw()函数 完成最终的绘制

invalidate();

}

•设置渲染器的变换矩阵

/**

* 这个函数为设置BitmapShader的Matrix参数,设置最小缩放比例,平移参数。

* 作用:保证图片损失度最小和始终绘制图片正中央的那部分

*/

private void updateShaderMatrix() {

float scaleX = 1.0f;

float scaleY = 1.0f;

float scale = 1.0f;

float dx = 0;

float dy = 0;

// 如果图片的宽或者高与view的宽高不匹配,计算出需要缩放的比例;缩放后的图片的宽高,一定要大于我们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轴方向的边的尺寸缩放到图片显示区域(mDrawableRect)一样)

dy = (mDrawableRect.height() - mBitmapHeight * scale) * 0.5f;

} else {

// y轴缩放 x轴平移 使得图片的y轴方向的边的尺寸缩放到图片显示区域(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);

// 设置变换矩阵

mBitmapShader.setLocalMatrix(mShaderMatrix);

}

•onDraw

@Override

protected void onDraw(Canvas canvas) {

//如果图片不存在就不画

if (getDrawable() == null)

return;

if (type == TYPE_ROUND) {

//绘制内圆角矩形,参数矩形区域,圆角半径,图片画笔为mBitmapPaint

canvas.drawRoundRect(mDrawableRect, mRoundRadius, mRoundRadius, mBitmapPaint);

if (mBorderWidth != 0) {

//如果圆形边缘的宽度不为0 我们还要绘制带边界的外圆角矩形 参数矩形区域,圆角半径,边界画笔为mBorderPaint

canvas.drawRoundRect(mBorderRect , mRoundRadius + mBorderWidth / 2, mRoundRadius + mBorderWidth / 2, mBorderPaint);

}

} else if (type == TYPE_CIRCLE) {

//绘制内圆形,参数圆心坐标,内圆半径,图片画笔为mBitmapPaint

canvas.drawCircle(getWidth() / 2, getHeight() / 2, mDrawableRadius, mBitmapPaint);

//如果圆形边缘的宽度不为0 我们还要绘制带边界的外圆形 参数圆心坐标,外圆半径,边界画笔为mBorderPaint

if (mBorderWidth != 0) {

canvas.drawCircle(getWidth() / 2, getHeight() / 2, mBorderRadius, mBorderPaint);

}

}

}

而且,我们给自定义View添加了几个接口,可以用来直接设置类型、边缘颜色、边缘宽度和图片信息等。

使用CircleImageView布局文件:

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" >

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" />

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" />

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" />

我们在JAVA中对三个ImageView添加点击事件

@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;

}

运行后效果图如下:

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

Android圆形imageview布局,Android实现圆角矩形和圆形ImageView的方式相关推荐

  1. Android 遥控器按键 布局,Android 类遥控器圆形控件 扇形按钮 带中间按钮

    Android 类遥控器圆形控件 扇形按钮 带中间按钮 前言 效果图 使用方法 添加依赖 在布局中使用 参数设定 设定是否有中间按钮 设定正常情况下的中间按钮的背景颜色 设定中间按钮的圆圈描边颜色 设 ...

  2. MYSQL圆角矩形表示_android 利用Bitmap获取圆角矩形、圆形图片

    1.在很多时候,我们要显示图片资源,需要将他的资源显示为圆角的:示例源码如下: public static Bitmap getRoundedCornerBitmap(Bitmap bitmap,fl ...

  3. 自定义圆角矩形图片/圆形图片

    图片的圆形/圆角矩形的处理方式有很多,网上也有很多例子,最近项目比较清闲,就试着自己写了一个通用的图片处理,可以根据参数的不同自动生成原型图片或者圆角矩形图片的自定义view大致的效果如下图,两个vi ...

  4. android dialog 自定义布局,Android自定义Dialog实现加载对话框效果

    前言 最近开发中用到许多对话框,之前都是在外面的代码中创建AlertDialog并设置自定义布局实现常见的对话框,诸如更新提示等含有取消和删除两个按钮的对话框我们可以通过代码创建一个AlertDial ...

  5. android win8风格布局,Android仿Win8界面开发

    本文将要模仿Win8界面的一个设计,一个一个的方块.方法很简单.这里自己把图片改改就可以成为自己想要的界面了. 1.首先来看看自定义的MyImageView: package com.example. ...

  6. android 图片文字布局,Android自定义控件图片+文字布局

    本来想用Tabrow来布局一组上面是图片下面是文字说明的控件,可是发现Tabrow不像想象的那样简易,并且这几组之间的控件距离很差把握,在网上找了两种方法以供参照.html 方法1.利用RadioBu ...

  7. android线程改变布局,Android线程中设置控件的值提示报错的解决方法

    本文实例讲述了Android线程中设置控件的值提示报错的解决方法.分享给大家供大家参考,具体如下: 在Android线程中设置控件的值一般会与Handler联合使用,如下: package com.y ...

  8. android旋转缩放布局,Android学习笔记(一):双指缩放及旋转计算

    请尊重原创,转载请注明来源. Android中,很多时候会用到手势判断,判断用户当前的手势是移动,还是双指缩放/旋转,关于Android中的手势和gesturedetector,已经有很多人进行过研究 ...

  9. android 多行布局,android布局-网格布局

    网格布局 自android4.0版本后新增的GridLayout网格布局的一些基本内容 GridLayout布局使用虚细线将布局划分为行,列和单元格,也支持一个控件在行,列上都有交错排列 GridLa ...

最新文章

  1. 8种方案解决重复提交问题
  2. FPGA的历史、现状和未来
  3. O(n)线性构造后缀树详解(一)
  4. 【CV】一文讲懂图像处理中的低通、高通、带阻和带通滤波器
  5. Axios——Axios封装DEMO
  6. Windows 网卡配置多VLAN
  7. 简洁!get请求和post请求的区别——Web网络系列学习笔记
  8. mysql 常用命令与备份恢复 整理
  9. CContextMenuManager上下文菜单管理器以及为菜单添加图标
  10. CSS垂直居中的方法
  11. 邮件服务器IMail教程(2)
  12. 西门子PLC程序下载方法简介
  13. 车道线检测数据集介绍
  14. 【IT职场】任正非十大特质
  15. 【arc093f】Dark Horse(容斥原理,动态规划,状态压缩)
  16. hive练习题(二)计算用户的复购率和回购率
  17. 一个matlab可视化的结果
  18. 项目绩效分析方法-挣值技术
  19. php 读取excel 数字,php如何读取excel中的数据
  20. SQL Server 2005 Management Studio Express部分中文部分英文

热门文章

  1. Discovery直播 | 3D“模”术师,还原立体世界——探秘3D建模服务
  2. 拖动水滴给土地浇水(CocosCreator)
  3. CF1474C Array Destruction
  4. android程序员的座右铭,作为一名程序员,你最喜欢的座右铭是什么?
  5. AS3,MXML,Flex,Flex Builder,Flash Builder,Flash,AIR,Flash Player之关系
  6. 盗贼之海自定义服务器,《盗贼之海》计划新增自定义服务器,远离恶性PVP
  7. 数据库课程设计--人事管理系统代码
  8. Qt之QImage无法获取图片尺寸(宽和高)
  9. 恢复Windows10系统禁用驱动程序强制签名的方法
  10. 单字ocr-cnn效果实现与测试