Kotlin实战练习——自定义圆形图片三种实现方式

前言

如今Kotlin越来越重要,本人也开始了Kotlin的学习。为了检测学习效果,加深学习印象,同时回顾一下以前的一些知识点,决定从写一个自定义圆形图片开始入手。圆形图片写法有很多,这里介绍最主要的三种方式,如果能掌握这三种方式,那么其他的自定义控件应该也都很好实现了。

1. XferMode方式

知识点

1. 关于XferMode

XferMode是一种图片重叠时的处理方式,主要是在图片重叠时,由用户来选取如何对重叠的图片进行处理,XferMode的模式有如下几种:

目前,XferMode有三个子类:AvoidXfermode, PixelXorXfermodePorterDuffXfermode,其中前两个已过时,现在一般用PorterDuffXfermode

2. Canvas和Bitmap的关系

Canvas类似于画板,Bitmap类似于画布,最终我们呈现给别人看的东西,是画布上的内容,也就是Bitmap,但是我们要在Bitmap上画东西,则需要画板的支撑。

3. drawable

drawable主要作用是提供一个可绘制区域和draw函数用来绘制需要的图像、颜色等,在ImageView内,我们只需要关心它的两个方法:

  • setBounds: 可绘制区域;
  • draw: 将内容绘制到画板上的画布中。

实现思路

  1. 先获取一个圆形的Bitmap对象;

  2. 将这个圆形的Bitmap对象覆盖在图片上;

  3. 通过XferMode中的DST_IN模式,选取圆形Bitmap和图片的相交部分。

实现代码

1.初始化画笔、圆形图片半径和XferMode
private var mPaint: Paint? = null
private var mWidth: Int = 0
private var mCircleBitmap: Bitmap? = null
private var xferMode : PorterDuffXfermode? = nullconstructor(context: Context?) : this(context, null)
constructor(context: Context?, attrs: AttributeSet?) : this(context, attrs, 0)
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int): super(context, attrs, defStyleAttr) {init(context)
}fun init(context: Context?) {mPaint = Paint(Paint.ANTI_ALIAS_FLAG)xferMode = PorterDuffXfermode(PorterDuff.Mode.DST_IN)
}override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {super.onMeasure(widthMeasureSpec, heightMeasureSpec)mWidth = if(width > height) height else widthsetMeasuredDimension(mWidth, mWidth)
}
2.获取一个圆形图片
// 1.先获取一个圆形图片
if(mCircleBitmap == null) {mCircleBitmap = Bitmap.createBitmap(mWidth, mWidth, Bitmap.Config.ARGB_8888)var circleCanvas = Canvas(mCircleBitmap)mPaint?.reset()mPaint?.style = Paint.Style.FILLcircleCanvas.drawCircle(mWidth/2f, mWidth/2f, mWidth/2f, mPaint)
}
3.将圆形Bitmap覆盖到图片上
// 2.将圆形图片和源图片相交,截取相交部分
var drawableHeight = drawable?.intrinsicHeight ?: 0
var drawableWidth = drawable?.intrinsicWidth ?: 0
var drawableBitmap = Bitmap.createBitmap(drawableWidth, drawableHeight, Bitmap.Config.ARGB_8888)
var drawableCanvas = Canvas(drawableBitmap)
drawable?.setBounds(0, 0, mWidth, maxHeight)
drawable?.draw(drawableCanvas)mPaint?.reset()
mPaint?.xfermode = xferMode
drawableCanvas.drawBitmap(mCircleBitmap, 0f, 0f, mPaint)
mPaint?.xfermode = null
4.将合成后的圆形图片显示到控件中
// 3.将合成后的圆形图片显示到控件中
canvas?.drawBitmap(drawableBitmap, 0f, 0f, mPaint)

2. BitmapShader方式

知识点

1. BitmapShader介绍

bitmapshader是用来给Paint施加一个渲染效果,它是shader的子类。初始化的时候,需要对它设置TileMode,一共有三种模式:

  • CLAMP: 拉伸。若图片没有填充满布局,会将x,y轴的最后一个像素拉伸到布局边缘;
  • REPEAT: 重复。若图片没有填充满布局,会将图片进行x/y轴的重复;
  • MIRROR: 镜像。若图片没有填充满布局,则会将图片进行镜像复制。

BitmapShader是给画笔的渲染,它是从控件左上角开始渲染的,而不是从绘画开始的地方进行渲染的!

关于ShaderBitmapShader的更多介绍,请自行百度。

2. Matrix

Matrix有多种用法,我们这里仅仅是用它的缩放功能,目的是让图片的大小大于或等于控件的大小,以免图片填充不满产生拉伸效果!

实现思路

原理: 给画笔设置一个BitmapShader,就好像画布上已经存在一张隐藏的Bitmap,画笔画哪个地方,哪个地方的画面就显示出来。

  1. drawable转换成Bitmap

  2. 新建BitmapShader,将Bitmap设置进去,并通过MatrixBitmap缩放到和控件大小一样(不能小于控件大小),以免产生拉伸效果;

  3. 画圆形图片,将"隐藏的"图片显示出来。

实现代码

1.初始化

同方法一

2.将drawable转换成bitmap
if(mShaderBitmap == null) {if(drawable is BitmapDrawable) {var d = drawable as? BitmapDrawablemShaderBitmap = d?.bitmap} else {var drawableHeight = drawable.intrinsicHeightvar drawableWidth = drawable.intrinsicWidthmShaderBitmap = Bitmap.createBitmap(drawableWidth, drawableHeight, Bitmap.Config.ARGB_8888)var drawableCanvas = Canvas(mShaderBitmap);drawable.setBounds(0, 0, drawableWidth, drawableHeight)drawable.draw(drawableCanvas);}
}
3.设置BitmapShader
if(mBitmapShader == null) {mBitmapShader = BitmapShader(mShaderBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)// 设置缩放大小,保证bitmap的大小要大于控件的大小(以免产生拉伸效果!)var bitmapWidth = Math.min(mShaderBitmap!!.width, mShaderBitmap!!.height)var scale = mWidth * 1.0f / bitmapWidthmMatrix = Matrix()mMatrix?.setScale(scale, scale)mBitmapShader?.setLocalMatrix(mMatrix);
}
4.给画笔设置BitmapShader
mPaint?.shader = mBitmapShader;
5.将圆形图片画在画板上
canvas?.drawCircle(mWidth / 2.0f, mWidth / 2.0f, mWidth / 2.0f, mPaint)

3.ClipPath方式

知识点

1.canvas.clipPath()

裁剪功能,设置canvas的绘画区域。
重要: ClipPath()方法不支持硬件加速!!!

实现思路

  1. 先将drawable转换成bitmap

  2. 给画板设置绘图区域为圆形;

  3. 绘画

实现代码

1. 先将drawable转换成bitmap
if(mClipPathBitmap == null) {if(drawable is BitmapDrawable) {var d = drawable as? BitmapDrawablemClipPathBitmap = d?.bitmap} else {var h = drawable.intrinsicHeightvar w = drawable.intrinsicWidthmClipPathBitmap = Bitmap.createBitmap(w,h,Bitmap.Config.ARGB_8888)var drawableCanvas = Canvas(mClipPathBitmap);drawable.setBounds(0 ,0, mWidth, mWidth)drawable.draw(drawableCanvas)}
}
2. 给画板设置绘图区域为圆形
var path = Path()
path.addCircle(mWidth / 2.0f, mWidth / 2.0f,mWidth / 2.0f,Path.Direction.CCW)
3.绘图
canvas?.save()
canvas?.clipPath(path)
canvas?.drawBitmap(mClipPathBitmap, 0f, 0f, mPaint);
canvas?.restore()

Kotlin实战练习——自定义圆形图片三种实现方式相关推荐

  1. 自定义View的三种实现方式及自定义属性使用介绍

    自定义View的三种实现方式及自定义属性使用介绍 一 前言 二 三种自定义控件的方法 2.1 组合控件 2.2 继承控件 2.2.1 继承View类系统控件 2.2.2 继承ViewGroup类系统控 ...

  2. Android 自定义圆形图片 CircleImageView

    1.效果预览 1.1.布局中写自定义圆形图片的路径即可 1.2.然后看一看图片效果 1.3.原图是这样的 @mipmap/ic_launcher 2.使用过程 2.1.CircleImageView源 ...

  3. Web框架之Django_07 进阶操作(MTV与MVC、多对多表三种创建方式、前后端传输数据编码格式contentType、ajax、自定义分页器)

    阅读目录 一.MVC与MTV 二.多对多表的创建 三.ajax,前后端传输编码格式contentType 四.批量插入数据与自定义分页器 摘要 MTV与MVC 多对多表三种创建方式 ajax ,前后端 ...

  4. 鸿蒙os事例代码,鸿蒙HarmonyOS App开发造轮子之自定义圆形图片组件的实例代码

    一.背景 在采用Java配合xml布局编写鸿蒙app页面的时候,发现sdk自带的Image组件并不能将图片设置成圆形,反复了翻阅了官方API手册(主要查阅了Compont和Image相关的API),起 ...

  5. Unity 自定义圆形图片

    使用Mask组件的缺点 我们知道项目中可以这样展示圆形图片,一般是Image组件,下面再加上一个圆形Mask.但是这样做有几个缺点: 使用Mask会额外消耗多一个Drawcall来创建Mask,做像素 ...

  6. 打开桌面计算机图片,电脑桌面截图呢?三种截图方式

    在日常工作的时候,经常会需要截图工具来截取一些图片用于保存,特别是有的时候,图片需要特定尺寸的时候,截图方法是最便捷的,但是很多人对电脑截图并不是很熟悉,电脑桌面截图呢?今天就给大家讲解一下三种截图方 ...

  7. Android 自定义圆形图片

    代码注释很多,简单说下思路,然后直接贴代码 1.截取选定图片中间区域(宽等于高的正方形) 2.按照控件大小进行缩放 3.画圆,设置paint.setXfermode(new PorterDuffXfe ...

  8. java基础:map遍历使用;java使用 Patten 和Matches 进行正则匹配;后端传到前端展示图片三种情况,并保存到手机;

    文章目录 前言 一.map 遍历方法 二.java正则学习 三.后端传到前端图片三种情况 1. 图片流数据(InputStream) 转 base64,前端展示保存 a. 后端:输入流转base,直接 ...

  9. canvas保存到本地图片三种方法

    canvas保存到本地图片三种方法 canvas保存本地图片 第一种方法(修改图片的媒体类型,window.open直接下载) 第二种方法(创建a标签,通过自己触发点击来下载) 第三种方法(将图片数据 ...

最新文章

  1. OpenCV中图像修复技术介绍与演示
  2. 计算机的图形渲染机制
  3. python简单代码input-python基础 input()函数
  4. 利用django中间件CsrfViewMiddleware防止csrf攻击
  5. ClickOnce部署(3):使用证书
  6. perl开发工具大全
  7. Javascript基础学习20问(二)
  8. android性能优化 掘金,Android性能优化之内存泄漏
  9. python cos函数_Python Tensorflow cos()用法及代码示例
  10. 如何还原已经推送到远程分支的合并提交?
  11. php mysql 输出csv_php使用指定编码导出mysql数据到csv文件的方法
  12. C语言二维数组指针用法
  13. 计算机本地硬盘带蓝色问号,win10本地磁盘显示蓝色问号该怎么解决
  14. centos6.5 ifconfig 显示为eth2,配置文件只有eth0
  15. 身份验证错误,指定的句柄无效
  16. 2018秦皇岛ccpc赛后总结
  17. Photoshop支持ICO图片格式
  18. upc组队赛16 GCDLCM 【Pollard_Rho大数质因数分解】
  19. android 2d 字体描边,关于ios下字体描边的一个细节
  20. 电子元件学习——晶闸管(可控硅)

热门文章

  1. 单片机原理及接口技术(C51微课第3版)张毅刚课后习题答案
  2. ionic2开发环境 linux,安装ionic开发环境
  3. seo优化notfallow有二种下拉菜单百度搜索引擎
  4. 哈尔滨工业大学计算机考研专业课,2020考研哈尔滨工业大学计算机考研考试科目...
  5. micropython大小_Micropython进阶 | 如何用单片机制作鞋码匹配仪
  6. linux桌面添加第三方软件图标
  7. 网卡驱动卸载后一直安装失败的问题成功解决
  8. 交互媒体专题设计------《The Wiley Handbook of Human Computer Interaction》
  9. 【转】100本最棒的英文侦探小说
  10. libnativehelper 加载库失败