位置: 编程技术 - 正文

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)

  • 租赁合同印花税计税依据
  • 结转应交增值税是什么意思
  • 企业如何帮员工交公积金
  • 商业汇票申请贴现分录
  • 四联发票都需要盖什么章
  • 个体经营部可以开增值税专用发票吗
  • 印花税的纳税人为书立合同双方
  • 工程结算开票金额与付款金额区别
  • 2021小规模纳税人减免增值税
  • 费用类科目分类怎么避免出错
  • 向境外销售货物交增值税吗?
  • 一般纳税人无票收入会计分录
  • 土地结转会计分录是什么
  • 专利技术转让使用费如何做会计处理?
  • 材料成本差异分配率
  • 合并报表汇兑损益怎么填
  • 小规模纳税人如何纳税
  • 高新技术企业如何融资
  • 没有核定税种怎么报税
  • 薪酬费用属于什么科目
  • 不动产处置流程
  • 企业的应收帐款增长率超过销售收入增长率是正常现象
  • 个人独资企业查账征收个人所得税汇算清缴
  • 增值税退税金额怎么算
  • 未确认融资费用属于企业资产类科目对不对
  • 推广服务费收入如何核算成本
  • 推广费属于什么科目
  • 业务招待费例子
  • windows11怎么创建宽带拨号连接图标
  • 营运能力指标正常范围
  • w10触摸键盘
  • php file_exists 检查文件或目录是否存在的函数
  • 红字发票只能一张一张开吗
  • antvl7
  • 典当行交易是给现金吗
  • 影响安全库存的因素包括
  • 固定资产清理如何结转
  • laravel多条件查询
  • 农产品来料加工设备
  • 设备销售合作协议书范本
  • 待转销项税额会计分录
  • 代理服务费怎么入账
  • idea如何运行vue项目
  • 危废处理需要哪些手续
  • 什么是长期应付票据
  • javascript bom dom
  • opencv教程
  • xi:xtreg命令
  • atx系统的grpck命令可验证组的合法性
  • 未确认融资费用账务处理
  • java 访问者模式
  • 生产车间的辅助记录
  • sqlserver高版本数据库文件转低版本
  • 个人所得税应纳税额
  • 因质量问题免费退货
  • 对公账户收到钱都要开票吗
  • 存货跌价准备是什么意思
  • 私车公用的风险防范
  • 个人承包公司运输违法吗
  • 利息收入红字如何入账
  • 母子公司往来款属于借款吗
  • 未认证的发票不入账有什么影响
  • 应收账款贷方有余额说明什么
  • 公司收到赔偿款要交增值税吗
  • 银行涉外收入申报单
  • 投资收益怎么做帐
  • 无形资产减值准备是什么科目
  • 禁用windows杀毒
  • linux处理文件命令
  • win10链接手机怎么用
  • pavprot.exe - pavprot是什么进程 作用是什么
  • cocos2d转unity难吗
  • nodejs后端教程
  • android 生成图片
  • lua脚本语言零基础教程
  • android 笔记软件推荐
  • 所得税季度预缴,年度汇算清缴
  • 福建省农业厅副厅长梁
  • 软件企业增值税即征即退政策
  • 武汉二手房交易信息
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

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

    友情链接: 武汉网站建设