位置: 编程技术 - 正文

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)

  • 居间费用如何纳税
  • 如何根据资产负债表填写现金流量表
  • 商品和服务税收分类编码
  • 年底没计提年终奖,下一年发放要怎么做
  • 合同履约成本合同结算如何处理抵消
  • 收到的油费预付怎么入账
  • 抵扣上月留抵税额的分录
  • 银行缴纳印花税贷款方面哪些可以减免
  • 股权转让 分期付款
  • 增值税申报金额含税吗
  • 三十个生僻字
  • 销售退货成本如何计算
  • 企业所得税上个季度赔钱下个季度挣钱
  • 土地使用权出让金
  • 只有专票没有普票
  • 不征税发票的12个税种
  • 关于积分的三种账务处理方法
  • 亿企代账怎么删除科目
  • centos 6.5安装教程
  • psdrvcheck.exe - psdrvcheck是什么进程 有什么用
  • 法人变更涉及到什么
  • 网速不稳定的解决方法
  • 进项税额转出会计分录福利费
  • 代扣代缴手续费比例
  • 增值税专用发票有几联?
  • php的数据类型主要有哪几种?
  • 工程完工后有关工作总结
  • 银行汇票属于银行存款吗
  • 可以跨城租车吗
  • 分页page
  • 封装和调用
  • 前端向后端传递对象数组
  • 谈谈社会公德普通话三分钟
  • yolov3 改进
  • 小规模纳税人按简易计税法计税时也可以进行税额的抵扣
  • dd命令拷贝磁盘
  • 公司没有车,加柴油票可以抵扣增值税吗
  • 帝国cms模板文件在哪
  • 什么是跨域以及解决方法
  • 给最爱的他
  • 管理费用包括项目成本吗
  • java接口基础知识
  • 生产型出口企业的概念
  • 支付国外佣金的税率多少
  • 库存现金怎么算
  • 外汇保值业务的特点包括
  • 非财政补助结余分配属于什么科目
  • 怎样识别真假增值税发票
  • 职工体检费用标准规定
  • 只有收据没有发票怎么入账
  • 发放工资凭证后多久到账
  • 小规模公司购买水泥怎么入账
  • 货款去零头分录
  • 开具红字发票如何做账?
  • 现金日记账怎么记账
  • 去年的车辆保险今年才开怎么做分录
  • 投资款如何界定
  • MySql 5.6.14 winx64配置方法(免安装版)
  • win7系统环境变量无法编辑怎么办
  • win8系统怎么关闭投影
  • 安装windowsserver2008r2提示无法定位程序输入点
  • 苹果的os什么意思
  • xp系统如何进入桌面
  • 如何禁止mac adobe acrobat联网
  • remind32.exe - remind32是什么进程 有什么用
  • 退出清理磁盘
  • linux如何使用uname命令
  • window10如何设置访客权限
  • linux命令删除指定目录
  • ms-dos 6.2批处理文件高级指南
  • jquery easy ui
  • android.intent.extra.text
  • 完美世界3v3
  • androidapplication
  • 贵州省电子税务局操作手册
  • 国家税务总局党建工作局
  • 如何查询车辆购买的保险
  • 中山市地方税务局官网
  • 手机微信怎么预约
  • 企业年检里的纳税是什么
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

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

    友情链接: 武汉网站建设