位置: 编程技术 - 正文

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)

  • 小规模纳税人附加税是几个点
  • 税务师考试科目搭配
  • 发票开错抬头做红字发票的账务处理
  • 资本公积转实收资本要交税吗
  • 一般 小规模
  • 季度所得税可以零申报吗
  • 财务费用利息收入结转本年利润
  • 公司付款发票
  • 一般纳税人增值税优惠政策
  • 减免的所得税额怎么入账
  • 转增股本是不是缴个人所得税
  • 自然灾害造成的房屋损失怎么处理
  • 核定征收企业怎么分红的
  • 财政补贴的概念是什么?其性质是什么?
  • 房改房增值税
  • 出口货物保险免税
  • 期初建账库存少录数量会计怎么处理
  • 福利费不交个人所得税会怎么样
  • 发票已认证未抵扣怎么办
  • 个税申报所属期和所得期
  • 制造费用月末怎么结转到生产成本
  • 其他应收款计提坏账比例
  • mac如何强制退出全屏
  • 电脑桌面刷新反应迟钝
  • 预缴税款忘记抵扣
  • 应收存款利息计入什么科目
  • 事业单位预付款会计分录
  • 预收账款调增应纳税所得额
  • 支付厂房租金计入什么科目
  • 羽毛球脚踝扭伤怎么办
  • php入门课程
  • 企业怎么知道增值税的核定方法
  • 融资租入固定资产是什么意思
  • 甲方如何规避合同责任
  • 劳务费发票差额征税
  • 使用spring框架,大概有哪些步骤
  • 猿创部落是干什么的
  • 应付未付的工资属于负债吗
  • 宝塔面板要安装什么环境
  • 合伙企业退伙个税
  • 实际缴纳增值税和应缴纳增值税
  • 什么是企业所得税收入
  • 年终企业所得税怎么结转
  • 银行结算方式有哪几种方式?其具体内容是什么?
  • 有净残值的固定资产累计折旧怎么算
  • 其他应付款转实收资本走什么程序
  • 个人银行账户进账多少
  • 建筑业成本核算表格
  • 不动产租赁服务包括哪些
  • 装修行业小规模最高能开几个点的票
  • 非正常损失进项税额转出怎么计算
  • 预缴的所得税怎么申请退税
  • 押金为什么要走支付宝
  • 工程预付款计入什么科目
  • 住宅可以注册什么类型的公司
  • 资本公积转增股本所有者权益会变吗
  • 劳务外包存在的法律风险
  • 人力资源公司劳务费发票税率
  • 公司之间的借款利息有最小限制吗
  • 成本核算方法有哪几种
  • 服务行业服务费怎么入账
  • 中兴新支点操作系统安装教程
  • 老毛桃2013 U盘启动盘和重装系统图文教程
  • linux 下MySQL服务器的启动与停止
  • Linux下which、whereis、locate、find 区别
  • win10 2020h1
  • linux打包压缩文件的命令
  • win7arm
  • win8系统怎么设置桌面
  • Cocos2d-JS中JavaScript继承
  • apache使用端口
  • win10的安装方式有哪些
  • 小规模企业所得税怎么算
  • 1万4千块钱交多少个人所得税
  • 进项税留抵是什么意思
  • 广东国税app安卓版网上预约
  • 北京供暖 2020
  • 威海行风热线实时收听
  • 山东增值税普通发票查询
  • 地税管理员是干什么的
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

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

    友情链接: 武汉网站建设