用BitmapShader实现圆形图片

一、首先了解一下BitmapShader:

BitmapShader是Shader的子类,可以通过Paint.setShader(Shader shader)进行设置、

我们这里只关注BitmapShader,构造方法:

mBitmapShader = new BitmapShader(bitmap, TileMode.CLAMP, TileMode.CLAMP);

参数1:bitmap

参数2,参数3:TileMode:其取值有三种:1>CLAMP 拉伸 2>REPEAT 重复 3>MIRROR 镜像

二、首先来看一下效果:


三、下面进入编程阶段:

a.如果你是用的是Bitmap类型的图片,即你直接把图片放在了res/mipmap下,那么你就可以参考一下代码实现相应功能:

public class BitmapShaderView extends ImageView {

    private float mRadius;
    private int mWidth;
    private Paint mPaint;
    private Bitmap mBitmap;

    public BitmapShaderView(Context context) {
        this(context, null);
    }

    public BitmapShaderView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public BitmapShaderView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initPaint();
    }

    private void initPaint() {
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mWidth = Math.min(getMeasuredWidth(), getMeasuredHeight());
        mRadius = mWidth * 1.0f / 2;
        setMeasuredDimension(mWidth, mWidth);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        setBitmapShader();
        canvas.drawCircle(mRadius, mRadius, mRadius, mPaint);
//        canvas.drawCircle(mRadius,mRadius,mRadius-10.0f,mPaint);
        //第二个参数rx:x方向上的圆角半径。第三个参数ry:y方向上的圆角半径。
//        canvas.drawRoundRect(new RectF(0, 0, mWidth, mWidth), 30, 30, mPaint);
    }
    private void setBitmapShader() {

        mBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.img10);
        float mBitWidth = Math.min(mBitmap.getWidth(), mBitmap.getHeight());
        Log.d("aaa", "mBitmap.getWidth() = " + mBitmap.getWidth());
        Log.d("aaa", "mBitmap.getHeight() = " + mBitmap.getHeight());
        BitmapShader mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
        float scale = mWidth * 1.0f / mBitWidth;
        Log.d("aaa", "scale = " + scale);
        Matrix mMatrix = new Matrix();
        mMatrix.setScale(scale, scale);
        mBitmapShader.setLocalMatrix(mMatrix);
        mPaint.setShader(mBitmapShader);

    }
}

至于布局文件,那就很简单了   可以参考以下代码:

     
     

     
     
    
    
      
      

        
       
       

    
      
      

     
     

如此你就可以实现你梦寐以求的圆形图片了,怎么样简单吧!

当然有的同学可能会遇到下面这个问题   不解释直接看图:

没错   代码觉得没错,逻辑也没错   怎么就成了这个样子呢   真令人伤脑筋  抓狂
不要着急,我也遇到了这个问题,所以特地记下来提醒一下自己。这个问题其实很简单就只是因为一行代码的事,原因就是我们忘记了注释掉onDraw里面的super.onDraw(canvas);这句话。只要像下面这样注释掉就可以了。
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.ImageView;

/**
 * Created by Administrator on 2017/2/17.
 */
public class BitmapShaderView extends ImageView {

    private float mRadius;
    private int mWidth;
    private Paint mPaint;
    private Bitmap mBitmap;

    public BitmapShaderView(Context context) {
        this(context, null);
    }

    public BitmapShaderView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public BitmapShaderView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initPaint();
    }

    private void initPaint() {
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mWidth = Math.min(getMeasuredWidth(), getMeasuredHeight());
        mRadius = mWidth * 1.0f / 2;
        setMeasuredDimension(mWidth, mWidth);
    }

    @Override
    protected void onDraw(Canvas canvas) {
//        super.onDraw(canvas);//务必注释掉
        setBitmapShader();
        canvas.drawCircle(mRadius, mRadius, mRadius, mPaint);
//        canvas.drawCircle(mRadius,mRadius,mRadius-10.0f,mPaint);
        //第二个参数rx:x方向上的圆角半径。第三个参数ry:y方向上的圆角半径。
//        canvas.drawRoundRect(new RectF(0, 0, mWidth, mWidth), 30, 30, mPaint);
    }
    private void setBitmapShader() {

        mBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.img10);
        float mBitWidth = Math.min(mBitmap.getWidth(), mBitmap.getHeight());
        Log.d("aaa", "mBitmap.getWidth() = " + mBitmap.getWidth());
        Log.d("aaa", "mBitmap.getHeight() = " + mBitmap.getHeight());
        BitmapShader mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
        float scale = mWidth * 1.0f / mBitWidth;
        Log.d("aaa", "scale = " + scale);
        Matrix mMatrix = new Matrix();
        mMatrix.setScale(scale, scale);
        mBitmapShader.setLocalMatrix(mMatrix);
        mPaint.setShader(mBitmapShader);

    }
}



那么有的人又想把图片制成圆角的,又该怎么办呢?下面我们就来看一下   其实也很简单只要修改一行代码就可以。
当然先看效果图:

代码实现很简单   只需要在圆形代码的基础上修改一行代码即可 惊讶
package com.example.circleimageview;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.ImageView;

/**
 * Created by Administrator on 2017/2/17.
 */
public class BitmapShaderView extends ImageView {

    private float mRadius;
    private int mWidth;
    private Paint mPaint;
    private Bitmap mBitmap;

    public BitmapShaderView(Context context) {
        this(context, null);
    }

    public BitmapShaderView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public BitmapShaderView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initPaint();
    }

    private void initPaint() {
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mWidth = Math.min(getMeasuredWidth(), getMeasuredHeight());
        mRadius = mWidth * 1.0f / 2;
        setMeasuredDimension(mWidth, mWidth);
    }

    @Override
    protected void onDraw(Canvas canvas) {
//        super.onDraw(canvas);//务必注释掉
        setBitmapShader();
//        canvas.drawCircle(mRadius, mRadius, mRadius, mPaint);
//        canvas.drawCircle(mRadius,mRadius,mRadius-10.0f,mPaint);
        //第二个参数rx:x方向上的圆角半径。第三个参数ry:y方向上的圆角半径。
        canvas.drawRoundRect(new RectF(0, 0, mWidth, mWidth), 30, 30, mPaint);
    }
    private void setBitmapShader() {

        mBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.img10);
        float mBitWidth = Math.min(mBitmap.getWidth(), mBitmap.getHeight());
        Log.d("aaa", "mBitmap.getWidth() = " + mBitmap.getWidth());
        Log.d("aaa", "mBitmap.getHeight() = " + mBitmap.getHeight());
        BitmapShader mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
        float scale = mWidth * 1.0f / mBitWidth;
        Log.d("aaa", "scale = " + scale);
        Matrix mMatrix = new Matrix();
        mMatrix.setScale(scale, scale);
        mBitmapShader.setLocalMatrix(mMatrix);
        mPaint.setShader(mBitmapShader);

    }
}


这么神奇嘛!哈哈,没错,相信自己的眼睛就是这么神奇!

b. .那么如果有的人就非得用Drawable类型的图片呢,即你直接把图片放在了res/drawable下,那么也没关系,你可以参考一下代码实现相应功能:
package com.example.circleimageview;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.ImageView;

/**
 * Created by Administrator on 2017/2/17.
 */
public class BitmapShaderView extends ImageView {

    private float mRadius;
    private int mWidth;
    private Paint mPaint;
    private Bitmap mBitmap;

    public BitmapShaderView(Context context) {
        this(context, null);
    }

    public BitmapShaderView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public BitmapShaderView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initPaint();
    }

    private void initPaint() {
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mWidth = Math.min(getMeasuredWidth(), getMeasuredHeight());
        mRadius = mWidth * 1.0f / 2;
        setMeasuredDimension(mWidth, mWidth);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        setBitmapShader();
        canvas.drawCircle(mRadius, mRadius, mRadius, mPaint);
//        canvas.drawCircle(mRadius,mRadius,mRadius-10.0f,mPaint);
        //第二个参数rx:x方向上的圆角半径。第三个参数ry:y方向上的圆角半径。
//        canvas.drawRoundRect(new RectF(0, 0, mWidth, mWidth), 30, 30, mPaint);
    }

    private Bitmap DrawableToBitmap(Drawable drawable) {
        //首先明白instanceof是一种运算符是用来在运行时指出对象是否是特定类的一个实例。例如:result = object instanceof class 主要判断前面是否是后面的一个实例 如果 object 是 class 的一个实例,则 instanceof 运算符返回 true。如果 object 不是指定类的一个实例,或者 object 是 null,则返回 false。
        if (drawable instanceof BitmapDrawable) {
            BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
            return bitmapDrawable.getBitmap();
        }
        int w = drawable.getIntrinsicWidth();
        int h = drawable.getIntrinsicHeight();
        // ARGB指的是一种 色彩模式,里面A代表Alpha,R表示red,G表示green,B表示blue. ARGB_8888就是由4个8位组成即32位 ,代表32位ARGB位图.
        Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        drawable.setBounds(0, 0, w, h);
        drawable.draw(canvas);
        return bitmap;
    }

    private void setBitmapShader() {

        Drawable drawable = getDrawable();
        if (null == drawable) {
            return;
        } else {
            //首先获取到bitmap类型的图片
            Bitmap bitmap = DrawableToBitmap(drawable);
            //构造渲染器BitmapShader TileMode的取值有三种:CLAMP 拉伸 REPEAT 重复 MIRROR 镜像
            BitmapShader mBitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
            int mBitWidth = Math.min(bitmap.getWidth(), bitmap.getHeight());
            float scale = mWidth * 1.0f / mBitWidth;
            // shader的变换矩阵,我们这里主要用于放大或者缩小
            Matrix mMatrix = new Matrix();
            mMatrix.setScale(scale, scale);
            mBitmapShader.setLocalMatrix(mMatrix);
            mPaint.setShader(mBitmapShader);
        }

    }
}

好了,本篇就先到这里吧,希望对各位正处在迷茫之中的小伙伴有所帮助 大笑




 




  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值