自定义View--圆形头像(用PorterDuff.Mode)

本文介绍了如何使用PorterDuff.Mode中的SRC_IN模式创建圆形头像效果。通过在onDraw()中初始化并画出圆形,然后设置mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)),实现了将头像图片裁剪为圆形。在实践中发现,onMeasure()的多次执行可能导致问题,而将相关操作放在onDraw()中可以得到预期效果。此外,文章讨论了PorterDuff.Mode的不同参数如何影响最终效果,并提醒读者在实际应用中,SRC和DST的大小及位置关系会影响最终显示结果,需要根据具体情况调整。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

效果图:


自定义view--刮刮卡类似的是,都是使用PorterDuff.Mode来实现效果,不同的是这次使用的是SRC_IN

代码:

该例子中,SRC是那张头像图片,DST就是画的圆形,先画圆形,再设置mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));


public class GuaThree extends View {
    private Paint mPaint;//绘制mPath的画笔
    private Canvas mCanvas;
    private Bitmap mBitmap;
    private Bitmap src;
    int width ;
    int height ;
    int min;//画圆的半径
    public GuaThree(Context context) {
        this(context, null);
    }

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

    public GuaThree(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //获得控件的宽高
        width = getMeasuredWidth();
        height = getMeasuredHeight();
        min = Math.min(width, height);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        drawMyCanvas();
        canvas.drawBitmap(mBitmap, 0, 0, null);
    }

    private void drawMyCanvas(){
        //初始化bitmap
        mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        mCanvas = new Canvas(mBitmap);//用指定的位图构造一个画布来绘制。
        mCanvas.drawCircle(width / 2, height / 2, min / 2 - 20, mPaint);
        mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        mCanvas.drawBitmap(src, 0, 0, mPaint);
    }

    /**
     * 初始化信息
     */
    private void init() {
        // 禁止硬件加速,硬件加速会有一些问题,这里禁用掉
       setLayerType(LAYER_TYPE_SOFTWARE, null);
        mPaint = new Paint();
        src = BitmapFactory.decodeResource(getResources(),
                R.drawable.tou);
    }
}

我在上一篇文章中写刮刮卡的时候,临时画布mCanvas就是在onMeasure里面初始化并画相关的东西,但是在这个例子中,就出不来效果,参考的网友的代码,把mCanvas相关的操作放在onDraw()里面,就可以出来效果了,很神奇。有待后面研究。现在能想到的就是onMeasure会反复的执行,可能多次执行会引起很多问题吧。


题外话:

在自定义view--刮刮卡的基础上,本来实现篇文章的效果是很容易了,不就改个参数吗?可是我遇到的好多问题。

我直接在上一篇文章的基础上改属性,出不来效果,而且下面这图上的每个参数我都试了试,将近一半的参数与图上的效果不对应,百度了很多文章,也没有找到解决问题的关键,特别让自己很无语的是,有一部分能出来,一部分不能出来,比如Dst,DsrOver,DstOut,Xor和最下面一排都没有问题,剩下的很多都出不来效果,记不清楚是哪些了。

我疑问,按照图上的效果图,我之前的做法是,把头像图片当作Dst,绘制完了之后再设置画笔DstIn,之后再绘制圆形当作Src,这样是应该呈现出两则交汇(即所要的圆形头像部分)的地方显示,其他不显示。理论上是可以的啊,可是怎么都出不来。

然后找大神帮忙,大神看了许久,给了我一篇文章,该文章说上面的图是有问题的,具体看文章内容,他说他测量的效果图:


我看了之后,按照该作者的代码测试,的确和他给出的上图效果一模一样。

不过在我们的实际运用中,我们会觉得他们的图都有问题,我想原因应该是你选用的Src和Dst的大小的位置关系不同,你想象的效果也就有所不同。

比如:

以下是Clear参数值的效果图,两种情况都是没有错误的,当SRC很大而且位置刚好盖过DST的时候,那么效果图就是左边这个,如果两者只是相交一点点,那么效果图就是右边这个(绿色部分为背景颜色,即最外层布局,便于观看效果)



以下是Src参数值效果图,也是和上面一样的理解,如果蓝色框框太大就会覆盖掉黄色圆,这时候效果图就是左边,否则就是右边。


剩下的就不分析了,总的来说就是自己选择的SRC和DST大小和相对位置不同,效果和官网上的图会有所差别,不用一概而论,就像要那样的效果,所以,自己用的时候还是得动动脑袋。









评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值