android自定义view-利用Paint 的 Xfermode 把图片撸成各种形状

来源:互联网 发布:停车位软件哪个好 编辑:程序博客网 时间:2024/06/14 21:22

在上一篇文章 Paint 的 Xfermode 的用法 中回顾了下Xfermode的用法,这篇文章我们来实战下,利用它来将图片绘制成各种形状。
先来一张效果图
这里写图片描述

实现原理:

  1. 创建一个抽象类继承ImageView重写ondraw()方法
  2. 将图片以centerCrop方式显示,
  3. 绘制要显示成的图形
  4. 设置图像混合模式
public abstract class GeometryImageView extends AppCompatImageView {    protected Paint mPaint = new Paint();    public GeometryImageView(Context context) {        super(context);    }    public GeometryImageView(Context context, AttributeSet attrs) {        super(context, attrs);    }    public GeometryImageView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);    }    @Override    protected void onDraw(Canvas canvas) {        Drawable drawable = getDrawable();        if (drawable != null) {            //设置离屏缓冲            int saveLayer = canvas.saveLayer(null, null, Canvas.ALL_SAVE_FLAG);            Bitmap bitmap = getDstBitmap(drawable);            canvas.drawBitmap(bitmap, 0, 0, mPaint);            mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));            Bitmap maskBitamp = getMaskBitamp();            canvas.drawBitmap(maskBitamp, 0, 0, mPaint);            mPaint.setXfermode(null);            canvas.restoreToCount(saveLayer);        }    }    /**     * 将设置的图片以centerCrop方式显示     * @param drawable     * @return     */    @NonNull    private Bitmap getDstBitmap(Drawable drawable) {        Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);        Canvas _canvas = new Canvas(bitmap);        //        final int dwidth = drawable.getIntrinsicWidth();        final int dheight = drawable.getIntrinsicHeight();        final int vwidth = getWidth();        final int vheight = getHeight();        Matrix mDrawMatrix = new Matrix();        float scale;        float dx = 0, dy = 0;        if (dwidth * vheight > vwidth * dheight) {            scale = (float) vheight / (float) dheight;            dx = (vwidth - dwidth * scale) * 0.5f;        } else {            scale = (float) vwidth / (float) dwidth;            dy = (vheight - dheight * scale) * 0.5f;        }        mDrawMatrix.setScale(scale, scale);        mDrawMatrix.postTranslate(Math.round(dx), Math.round(dy));        _canvas.concat(mDrawMatrix);        drawable.draw(_canvas);        return bitmap;    }    /**     * 图形,由子类实现,方便扩展     * @return     */    public abstract Bitmap getMaskBitamp();}

然后来一个实现:

public class EquilateralPolygonImageView extends GeometryImageView {    private int n;    public void setN(int n) {        this.n = n;    }    public EquilateralPolygonImageView(Context context) {        this(context, null);    }    public EquilateralPolygonImageView(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public EquilateralPolygonImageView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        final TypedArray a = context.obtainStyledAttributes(                attrs, R.styleable.EquilateralPolygonImageView);        int aInteger = a.getInteger(R.styleable.EquilateralPolygonImageView_N, 0);        setN(aInteger);    }    @Override    public Bitmap getMaskBitamp() {        Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(),                Bitmap.Config.ARGB_8888);        Canvas canvas = new Canvas(bitmap);        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);        drawPolygon(new RectF(0, 0, getWidth(), getHeight()), canvas, paint, n);        return bitmap;    }    /**     * @param rect     * @param canvas     * @param paintByLevel     * @param number     */    public void drawPolygon(RectF rect, Canvas canvas, Paint paintByLevel, int number) {        if (number < 3) {            return;        }        float r = (rect.right - rect.left) / 2;        float mX = (rect.right + rect.left) / 2;        float my = (rect.top + rect.bottom) / 2;        Path path = new Path();        for (int i = 0; i <= number; i++) {            // - 0.5 : Turn 90 ° counterclockwise            float alpha = Double.valueOf(((2f / number) * i - 0.5) * Math.PI).floatValue();            float nextX = mX + Double.valueOf(r * Math.cos(alpha)).floatValue();            float nextY = my + Double.valueOf(r * Math.sin(alpha)).floatValue();            if (i == 0) {                path.moveTo(nextX, nextY);            } else {                path.lineTo(nextX, nextY);            }        }        canvas.drawPath(path, paintByLevel);    }}

在布局文件中使用:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical"    android:padding="16dp"    tools:context="com.zomll.myapplication.MainActivity">    <com.zomll.geometryimageview.EquilateralPolygonImageView        android:layout_width="100dp"        android:layout_height="100dp"        app:N="3"        android:layout_marginTop="10dp"        android:src="@mipmap/a" />    <com.zomll.geometryimageview.EquilateralPolygonImageView        android:layout_width="100dp"        android:layout_height="100dp"        app:N="4"        android:layout_marginTop="10dp"        android:src="@mipmap/a" />    <com.zomll.geometryimageview.EquilateralPolygonImageView        android:layout_width="100dp"        android:layout_height="100dp"        app:N="5"        android:layout_marginTop="10dp"        android:src="@mipmap/a" />    <com.zomll.geometryimageview.EquilateralPolygonImageView        android:layout_width="100dp"        android:layout_height="100dp"        app:N="6"        android:layout_marginTop="10dp"        android:src="@mipmap/a" /></LinearLayout>

全部的代码在:https://github.com/zomll/EquilateralPolygonImageView

原创粉丝点击