位置: 编程技术 - 正文

Android 圆形/圆角图片的方法(安卓圆角矩形图标)

编辑:rootadmin

推荐整理分享Android 圆形/圆角图片的方法(安卓圆角矩形图标),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:android设置圆角布局,android 圆角imageview,androiddialog圆角,androiddialog圆角,androiddialog圆角,android圆角图片,androiddialog圆角,androiddialog圆角,内容如对您有帮助,希望把文章链接给更多的朋友!

Android 圆形/圆角图片的方法

目前网上有很多圆角图片的实例,Github上也有一些成熟的项目。之前做项目,为了稳定高效都是选用Github上的项目直接用。但这种结束也是Android开发必备技能 ,所以今天就来简单研究一下该技术,分享给大家。

预备知识:

Xfermode介绍:

下面是Android ApiDemo里的“Xfermodes”实例,效果图。

Xfermode有三个子类,结构如下:

view sourceprint?1.publicclass2.Xfermode3.extendsObject4.java.lang.Object5.? android.graphics.Xfermode6.Known Direct Subclasses7.AvoidXfermode, PixelXorXfermode, PorterDuffXfermode

AvoidXfermode 指定了一个颜色和容差,强制Paint避免在它上面绘图(或者只在它上面绘图)。

PixelXorXfermode 当覆盖已有的颜色时,应用一个简单的像素异或操作。

PorterDuffXfermode 这是一个非常强大的转换模式,使用它,可以使用图像合成的条Porter-Duff规则的任意一条来控制Paint如何与已有的Canvas图像进行交互。

上面图片种显示的种模式介绍如下:

1.PorterDuff.Mode.CLEAR

所绘制不会提交到画布上。2.PorterDuff.Mode.SRC

显示上层绘制图片3.PorterDuff.Mode.DST

显示下层绘制图片4.PorterDuff.Mode.SRC_OVER

正常绘制显示,上下层绘制叠盖。5.PorterDuff.Mode.DST_OVER

上下层都显示。下层居上显示。6.PorterDuff.Mode.SRC_IN

取两层绘制交集。显示上层。7.PorterDuff.Mode.DST_IN

取两层绘制交集。显示下层。8.PorterDuff.Mode.SRC_OUT

取上层绘制非交集部分。9.PorterDuff.Mode.DST_OUT

取下层绘制非交集部分。.PorterDuff.Mode.SRC_ATOP

取下层非交集部分与上层交集部分.PorterDuff.Mode.DST_ATOP

取上层非交集部分与下层交集部分.PorterDuff.Mode.XOR

异或:去除两图层交集部分.PorterDuff.Mode.DARKEN

Android 圆形/圆角图片的方法(安卓圆角矩形图标)

取两图层全部区域,交集部分颜色加深.PorterDuff.Mode.LIGHTEN

取两图层全部,点亮交集部分颜色.PorterDuff.Mode.MULTIPLY

取两图层交集部分叠加后颜色.PorterDuff.Mode.SCREEN

取两图层全部区域,交集部分变为透明色

了解了上面的知识点后,我们根据上面的知识点先来实现第一种圆角图片制作方式:

原图:

先看这一段代码

view sourceprint?.privateImageView mImg;. .@Override.protectedvoid onCreate(Bundle savedInstanceState) {.super.onCreate(savedInstanceState);.setContentView(R.layout.activity_main);.mImg = (ImageView) findViewById(R.id.img);. .//获得imageview中设置的图片.BitmapDrawable drawable = (BitmapDrawable) mImg.getDrawable();.Bitmap bmp = drawable.getBitmap();.//获得图片的宽,并创建结果bitmap.intwidth = bmp.getWidth();.Bitmap resultBmp = Bitmap.createBitmap(width, width,.Bitmap.Config.ARGB_);.Paint paint =new Paint();.Canvas canvas =new Canvas(resultBmp);.//画圆.canvas.drawCircle(width /2, width / 2, width /2, paint);.paint.setXfermode(newPorterDuffXfermode(PorterDuff.Mode.SRC_IN));// 选择交集去上层图片.canvas.drawBitmap(bmp,0, 0, paint);.mImg.setImageBitmap(resultBmp);.bmp.recycle();. .}通过运行上面的代码,我们得出的结果如下:

大家看到这是我们需要的结果。可是这样做可能导致OutOfMomery异常。假如图片很大或者你可能并非通过ImageView的getDrawable获得图像,而是直接Decode一张很大的图片加载到内存,你会发现可能会出现异常。我们做一下改变。

view sourceprint?.privatestatic final String TAG = "RoundImage";.privateImageView mImg;. .@Override.protectedvoid onCreate(Bundle savedInstanceState) {.super.onCreate(savedInstanceState);.setContentView(R.layout.activity_main);.mImg = (ImageView) findViewById(R.id.img);.// 裁剪图片.BitmapFactory.Options options =new BitmapFactory.Options();.options.inJustDecodeBounds =true;.BitmapFactory..decodeResource(getResources(), R.drawable.avatar, options);.Log.d(TAG,"original outwidth: " &#; options.outWidth);.// 此宽度是目标ImageView希望的大小,你可以自定义ImageView,然后获得ImageView的宽度。.intdstWidth = ;.// 我们需要加载的图片可能很大,我们先对原有的图片进行裁剪.intsampleSize = calculateInSampleSize(options, dstWidth, dstWidth);.options.inSampleSize = sampleSize;.options.inJustDecodeBounds =false;.Log.d(TAG,"sample size: " &#; sampleSize);.Bitmap bmp = BitmapFactory.decodeResource(getResources(),.R.drawable.avatar, options);. .// 绘制图片.Bitmap resultBmp = Bitmap.createBitmap(dstWidth, dstWidth,.Bitmap.Config.ARGB_);.Paint paint =new Paint();.paint.setAntiAlias(true);.Canvas canvas =new Canvas(resultBmp);.// 画圆.canvas.drawCircle(dstWidth /2, dstWidth / 2, dstWidth /2, paint);.// 选择交集去上层图片.paint.setXfermode(newPorterDuffXfermode(PorterDuff.Mode.SRC_IN));.canvas.drawBitmap(bmp,new Rect(0,0, bmp.getWidth(), bmp.getWidth()),.newRect(0,0, dstWidth, dstWidth), paint);.mImg.setImageBitmap(resultBmp);.bmp.recycle();.}. .privateint calculateInSampleSize(BitmapFactory.Options options,.intreqWidth, int reqHeight) {.// Raw height and width of image.finalint height = options.outHeight;.finalint width = options.outWidth;.intinSampleSize = 1;. .if(height > reqHeight || width > reqWidth) {. .finalint halfHeight = height / 2;.finalint halfWidth = width / 2;. .// Calculate the largest inSampleSize value that is a power of 2 and.// keeps both.// height and width larger than the requested height and width..while((halfHeight / inSampleSize) > reqHeight.&& (halfWidth / inSampleSize) > reqWidth) {.inSampleSize *=2;.}.}.returninSampleSize;.}

再来看一下效果:

上面提供了一种方式,更多细节,需要你自己去优化,下面介绍第二种绘制圆角图片的方式。

首先我们需要了解一个类BitmapShader

引用的介绍如下:

public BitmapShader(Bitmap bitmap,Shader.TileMode tileX,Shader.TileMode tileY)

调用这个方法来产生一个画有一个位图的渲染器(Shader)。

bitmap 在渲染器内使用的位图

tileX The tiling mode for x to draw the bitmap in. 在位图上X方向花砖模式

tileY The tiling mode for y to draw the bitmap in. 在位图上Y方向花砖模式

TileMode:(一共有三种)

CLAMP :如果渲染器超出原始边界范围,会复制范围内边缘染色。

REPEAT :横向和纵向的重复渲染器图片,平铺。

MIRROR :横向和纵向的重复渲染器图片,这个和REPEAT 重复方式不一样,他是以镜像方式平铺。

知道这个原理后,我们贴出对应的代码:view sourceprint?.publicclass CircleImageView extendsImageView {. .privatestatic final String TAG = CircleImageView.class.getSimpleName();.privatePaint mBitmapPaint = new Paint();.privateint mRadius;. .publicCircleImageView(Context context, AttributeSet attrs, intdefStyleAttr) {.super(context, attrs, defStyleAttr);.init();.}. .publicCircleImageView(Context context, AttributeSet attrs) {.super(context, attrs);.init();.}. .publicCircleImageView(Context context) {.super(context);.init();.}. .privatevoid init() {.BitmapDrawable drawable = (BitmapDrawable) getDrawable();.if(drawable == null) {.Log.i(TAG,"drawable: null");.return;.}.Bitmap bmp = drawable.getBitmap();.BitmapShader shader =new BitmapShader(bmp, TileMode.CLAMP,.TileMode.CLAMP);.mBitmapPaint.setShader(shader);.mBitmapPaint.setAntiAlias(true);.invalidate();.}. .@Override.protectedvoid onDraw(Canvas canvas) {.if(getDrawable() == null) {.return;.}.mRadius = Math.min(getWidth()/2, getHeight()/2);.canvas.drawCircle(getWidth() /2, getHeight() / 2, mRadius,.mBitmapPaint);.}. .}

是不是挺简单的

结果我就不显示了,跟上面的一样。上面也是最原始的代码,文章的结尾贴出一份完整优化过的代码共大家参考如下:

view sourceprint?.publicclass CircleImageView extendsImageView {. .privatestatic final ScaleType SCALE_TYPE = ScaleType.CENTER_CROP;. .privatestatic final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_;.privatestatic final int COLORDRAWABLE_DIMENSION = 1;. .privatestatic final int DEFAULT_BORDER_WIDTH = 0;.privatestatic final int DEFAULT_BORDER_COLOR = Color.BLACK;. .privatefinal RectF mDrawableRect = new RectF();.privatefinal RectF mBorderRect = new RectF();. .privatefinal Matrix mShaderMatrix = new Matrix();.privatefinal Paint mBitmapPaint = new Paint();.privatefinal Paint mBorderPaint = new Paint();. .privateint mBorderColor = DEFAULT_BORDER_COLOR;.privateint mBorderWidth = DEFAULT_BORDER_WIDTH;. .privateBitmap mBitmap;.privateBitmapShader mBitmapShader;.privateint mBitmapWidth;.privateint mBitmapHeight;. .privatefloat mDrawableRadius;.privatefloat mBorderRadius;. .privateboolean mReady;.privateboolean mSetupPending;. .publicCircleImageView(Context context) {.super(context);. .init();.}. .publicCircleImageView(Context context, AttributeSet attrs) {.this(context, attrs,0);.}. .publicCircleImageView(Context context, AttributeSet attrs, intdefStyle) {.super(context, attrs, defStyle);. .TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CircleImageView, defStyle,0);. .mBorderWidth = a.getDimensionPixelSize(R.styleable.CircleImageView_border_width, DEFAULT_BORDER_WIDTH);.mBorderColor = a.getColor(R.styleable.CircleImageView_border_color, DEFAULT_BORDER_COLOR);. .a.recycle();. .init();.}. .privatevoid init() {.super.setScaleType(SCALE_TYPE);.mReady =true;. .if(mSetupPending) {.setup();.mSetupPending =false;.}.}. .@Override.publicScaleType getScaleType() {.returnSCALE_TYPE;.}. .@Override.publicvoid setScaleType(ScaleType scaleType) {.if(scaleType != SCALE_TYPE) {.thrownew IllegalArgumentException(String.format("ScaleType %s not supported.", scaleType));.}.}. .@Override.protectedvoid onDraw(Canvas canvas) {.if(getDrawable() == null) {.return;.}. .canvas.drawCircle(getWidth() /2, getHeight() / 2, mDrawableRadius, mBitmapPaint);.if(mBorderWidth != 0) {.canvas.drawCircle(getWidth() /2, getHeight() / 2, mBorderRadius, mBorderPaint);.}.}. .@Override.protectedvoid onSizeChanged(intw, int h, int oldw, intoldh) {.super.onSizeChanged(w, h, oldw, oldh);.setup();.}. .publicint getBorderColor() {.returnmBorderColor;.}. .publicvoid setBorderColor(intborderColor) {.if(borderColor == mBorderColor) {.return;.}. .mBorderColor = borderColor;.mBorderPaint.setColor(mBorderColor);.invalidate();.}. .publicint getBorderWidth() {.returnmBorderWidth;.}. .publicvoid setBorderWidth(intborderWidth) {.if(borderWidth == mBorderWidth) {.return;.}. .mBorderWidth = borderWidth;.setup();.}. .@Override.publicvoid setImageBitmap(Bitmap bm) {.super.setImageBitmap(bm);.mBitmap = bm;.setup();.}. .@Override.publicvoid setImageDrawable(Drawable drawable) {.super.setImageDrawable(drawable);.mBitmap = getBitmapFromDrawable(drawable);.setup();.}. .@Override.publicvoid setImageResource(intresId) {.super.setImageResource(resId);.mBitmap = getBitmapFromDrawable(getDrawable());.setup();.}. .@Override.publicvoid setImageURI(Uri uri) {.super.setImageURI(uri);.mBitmap = getBitmapFromDrawable(getDrawable());.setup();.}. .privateBitmap getBitmapFromDrawable(Drawable drawable) {.if(drawable == null) {.returnnull;.}. .if(drawable instanceof BitmapDrawable) {.return((BitmapDrawable) drawable).getBitmap();.}. .try{.Bitmap bitmap;. .if(drawable instanceof ColorDrawable) {.bitmap = Bitmap.createBitmap(COLORDRAWABLE_DIMENSION, COLORDRAWABLE_DIMENSION, BITMAP_CONFIG);.}else {.bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), BITMAP_CONFIG);.}. .Canvas canvas =new Canvas(bitmap);.drawable.setBounds(0,0, canvas.getWidth(), canvas.getHeight());.drawable.draw(canvas);.returnbitmap;.}catch (OutOfMemoryError e) {.returnnull;.}.}. .privatevoid setup() {.if(!mReady) {.mSetupPending =true;.return;.}. .if(mBitmap == null) {.return;.}. .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();. .mBorderRect.set(0,0, getWidth(), getHeight());.mBorderRadius = Math.min((mBorderRect.height() - mBorderWidth) /2, (mBorderRect.width() - mBorderWidth) /2);. .mDrawableRect.set(mBorderWidth, mBorderWidth, mBorderRect.width() - mBorderWidth, mBorderRect.height() - mBorderWidth);.mDrawableRadius = Math.min(mDrawableRect.height() /2, mDrawableRect.width() / 2);. .updateShaderMatrix();.invalidate();.}. .privatevoid updateShaderMatrix() {.floatscale;.floatdx = 0;.floatdy = 0;. .mShaderMatrix.set(null);. .if(mBitmapWidth * mDrawableRect.height() > mDrawableRect.width() * mBitmapHeight) {.scale = mDrawableRect.height() / (float) mBitmapHeight;.dx = (mDrawableRect.width() - mBitmapWidth * scale) *0.5f;.}else {.scale = mDrawableRect.width() / (float) mBitmapWidth;.dy = (mDrawableRect.height() - mBitmapHeight * scale) *0.5f;.}. .mShaderMatrix.setScale(scale, scale);.mShaderMatrix.postTranslate((int) (dx &#;0.5f) &#; mBorderWidth, (int) (dy &#;0.5f) &#; mBorderWidth);. .mBitmapShader.setLocalMatrix(mShaderMatrix);.}. .}

CentOS使用android 一,Linux部署JDK1.1下载JDK地址:

android 背景图片的变形(background) 这是我因为这个问题第二次影响开发效果了,第一次遇到时解决了一下,中间也遇到过它,都给解决了,但是一段时间后遗忘了,现在把它记下:对butto

android开发扩大CheckBox点击监听范围 android开发过程中,image很小的时候,点击范围很小,很难点击到,用户体验差,在xml文件添加android:text=,就是空格。android:drawableRight="@drawable/...."android:

标签: 安卓圆角矩形图标

本文链接地址:https://www.jiuchutong.com/biancheng/385098.html 转载请保留说明!

上一篇:Android Studio --自动删除没有用的资源,给APK减减肥

下一篇:CentOS使用android(安卓 centos)

  • 工程图纸设计费用收费标准
  • 软件使用权收入怎么计算
  • 多少金额以下可以一次性费用
  • 个体工商户定期定额核定
  • 员工充值饭卡的收入如何做账
  • 个人所得税差额20%政策
  • 半成品委托加工费计入成本还是费用
  • 调整上月的生产成本
  • 跨月应该如何开具红字发票?
  • 零售盘点窍门
  • 全年累积盈利交所得税吗?
  • 建筑业收入确认条件
  • 企业房产税如何申报缴纳
  • 积分抵扣所开的发票,也能在税前扣除吗?
  • 企业优惠条件
  • 广西电子税务局申报
  • 自己从自己公司直接拿钱是犯罪吗知乎
  • 企业所得税可以弥补几年亏损
  • 收到雇主责任险发票计入什么科目
  • 风险控制措施包括哪5个方面
  • 上个月开票这个月确认收入
  • 资源税的征税对象和纳税环节
  • 鸿蒙系统最新版本
  • excel中如何选择只能选择的项
  • dhcp的安全防范
  • 公司给部分员工交公积金
  • 扣缴公积金的会计分录
  • 固定资产计提完折旧怎么处理
  • linux is
  • PHP:mb_strrchr()的用法_mbstring函数
  • php数组函数题目
  • .sfx.exe是什么文件
  • 将款项汇往外地采购专用账户会计分录
  • 前端和后端到底是什么
  • php pdo oracle
  • 限售股交易征税是多少
  • thinkphp+vue
  • ai模拟
  • vi操作命令进入编辑命令
  • 开具农产品收购发票需要什么资料
  • 公司收到银行存款利息回单的会计分录
  • 库存材料清查结论怎么写
  • 发布相应的搜索公告
  • mysql的简单操作
  • 帝国cms使用手册
  • 法人给对公账户转账
  • 进项发票入账但没有发票
  • 增值税普通发票和电子普通发票的区别
  • 培训学校不退学费找什么部门
  • 设计服务内容是什么
  • 公司因担保产生损失
  • 持有至到期投资和债权投资的区别
  • 为什么增值税不计入成本费用
  • 充话费送手机业务
  • 新准则建筑业会计核算
  • 转账手续费怎么入账
  • 建立备查账簿登记的有哪些
  • mysql怎么实现
  • sql server数据库中的null(空值)
  • 重装机兵
  • Linux下Mysql5.7.19卸载方法
  • 修改mysql用户权限
  • bios设置bios密码
  • win7系统锁屏密码
  • Win7系统安装方法
  • 订书针的原理
  • javascript中的document.write
  • unity3d面试题摘选(全)
  • firefox浏览器标识ua
  • windows安装python pip
  • jquery escape
  • javascript中变量的命名规则有哪些?
  • ajax支持浏览器back按钮吗
  • 重新加载activity
  • javascript程序设计教程
  • javascript好学吗?
  • 国家税务总局电子发票
  • 湖南地税电话号码
  • 土地评估报告书
  • 中科院有多少在校研究生
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设