项目实践-自定义View - 自定义圆形头像

一 前言

毕业了,纷纷杂杂的事情。

参考资料:
Android BitmapShader 实战 实现圆形、圆角图片

好的,第一个问题就是BitmapShader是什么。

二 BitmapShader是什么

官方文档

Shader used to draw a bitmap as a texture. The bitmap can be repeated or mirrored by setting the tiling mode.
Shader用于将位图绘制为纹理。通过设置平铺模式可以重复或镜像位图。

没懂,纹理又是什么?
Android BitmapShader 实战 实现圆形、圆角图片第三节浅谈BitmapShader中了解到,其实就是用bitmap来绘制。根据指定的TileMode,对指定区域用bitmap进行着色。
而它继承的Shader,就是一个着色器。
具体关于BitmapShader的效果,看自定义控件其实很简单1/3
在这里插入图片描述

三 实现思路

mPaint.setShader(new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.MIRROR));这句语句以及它的实现效果,我们可以看到,它就是一个根据传入的Bitmap,和设置的TileMode模式进行上色的作用
那么假如,把画笔设置成这样,并且让它画圆形,不就实现了想要的效果吗?

四 实践

public class CircleImageView extends android.support.v7.widget.AppCompatImageView {
    private Paint bitmapPaint;
    private BitmapShader bitmapShader;
    /**
     * 3x3 矩阵,主要用于缩小放大
     */
    private Matrix mMatrix;

    //View的宽高
    private int mWidth;
    //半径
    private int mRadius;

    public CircleImageView(Context context, AttributeSet attrs) {
        super(context, attrs);

        bitmapPaint = new Paint();
        bitmapPaint.setAntiAlias(true);
        mMatrix = new Matrix();

    }

	
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //强制改变view的宽高一致,以小值为准
        mWidth = Math.min(getMeasuredWidth(), getMeasuredHeight());
        mRadius = mWidth / 2;
        setMeasuredDimension(mWidth, mWidth);
    }


    /**
     * 初始化BitmapShader
     */
    private void setUpShader()
    {
        Drawable drawable = getDrawable();
        if (drawable == null)
        {
            return;
        }

        Bitmap bmp = drawableToBitmap(drawable);
        // 将bmp作为着色器,就是在指定区域内绘制bmp
        bitmapShader = new BitmapShader(bmp, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
        float scale = 1.0f;
            // 拿到bitmap宽或高的小值
        int bSize = Math.min(bmp.getWidth(), bmp.getHeight());
        scale = mWidth * 1.0f / bSize;
        // shader的变换矩阵,我们这里主要用于放大或者缩小
        mMatrix.setScale(scale, scale);
        // 设置变换矩阵
        bitmapShader.setLocalMatrix(mMatrix);
        // 设置shader
        bitmapPaint.setShader(bitmapShader);
    }


    private Bitmap drawableToBitmap(Drawable drawable) {
        if (drawable instanceof BitmapDrawable)
        {
            BitmapDrawable bd = (BitmapDrawable) drawable;
            return bd.getBitmap();
        }
        int w = drawable.getIntrinsicWidth();
        int h = drawable.getIntrinsicHeight();
        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;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (getDrawable() == null) {
            return;
        }
        setUpShader();
        canvas.drawCircle(mRadius, mRadius, mRadius, bitmapPaint);
    }
}

在这里插入图片描述

五 反馈-api学习

说实话,有了清晰的思路之后,问题在于api不熟悉。不知道有什么方法可以做到什么效果。
这里总结一下上面用到的:

  1. setUpShader方法中
    bitmapShader.setLocalMatrix(mMatrix); 设置变化矩阵,能让你对横轴纵轴做缩放。通过mMatrix.setScale(scale, scale);方法。
  2. onMeasure方法中
    mWidth = Math.min(getMeasuredWidth(), getMeasuredHeight());
    setMeasuredDimension方法。他们的含义是什么?文章1 measure
    文章二:setMeasuredDimension决定了当前View的大小。Dimension是尺寸的意思
  3. drawableToBitmap方法中
    drawable.getIntrinsicWidth();参考:获得drawable的宽
    Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); 参考:即创建一个空数组
    new Canvas(bitmap)这就是我们一直以来用的canvas的创建方式了!用位图来绘制,所以传入bitmap
    drawable.setBounds(0, 0, w, h);表示drawable会绘制在(0,0) (w,h)区域内
    drawable.draw(canvas);Drawable就是一个可画的对象,其可能是一张位图(BitmapDrawable),也可能是一个图形(ShapeDrawable),还有可能是一个图层(LayerDrawable)。所以想paint一样可以画

后记

  1. 类似于自定义View注入失败这种报错,不是只和构造函数有关系。
    如果说自定义View里面有比如空指针这样的bug,IDE并不会报错空指针,而是报错注入失败。

  2. 不借鉴别人的,真的不知道有这么些api。不知道有哪些api,就是巧妇难为无米之炊。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值