先看下效果图

我们再来看一张CSDN的圆角图片

从布局能够看出csdn app 的头像也是圆角的Image,但能够看到。有明显的毛刺感。不知道是csdn 程序猿的疏忽还是 我手机的问题,本人手机(小米note)。

不知道其它的小伙伴显示效果也是这样。

好回到主题。事实上实现圆角Image的方式有非常多,今天所讲的是我觉得比較简单的一种。首先我们须要了解Xfermode属性,什么意思呢?看一张图你就明确了

这是Xfermode属性的几种模式和效果。简单说明一下

Src和Dst各自是一张矩形和原型图片。当我们设置不同的模式。显示的效果就如上图所看到的。关于Xfermode这里只是多阐述,免得把大家绕晕了,我们这里仅仅须要关注当中的SrcIn模式,能够看到这个模式取的是两张图片的交集部分。

这就好办了,我们通常拿到img图片都是矩形。我们能够利用canvas画一个圆。然后利用SrcIn属性,取img和圆的交集,那么圆角ImageView是不是就轻易实现了呢?

这里先理一下思路。1、自己定义两个属性来设置圆角的弧度。以及当前是否画纯圆。2、设置Xfermode属性为SrcIn 。

就这简单两步圆角ImageView就实现了,接下来直接上代码。


import wu.han.himan_library.R;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.ImageView; /**
*
* @author Mr.Himan
* @version 1.0<br>
* 2015年12月16日 09:28:25<br>
* 图片圆角实现
*
*/
public class CustomImageView extends ImageView {
private Paint paint;
private Paint paintBorder;
private Bitmap mSrcBitmap;
/**
* 圆角的弧度
*/
private float mRadius;
private boolean mIsCircle; public CustomImageView(final Context context) {
this(context, null);
} public CustomImageView(Context context, AttributeSet attrs) {
this(context, attrs, R.attr.customImageViewStyle);
} public CustomImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
TypedArray ta = context.obtainStyledAttributes(attrs,
R.styleable.CustomImageView, defStyle, 0);
mRadius = ta.getDimension(R.styleable.CustomImageView_radius, 0);
mIsCircle = ta.getBoolean(R.styleable.CustomImageView_circle, false);
int srcResource = attrs.getAttributeResourceValue(
"http://schemas.android.com/apk/res/android", "src", 0);
if (srcResource != 0)
mSrcBitmap = BitmapFactory.decodeResource(getResources(),
srcResource);
ta.recycle();
paint = new Paint();
paint.setAntiAlias(true);
paintBorder = new Paint();
paintBorder.setAntiAlias(true);
} @Override
public void onDraw(Canvas canvas) {
int width = canvas.getWidth() - getPaddingLeft() - getPaddingRight();
int height = canvas.getHeight() - getPaddingTop() - getPaddingBottom();
Bitmap image = drawableToBitmap(getDrawable());
if (mIsCircle) {
Bitmap reSizeImage = reSizeImageC(image, width, height);
canvas.drawBitmap(createCircleImage(reSizeImage, width, height),
getPaddingLeft(), getPaddingTop(), null); } else { Bitmap reSizeImage = reSizeImage(image, width, height);
canvas.drawBitmap(createRoundImage(reSizeImage, width, height),
getPaddingLeft(), getPaddingTop(), null);
}
} /**
* 画圆角
*
* @param source
* @param width
* @param height
* @return
*/
private Bitmap createRoundImage(Bitmap source, int width, int height) {
Paint paint = new Paint();
paint.setAntiAlias(true);
Bitmap target = Bitmap.createBitmap(width, height, Config.ARGB_8888);
Canvas canvas = new Canvas(target);
RectF rect = new RectF(0, 0, width, height);
canvas.drawRoundRect(rect, mRadius, mRadius, paint);
// 核心代码取两个图片的交集部分
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(source, 0, 0, paint);
return target;
} /**
* 画圆
*
* @param source
* @param width
* @param height
* @return
*/
private Bitmap createCircleImage(Bitmap source, int width, int height) { Paint paint = new Paint();
paint.setAntiAlias(true);
Bitmap target = Bitmap.createBitmap(width, height, Config.ARGB_8888);
Canvas canvas = new Canvas(target);
canvas.drawCircle(width / 2, height / 2, Math.min(width, height) / 2,
paint);
// 核心代码取两个图片的交集部分
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(source, (width - source.getWidth()) / 2,
(height - source.getHeight()) / 2, paint);
return target; } @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(width, height);
} /**
* drawable转bitmap
*
* @param drawable
* @return
*/
private Bitmap drawableToBitmap(Drawable drawable) {
if (drawable == null) {
if (mSrcBitmap != null) {
return mSrcBitmap;
} else {
return null;
}
} else if (drawable instanceof BitmapDrawable) {
return ((BitmapDrawable) drawable).getBitmap();
}
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
} /**
* 重设Bitmap的宽高
*
* @param bitmap
* @param newWidth
* @param newHeight
* @return
*/
private Bitmap reSizeImage(Bitmap bitmap, int newWidth, int newHeight) {
int width = bitmap.getWidth();
int height = bitmap.getHeight();
// 计算出缩放比
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
// 矩阵缩放bitmap
Matrix matrix = new Matrix(); matrix.postScale(scaleWidth, scaleHeight);
return Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
} /**
* 重设Bitmap的宽高
*
* @param bitmap
* @param newWidth
* @param newHeight
* @return
*/
private Bitmap reSizeImageC(Bitmap bitmap, int newWidth, int newHeight) {
int width = bitmap.getWidth();
int height = bitmap.getHeight();
int x = (newWidth - width) / 2;
int y = (newHeight - height) / 2;
if (x > 0 && y > 0) {
return Bitmap.createBitmap(bitmap, 0, 0, width, height, null, true);
} float scale = 1; if (width > height) {
// 依照宽度进行等比缩放
scale = ((float) newWidth) / width; } else {
// 依照高度进行等比缩放
// 计算出缩放比
scale = ((float) newHeight) / height;
}
Matrix matrix = new Matrix();
matrix.postScale(scale, scale);
return Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
}
}

attr.xml

<?xml version="1.0" encoding="utf-8"?

>
<resources> <declare-styleable name="Theme">
<attr name="customImageViewStyle" format="reference" />
</declare-styleable>
<!-- 自己定义圆角ImageView -->
<declare-styleable name="CustomImageView">
<attr name="circle" format="boolean" />
<attr name="radius" format="dimension" />
</declare-styleable> </resources>

到这里圆角ImageView就实现了。代码比較简单,相同的我们能够依据Xfermode设置不痛的模式。来实现不同的效果。

须要注意的是。在上面代码中我做了图片的压缩和缩放操作。当我们有时在载入网络图片的时候。图片宽高往往是不确定的。所以这里的压缩和缩放处理,须要大家依据自己的业务需求进行对应的修改

Android自己定义圆角ImageView 支持网络图片的更多相关文章

  1. Android自己定义圆角ImageView

    我们常常看到一些app中能够显示圆角图片.比方qq的联系人图标等等,实现圆角图片一种办法是直接使用圆角图片资源,当然假设没有圆角图片资源.我们也能够自己通过程序实现的,以下介绍一个自己定义圆角Imag ...

  2. Android 自己定义ImageView实现圆角/圆形 附加OnTouchListener具体凝视以及Button圆角

    转载请注明出处:王亟亟的大牛之路 平时要用一些非方方正正的button之类的小伙伴们是怎样实现的?RadioButton? ImageButton? 还是其它? 今天亟亟上的是ImageView来实现 ...

  3. Android使用ImageView显示网络图片

    本案例使用ImageView 简单的实现了网络图片的调用.当中注意事项.由于用到了网络,这里採用了HttpClient方法訪问网络联接,关于怎样使用,可參照文章 Android中使用HttpClien ...

  4. Android 自己定义UI圆角button

    Android实际开发中我们一般须要圆角的button,普通情况下我们能够让美工做出来对应的button图片.然后放上去就可以,另外我们能够在布局文件里直接设置,也能够达到一样的效果. 以下解说在布局 ...

  5. Android笔记之使用ImageView加载网络图片以及保存图片到本地并更新图库

    ImageView显示网络图片 findViewById(R.id.btnLoad).setOnClickListener(new View.OnClickListener() { @Override ...

  6. 自定义控件之 圆形 / 圆角 ImageView

    一.问题在哪里? 问题来源于app开发中一个很常见的场景——用户头像要展示成圆的:       二.怎么搞? 机智的我,第一想法就是,切一张中间圆形透明.四周与底色相同.尺寸与头像相同的蒙板图片,盖在 ...

  7. android 自己定义视频播放器之2/1

    非常久没更新博客,相信大家年后都比較忙. 今天给大家带来了一款视频播放器,首先确认的得有几点. 1.首先得有个播放视频的view. 2.加点额外功能进去左边上下滑动调节亮度,右边上下滑动调节声量: 3 ...

  8. Android可伸缩布局-FlexboxLayout(支持RecyclerView集成)

    Android可伸缩布局-FlexboxLayout(支持RecyclerView集成) 1 . 前言 前几天看到Google官方的博客介绍了Google开源的一个强大的布局-FlexboxLayou ...

  9. 【转】Android开发笔记——圆角和边框们

    原文地址:http://blog.xianqu.org/2012/04/android-borders-and-radius-corners/ Android开发笔记——圆角和边框们 在做Androi ...

随机推荐

  1. HDU 4976 A simple greedy problem. 贪心+DP

    题意: 给定n<=1000个小兵,A每次都能使小兵掉1点血,B每次能使所有小兵掉1点血,A.B轮流攻击,每次轮到A他会选择是否攻击,轮到B必须攻击.求A最多能杀死多少小兵.(当小兵血量为1时被攻 ...

  2. 安装虚拟机(VM)(一)

    原创作品,允许转载,转载时请务必声明作者信息和本声明.  https://www.cnblogs.com/zhu520/p/10728248.html 本人小白,有错指出.谢谢! 一:安装虚拟机前奏 ...

  3. ubuntu中开启、关闭防火墙

    1.关闭ubuntu的防火墙        ufw disable 开启防火墙 ufw enable 2.卸载了iptables        apt-get remove iptables 3.关闭 ...

  4. WebKit载入流程 - 概述

    之前写了几篇载入流程的说明,是从下向上看,有点仅仅见树木不见森林的感觉.经过近期一段时间的学习,有了能加以概括抽象的方法. WebKit载入流程和页面组成是直接相关的,页面就是WebKit要载入的对象 ...

  5. 简单记录一次REDO文件损坏报错 ORA-00333重做日志读取块出错

    一.故障描写叙述 首先是实例恢复须要用到的REDO文件损坏 二.解决方法 1.对于非当前REDO或者当前REDO可是无活动事务使用下面CLEAR命令: 用CLEAR命令重建该日志文件SQL>al ...

  6. NYOJ 541 最强的战斗力

    最强DE 战斗力 时间限制:1000 ms  |  内存限制:65535 KB 难度: 描写叙述 春秋战国时期,赵国地大物博,资源很丰富.人民安居乐业.但很多国家对它虎视眈眈.准备联合起来对赵国发起一 ...

  7. BZOJ1306: [CQOI2009]match循环赛

    [传送门:BZOJ1306] 简要题意: 有n个队伍,每个队伍都要和其他队伍比一场,赢了的队得3分,输了的队不得分,打平两队各得一分,给出每个队伍的得分,求出对战方案数 题解: DFS暴搜!!一眼就觉 ...

  8. Linux常用的安全工具

    Linux常用的安全工具 "工欲善其事,必先利其器".作为一个合格的系统管理员,要应对可能发生的安全事件,掌握Linux下各种必须的安全工具是首要大事.本文主要介绍Linux上常用 ...

  9. useradd

    功能说明:useradd命令可用于创建新的用户或者更改用户的信息. 语法格式:useradd [选项] [用户名]useradd -D [选项] 选项说明:1.使用useradd常规添加用户工作原理流 ...

  10. 127.0.0.1和localhost和本机IP三者的区别!

    1, 先来说下回送地址(Loopback Address): 回送地址是主机用于向自身发送通信的一个特殊地址(也就是一个特殊的目的地址).可以这么说:同一台主机上的两项服务若使用回送地址而非分配的主机 ...