Android实现自定义圆形ImageView

要实现圆形的ImageView,有一个重要的类:PorterDuffXfermode。PorterDuffXfermode 这是一个非常强大的转换模式,使用它,可以使用图像合成的16条Porter-Duff规则的任意一条来控制Paint如何与已有的Canvas图像进行交互。该类的用法如下:

//创建PorterDuffXfermode
PorterDuffXfermode mode=new PorterDuffXfermode(PorterDuff.Mode.DST_IN);
//设置mode画笔风格
paintnew.setXfermode(mode);

那么这样设置画笔有什么效果呢?可以看看google的效果图:


一共有16种属性可以选择:

1.PorterDuff.Mode.CLEAR
所绘制不会提交到画布上。
2.PorterDuff.Mode.SRC
显示上层绘制图片
3.PorterDuff.Mode.DST
显示下层绘制图片
4.PorterDuff.Mode.SRC_OVER
正常绘制显示,上下层绘制叠盖。
5.PorterDuff.Mode.DST_OVER
上下层都显示。下层居上显示。
6.PorterDuff.Mode.SRC_IN
取两层绘制交集。显示上层。
7.PorterDuff.Mode.DST_IN
取两层绘制交集。显示下层。
8.PorterDuff.Mode.SRC_OUT
取上层绘制非交集部分。
9.PorterDuff.Mode.DST_OUT
取下层绘制非交集部分。
10.PorterDuff.Mode.SRC_ATOP
取下层非交集部分与上层交集部分
11.PorterDuff.Mode.DST_ATOP
取上层非交集部分与下层交集部分
12.PorterDuff.Mode.XOR
异或:去除两图层交集部分
13.PorterDuff.Mode.DARKEN
取两图层全部区域,交集部分颜色加深
14.PorterDuff.Mode.LIGHTEN
取两图层全部,点亮交集部分颜色
15.PorterDuff.Mode.MULTIPLY
取两图层交集部分叠加后颜色
16.PorterDuff.Mode.SCREEN
取两图层全部区域,交集部分变为透明色

简单的解释一下:

首先看上面的16副图中的第二幅和第三幅图,里面都是一幅图片,Src代表原图,是一个正方形,Dst代表目的图,是一个圆形。
下面接着看第四幅图,SrcOver模式,你会发现正方形放在了圆形的上面,并且正方形显示完全,圆形被正方形覆盖了一部分。这就是SrcOver模式的效果。
下面再看第五幅图,PorterDuff.Mode.DST_OVER,你会发现圆形放在了正方形的上面,圆形显示完全,正方形被覆盖了,这就是这种模式达到的效果。

也就是说上面的PorterDuffXfermode 类完成的效果,应该是两幅图或者说两个位图完成的效果。

下面我们就有了画圆形图头像的思路了。
利用的就是上面的PorterDuff.Mode.SRC_IN或者是PorterDuff.Mode.DST_IN这两种模式达到的效果。

 首先说说PorterDuff.Mode.SRC_IN这种模式的思路:
我们可以把正方形的部分设置我们要显示的头像图片,把圆形部分设置为我们的圆形的位图,并且这两个图都居中显示,这样达到的效果就是圆形头像图片的效果!!

再说说PorterDuff.Mode.DST_IN这种模式的思路:
这个模式下,我们把圆形图设置为我们想要显示的头像图片,把正方形设置为圆形的位图,并且这两个图都居中显示,这样达到的效果就是圆形头像的效果。

下面给出两种模式下的代码。首先给出PorterDuff.Mode.SRC_IN模式下的代码:

package org.hunter.a361camera.widget;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.graphics.Xfermode;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.ImageView;

public class PorterDuffViewImageView extends ImageView {
    private Paint mpaint;
    private static Xfermode xfermode;
    private Bitmap mbitmap;
    private Bitmap moutbitmap;

    public PorterDuffViewImageView(Context context) {
        super(context);
        init();
    }

    public PorterDuffViewImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public PorterDuffViewImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        setLayerType(LAYER_TYPE_SOFTWARE, null);
        xfermode = new PorterDuffXfermode(PorterDuff.Mode.DST_IN);
        mpaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int width = getWidth();
        int height = getHeight();
        Bitmap.Config config = Bitmap.Config.ARGB_8888;
        Canvas canvas1 = null;
        BitmapDrawable drawable = (BitmapDrawable) getDrawable();
        // If image is not set, return
        if (drawable == null) {
            return;
        }
        mbitmap = drawable.getBitmap();
        //以后的绘制都将显示在moutbitmap上面
        moutbitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Log.d("图片信息", mbitmap.getWidth() + "高" + mbitmap.getHeight());
        Canvas canvas_outbitmap = new Canvas(moutbitmap);

        //Dst
        canvas_outbitmap.drawCircle(width / 2, height / 2, width / 2, mpaint);
        PorterDuffXfermode mode = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);
        mpaint.setXfermode(mode);
        //Src
        mbitmap = Bitmap.createScaledBitmap(mbitmap, width, height, false);
        canvas_outbitmap.drawBitmap(mbitmap, 0, 0, mpaint);
        canvas.drawBitmap(moutbitmap, 0, 0, mpaint);
    }

}
布局文件:

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="match_parent">

    <org.hunter.a361camera.widget.PorterDuffViewImageView
        android:id="@+id/capture"
        android:layout_width="90dp"
        android:layout_height="90dp"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="20dp"
        android:src="@mipmap/capture"/>

    <org.hunter.a361camera.widget.PorterDuffViewImageView
        android:id="@+id/iv_show_camera2"
        android:layout_width="80dp"
        android:layout_height="80dp"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:layout_marginBottom="20dp"
        android:layout_marginRight="20dp"
        android:scaleType="centerCrop" />
</RelativeLayout>

第二种方式,PorterDuff.Mode.DST_IN :

package org.hunter.a361camera.widget;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.graphics.Xfermode;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.ImageView;

public class PorterDuffViewImageView extends ImageView {
    private Paint mpaint;
    private static Xfermode xfermode;
    private Bitmap bitmap;
    private RectF rect;

    public PorterDuffViewImageView(Context context) {
        super(context);
        init();
    }

    public PorterDuffViewImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public PorterDuffViewImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        setLayerType(LAYER_TYPE_SOFTWARE, null);
        xfermode = new PorterDuffXfermode(PorterDuff.Mode.DST_IN);
        mpaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int width = getWidth();
        int height = getHeight();
        Bitmap.Config config = Bitmap.Config.ARGB_8888;
        Canvas canvas1 = null;
        BitmapDrawable drawable = (BitmapDrawable) getDrawable();
        // If image is not set, return
        if (drawable == null) {
            return;
        }
        drawable.setBounds(0, 0, width, height);
        drawable.draw(canvas);
        if (bitmap == null){
            Log.i("porterduffviewimage","bitmap==null");
            Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
            rect = new RectF(0,0,width,height);
            bitmap = Bitmap.createBitmap(width, height, config);
            canvas1 = new Canvas(bitmap);
            canvas1.drawOval(rect, paint);
        }
        mpaint.setXfermode(xfermode);
        canvas.drawBitmap(bitmap,0,0,mpaint);
    }

}

布局文件同上。

源码参考:https://github.com/gengqifu/361Camera/blob/master/361camera/src/main/java/org/hunter/a361camera/widget/PorterDuffImageView.java

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值