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);
  }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android canvas画图操作之切割画布实现方法(clipRect)

    本文实例讲述了Android canvas画图操作之切割画布实现方法.分享给大家供大家参考,具体如下: android切割画布的历程不算很难,可是理解起来也比较麻烦,这里写一下我的理解 但是不一定正确: canvas.clipRect(30, 30, 70, 70, Region.Op.XOR); 最后一个参数有多个选择分别是: //DIFFERENCE是第一次不同于第二次的部分显示出来 //REPLACE是显示第二次的 //REVERSE_DIFFERENCE 是第二次不同于第一次的部分显示

  • Android自定义控件绘制基本图形基础入门

    本文讲述绘制Android自定义各种图形效果,为自定义控件的入门篇 相关视频链接: Android自定义控件系列 http://edu.csdn.net/course/detail/3719/65396 Android视频全系列 http://edu.csdn.net/course/detail/2741/43163 绘制点–这个控件只需要在布局中引用或者代码中new 即可,下面几个绘制只展示onDraw方法 package com.example.viewdemo1.view; import

  • Android树形控件绘制方法

    前言 作为一个开发者,日常会接触到很多优秀的软件,其实,或多或少会有这样的想法,我能不能开发一个自己软件,甚至办公软件都希望是Markdown的文本,为何用office?我常常想自己做一个IDE什么的.但是,很多只是想了一下就过了,一直没有实现. 我接触思维导图软件已经很久的了,开始是使用微软的思维导图软件,接着XMind,后来使用了MindMaple Lite.感觉很好用的.也想过如何去实现一个思维导图的软件,加之我特别注意软件的快捷键,我选取软件常常是,看快捷如何,快捷键差的就不要了.基于自

  • Android开发之图形图像与动画(一)Paint和Canvas类学习

    Paint类 *Paint类代表画笔,用来描述图形的颜色和风格,如线宽,颜色,透明度和填充效果等信息. *使用Paint类时,需要先创建该类的对象,可以通过该类的构造函数实现.通常情况的实现代码是: *Paintpaint=newPaint(); *创建完Paint对象后,可以通过该对象提供的方法对画笔的默认设置进行改变 Canvas *Canvas类代表画布,通过该类提供的构造方法,可以绘制各种图形. *通常情况下,要在Android中绘图,需要先创建一个继承自View类的视图,并且在该类中重

  • Android编程之canvas绘制各种图形(点,直线,弧,圆,椭圆,文字,矩形,多边形,曲线,圆角矩形)

    本文实例讲述了Android编程之canvas绘制各种图形的方法.分享给大家供大家参考,具体如下: 1.首先说一下canvas类: Class Overview The Canvas class holds the "draw" calls. To draw something, you need 4 basic components: A Bitmap to hold the pixels, a Canvas to host the draw calls (writing into

  • Android编程实现canvas绘制饼状统计图功能示例【自动适应条目数量与大小】

    本文实例讲述了Android编程实现canvas绘制饼状统计图功能.分享给大家供大家参考,具体如下: 本例的目的是实现一个简单的饼状统计图,效果如下:    特点: 1.使用非常方便,可放在xml布局文件中,然后在代码中设置内容,即: PieChartView pieChartView = (PieChartView) findViewById(R.id.pie_chart); PieChartView.PieItemBean[] items = new PieChartView.PieItem

  • Android中使用Canvas绘制南丁格尔玫瑰图(Nightingale rose diagram)

    南丁格尔玫瑰图 在常规图表中实在很惊艳,但我初看没看懂,一查原来南丁格尔这么伟大,确实值得尊敬. 再仔细研究了下这种图的构成,发现原来就是把柱形图的柱形换成了扇形图的半径来表示,当然,变种有好多,我这只是说我理解的这种. 知道了其构成方式后就好实现了,依传入参数个数决定其扇形角度,依百分比决定其扇形的半径长度,然后就一切都水到渠成了. 漂亮的美图献上: 附上实现代码: package com.xcl.chart; /** * Canvas练习 * 自已画南丁格尔玫瑰图(Nightingale r

  • Android自定义View实现shape图形绘制

    概述 之前曾写过一篇文章介绍了Android中drawable使用Shape资源,通过定义drawable中的shape资源能够绘制简单的图形效果,如矩形,椭圆形,线形和圆环等.后来我在项目中正好遇到这样一个需求,要在特定的位置上显示一条垂直的虚线.正当我胸有成竹的把上面的资源文件放入进去的时候,我才发现它并不能符合我的要求.使用shape画出的垂直虚线,其实就是将一条水平的线,旋转90度.但这样做的弊端就是,该View有效区域为旋转90度后与原来位置相重合的区域,还不能随意的改动,这样的效果根

  • Android编程开发之在Canvas中利用Path绘制基本图形(圆形,矩形,椭圆,三角形等)

    本文实例讲述了Android编程开发之在Canvas中利用Path绘制基本图形的方法.分享给大家供大家参考,具体如下: 在Android中绘制基本的集合图形,本程序就是自定义一个View组件,程序重写该View组件的onDraw(Canvase)方法,然后在该Canvas上绘制大量的基本的集合图形. 直接上代码: 1.自定义的View组件代码: package com.infy.configuration; import android.content.Context; import andro

  • Android自定义view绘制圆环占比动画

    一.实现效果图 二.核心代码 1.自定义MyProgressView.java package com.czhappy.effectdemo.view; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas;

  • Android使用Canvas绘制圆形进度条效果

    前言 Android自定义控件经常会用到Canvas绘制2D图形,在优化自己自定义控件技能之前,必须熟练掌握Canvas绘图机制.本文从以下三个方面对Canvas绘图机制进行讲解: 画布Canvas 画笔Paint 示例圆形进度条 画布Canvas 首先,来看一下Android官网对Canvas类的定义: The Canvas class holds the "draw" calls.To draw something, you need 4 basic components: A B

随机推荐