android绘制圆形图片的两种方式示例
作者:S丶black 发布时间:2021-10-11 13:17:28
标签:android,绘制,圆形
android绘制圆形图片的两种方式
看下效果先
下面有完整的示例代码
使用BitmapShader(着色器)
我们在绘制view 的时候 就是小学上美术课 用水彩笔在本子上画画 使用着色器绘制圆形图片最简单的理解方式 就是把bitmap当做一种颜色 设置给paint ,paint都已经有颜色了 你想让它方了,圆了,扁了 还不是看你心情 canvas调用那个方法咯
实现的大致思路如下:
1. 创建一个类 继承imageView 重写onDraw()
2. 获取到bitmap图片
3. 计算图片的缩放比例 使用矩阵matrix 进行缩放
4. 创建BitmapShader着色器 设置缩放矩阵
5. paint设置着色器 绘制
具体实现 注释也标注的很清楚
private void shaderCircle(Canvas canvas){
//获取Drawable
Drawable resources=getDrawable();
float scale = 1.0f;//缩放比例
int mRadius=0;//圆的半径
if (resources instanceof BitmapDrawable){
//获取bitmap
Bitmap bitmap=((BitmapDrawable) resources).getBitmap();
if (bitmap==null) return;
// 获取bitmap宽高中的小值
int minBitMap = Math.min(bitmap.getWidth(), bitmap.getHeight());
//取view宽高中的小值 尽量保证图片内容的显示
int minValue=Math.min(getWidth(),getHeight());
//设置半径
mRadius=minValue/2;
//计算缩放比例 一定要*1.0f 因为int之间的计算结果会四舍五入0或1 效果就不美丽了
scale=minValue*1.0f/minBitMap;
//设置缩放比例
matrix.setScale(scale,scale);
/**
* 创建着色器 设置着色模式
* TileMode的取值有三种:
* CLAMP 拉伸 REPEAT 重复 MIRROR 镜像
*/
BitmapShader shader=new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
//设置矩阵
shader.setLocalMatrix(matrix);
paint.setShader(shader);
canvas.drawCircle(mRadius, mRadius, mRadius, paint);
}
}
使用Xfermode 设置图片相交模式
简单说呢 在一张画布上画了两张图片 这两张图的以怎样的方式显示出来 例如:只显示上层图片,只显示下层图片 ,显示两张图的交集部分 等等等
实现思路
1.创建一个空bitmap 根据这个bitmap创建一个Canvas
2.设置Canvas透明 画一个想要实现的形状
3.设置图形相交模式
4.获取图片资源 绘制到Canvas
实现代码
private Bitmap getCircleBitmap(){
Drawable drawable=getDrawable();
if (drawable instanceof BitmapDrawable) {
Paint paint=new Paint();
paint.setAntiAlias(true);
//获取资源图片
Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
//创建空位图
Bitmap output=Bitmap.createBitmap(getWidth(),getHeight(),Bitmap.Config.ARGB_8888);
//创建画板
Canvas canvas=new Canvas(output);
//绘制整个画板为透明
canvas.drawColor(Color.TRANSPARENT);
paint.setColor(Color.WHITE);
//绘制圆角图片
if (type==ROUND){
canvas.drawRoundRect(new RectF(0, 0, getWidth(), getHeight()), mRound, mRound,paint);
}else{
//绘制圆形图片
//取view宽高中的小值 尽量保证图片内容的显示
int minValue = Math.min(getWidth(), getHeight());
//设置半径
mRadius = minValue / 2;
canvas.drawCircle(mRadius,mRadius,mRadius,paint);
}
//设置图形相交模式
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
Rect src=new Rect(0,0,bitmap.getWidth(),bitmap.getHeight());
Rect dst=new Rect(0,0,output.getWidth(),output.getHeight());
canvas.drawBitmap(bitmap,src,dst,paint);
return output;
}
return null;
}
这个特别经典的图......
PorterDuff.Mode.CLEAR 清除画布上图像
PorterDuff.Mode.SRC 显示上层图像
PorterDuff.Mode.DST 显示下层图像
PorterDuff.Mode.SRC_OVER上下层图像都显示,上层居上显示
PorterDuff.Mode.DST_OVER 上下层都显示,下层居上显示
PorterDuff.Mode.SRC_IN 取两层图像交集部分只显示上层图像
PorterDuff.Mode.DST_IN 取两层图像交集部分,只显示下层图像
PorterDuff.Mode.SRC_OUT 取上层图像非交集部分
PorterDuff.Mode.DST_OUT 取下层图像非交集部分
PorterDuff.Mode.SRC_ATOP 取下层图像非交集部分与上层图像交集部分
PorterDuff.Mode.DST_ATOP 取上层图像非交集部分与下层图像交集部分
PorterDuff.Mode.XOR 取两层图像的非交集部分
参考文档
继承ImageVIew完成圆形和圆角图片控件的实现过程(使用着色器)
<declare-styleable name="CircleImage">
<attr name="imageRound" format="dimension"/>
<attr name="imageType">
<enum name="circle" value="0"/>
<enum name="round" value="1"/>
</attr>
</declare-styleable>
public class CircleImage extends ImageView {
private Matrix matrix;
private Paint paint;
private int mRound;//圆角度数
private int mRadius;//圆的半径
private int type;//控件类型
private final int CIRCLE=0;//圆形
private final int ROUND=1;//圆角
public CircleImage(Context context) {
super(context,null);
}
public CircleImage(Context context, AttributeSet attrs) {
super(context, attrs);
matrix=new Matrix();
paint=new Paint();
paint.setAntiAlias(true);
initAttrValues(context,attrs);
}
@Override
protected void onDraw(Canvas canvas) {
if (getDrawable() == null) {
return;
}
setShader();
if (type==CIRCLE){
canvas.drawCircle(mRadius, mRadius, mRadius, paint);
}else{
canvas.drawRoundRect(new RectF(0, 0, getWidth(), getHeight()), mRound, mRound,paint);
}
}
/**
* 初始化属性集合
* @param context
* @param attrs
*/
private void initAttrValues(Context context, AttributeSet attrs){
TypedArray typedArray=context.obtainStyledAttributes(attrs, R.styleable.CircleImage);
for (int i=0;i<typedArray.getIndexCount();i++){
int index=typedArray.getIndex(i);
switch (index){
case R.styleable.CircleImage_imageRound:
mRound =typedArray.getDimensionPixelSize(index,
(int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,10,getResources().getDisplayMetrics()));
break;
case R.styleable.CircleImage_imageType:
type=typedArray.getInt(index,CIRCLE);
break;
}
}
}
/**
* 设置着色器
*/
private void setShader() {
//获取Drawable
Drawable resources=getDrawable();
float scale = 1.0f;//缩放比例
if (resources instanceof BitmapDrawable) {
//获取bitmap
Bitmap bitmap = ((BitmapDrawable) resources).getBitmap();
if (bitmap == null) return;
//圆形
if (type==CIRCLE){
// 获取bitmap宽高中的小值
int minBitMap = Math.min(bitmap.getWidth(), bitmap.getHeight());
//取view宽高中的小值 尽量保证图片内容的显示
int minValue = Math.min(getWidth(), getHeight());
//设置半径
mRadius = minValue / 2;
//计算缩放比例 一定要*1.0f 因为int之间的计算结果会四舍五入0或1 效果就不美丽了
scale = minValue * 1.0f / minBitMap;
}else{
//比较view和图片宽高比例大的 要让缩放后的图片大于view
scale = Math.max(getWidth() * 1.0f / bitmap.getWidth(), getHeight()
* 1.0f / bitmap.getHeight());
}
//设置缩放比例
matrix.setScale(scale, scale);
/**
* 创建着色器 设置着色模式
* TileMode的取值有三种:
* CLAMP 拉伸 REPEAT 重复 MIRROR 镜像
*/
BitmapShader shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
//设置矩阵
shader.setLocalMatrix(matrix);
//设置着色
paint.setShader(shader);
}
}
/**
* 测试转换效果 没什么卵用 可以删除
* @param event
* @return
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction()==MotionEvent.ACTION_DOWN){
if (type==CIRCLE){
mRound =10;
type=ROUND;
}else{
type=CIRCLE;
}
invalidate();
}
return super.onTouchEvent(event);
}
}
来源:http://www.cnblogs.com/r-decade/p/6250450.html
0
投稿
猜你喜欢
- 前言之前实现过《Android可签到的日历控件》的功能,跟这篇一样都是实现签到打卡功能,这篇实现的是按月进行打卡做标识,本篇内容实现的按周进
- 先看代码://设置可以同时处于活动状态的线程池的请求数目。 bool pool = ThreadPool.SetMaxThreads(8,
- 1、抽象类 vs 接口 方法类型: 接口只能有抽象方法。抽象类可以有抽象和非抽象方法。从 Java 8 开始,它也可以有默认和静态
- Java调用cmd命令,并输出显示信息:package com.anxin.cmd.test; import java.io.Buffere
- 主要功能:勾选子节点的checkbox,右边会动态加载该节点的信息,出现TextBox让用户填写节点的值,点击保存按钮将文本框的值保存到对应
- 在学习MyBatis过程中想实现模糊查询,可惜失败了。后来上百度上查了一下,算是解决了。记录一下MyBatis实现模糊查询的几种方式。 数据
- 在ibatis的xml文件里,我们去写sql语句,对应mapper类的方法,这些sql语句与控制台上没什么两样,但在有些功能上需要注意,如w
- Thrift是一个软件框架,用来进行可扩展且跨语言的服务的开发。它结合了功能强大的软件堆栈和代码生成引擎,以构建在 C++, Java, P
- 解决办法:1.VCS--->Enable Version Control Integration2.选择要关联的版本工具补充:git
- 在上一篇笔记 《SpringMVC实现图片上传》记录了将图片上传到本地的实现,在很多项目中都会有一台专门的文件服务器来保存文件的,这边记录下
- java调用Rsync并发迁移数据并执行校验java代码如下RsyncFile.javaimport lombok.NoArgsConstr
- 具体代码如下所示:import java.io.File;public class Scan { public static v
- 简介:在团队协作开发的过程中,好的代码管理能更加有效的使日常开发的过程中对各个开发人员提高开发速度。下面将详细介绍在IDEA中使用git提交
- Eureka大白话解析笔记补录:1.Eureka 介绍Spring Cloud Eureka 是 Spring Clou
- 本文实例讲述了Java链表(Linked List)基本原理与实现方法。分享给大家供大家参考,具体如下:在分析链表之前,我们先来对之前的动态
- 1.情景展示java发送get请求、post请求(form表单、json数据)至另一服务器;可设置HTTP请求头部信息,可以接收服务器返回c
- 前言Kafka是现在非常热门的分布式消息队列,常用于微服务间异步通信,业务解耦等场景。kafka的性能非常强大,但是单个微服务吞吐性能是有上
- 服务端package lesson02;import java.io.*;import java.net.ServerSocket;impo
- 提到迭代器我们不能不想到迭代器模式,那我就以迭代器模式作为开场白.在我们的应用程序中常常有这样一些数据结构:它们是一个数据的集合,如果你知道
- 最近在做数据挖掘的课程设计,需要将数据分析的结果很直观的展现给用户,这就要用到数据统计图,要实现这个功能就需要几个第三方包了:1.