美文网首页
cavas画圆形的图片

cavas画圆形的图片

作者: 爱我O就直说 | 来源:发表于2020-02-14 03:50 被阅读0次

2020-02-14
原图:


a.png

效果图: 蓝色背景是我在布局里设置的,为了看居中的效果


yuan.png
  • 注意:canvas的裁切和几何变换都要写在drawXXX()之前,因为先走canvas.drawXXX()的代码,然后会从下往上走。
    canvas.save();与 canvas.restore();可以为一个节点(不知道这样理解对不对,反正这两方法之间的操作不会影响其他操作)
画圆形的图片: 两种方式,效果一样

方式一: 先裁切出一个圆的路径,再drawBitmap。其实代码是先执行画图,再执行的裁切
方式二: 在画圆时 使用Piant的着色器,图片着色器 着色图片

Pian的着色器的使用

代码:

package com.app.yf.myapplication.view.activity.diy;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;

import com.app.yf.myapplication.R;

import androidx.annotation.Nullable;

@SuppressLint("AppCompatCustomView")
public class MyView extends ImageView {
    private static final String TAG = "MyView";
    private Context context;

    // 控件的宽、高
    private int viewWidth, viewHeight;

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

    public MyView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    private void init(Context context) {
        this.context = context;
        // 初始化画笔
        initPaint();
    }

    private Paint mPaint; //画笔/颜料

    private void initPaint() {
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
//        mPaint.setStyle(Paint.Style.STROKE); //设置空心
//        mPaint.setStyle(Paint.Style.FILL); //设置空心
//       mPaint.setStrokeWidth(strokeWidth); //设置笔画宽度
        mPaint.setColor(Color.GRAY); //设置颜色

    }


    /**
     * 根据手机的分辨率从 dp 的单位 转成为 px(像素)
     */
    public static int dip2px(Context context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        Log.i(TAG, "onMeasure: width: " + widthMeasureSpec);
        Log.i(TAG, "onMeasure: height: " + heightMeasureSpec);
        Log.i(TAG, "onMeasure: getWidth: " + getWidth());
        Log.i(TAG, "onMeasure: getheight: " + getHeight());
        Log.i(TAG, "onMeasure: getMeasuredWidth: " + getMeasuredWidth());
        Log.i(TAG, "onMeasure: getMeasuredHeight: " + getMeasuredHeight());

        // 控件的宽、高
        viewWidth = getMeasuredWidth();
        viewHeight = getMeasuredHeight();
    }

    @Override
    protected void onDraw(Canvas canvas) {
//        super.onDraw(canvas);

        //如果是继ImagView,可以这样获取arc设置的Bitmap
        Drawable drawable = getDrawable();
        if (drawable == null || !(drawable instanceof BitmapDrawable)) {
            super.onDraw(canvas);
            return;
        }
        Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
        //这样可以直接取资源里的图片
//        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.a);
        int bitmapWidth = bitmap.getWidth();
        int bitmapHeight = bitmap.getHeight();

        //画椭圆以及圆角时,取图片宽的一面撑到边的比例。控件宽高与图片宽高的比例 取小的比例
//        float scale = Math.min(viewWidth * 1f / bitmapWidth, viewHeight * 1f / bitmapHeight);

        //画正圆以及正方形圆角时。取图片窄的一面撑到边的比例
        float minWidth = Math.min(bitmapWidth, bitmapHeight); //图片最小宽高
        float scale = Math.min(viewWidth * 1f / minWidth, viewHeight * 1f / minWidth);

        //计算移动到控件的中心位置的值
        float translateToCenterX = (viewWidth - bitmapWidth) / 2;
        float translateToCenterY = (viewHeight - bitmapHeight) / 2;


   /**
    * 注意:canvas的裁切和几何变换都要写在drawXXX()之前,因为先走canvas.drawXXX()的代码,然后会从下往上走。
    * canvas.save();与 canvas.restore();可以为一个节点(不知道这样理解对不对)
    */

/**
 * 画圆形的图片:  两种方式
 */
/**
 * 方式一: 先裁切出一个圆的路径,再drawBitmap
 */
        //在做范围裁切或几何变换时 要先保存 save(),再绘制,最后再恢复canvas.restore(),这样才不会影响其他的绘制
        canvas.save();

        //使用矩阵缩放 , Matrix可以实现所有的几何形变
        Matrix matrixx = new Matrix();
        matrixx.postTranslate(translateToCenterX, translateToCenterY);  //移动到控件的中心位置
        matrixx.postScale(scale, scale, viewWidth / 2, viewHeight / 2); //缩放
        canvas.setMatrix(matrixx);//canvas设置矩阵

        //裁切
        Path path = new Path();
        //椭圆,如果图片是正方形,自然就是正圆了
//        path.addOval(0, 0, bitmapWidth, bitmapHeight, Path.Direction.CW);
        //直接正圆
        path.addCircle(bitmapWidth / 2, bitmapHeight / 2, minWidth / 2, Path.Direction.CW);
//        path.addRoundRect(); //用这个方法就是圆角图片了
        canvas.clipPath(path); //按一个路径裁切

        //画图片
//        canvas.drawBitmap(bitmap, matrixx, mPaint); //为啥不用这句,要用下面这句呢?因为我要要裁切,后做几何变换
        canvas.drawBitmap(bitmap, 0, 0, mPaint);

        canvas.restore(); //再恢复canvas


/**
 * 方式二: 在画圆时 使用Piant的着色器,图片着色器 着色图片
 */

      /*  //在做范围裁切或几何变换时 要先保存 save(),再绘制,最后再恢复canvas.restore(),这样才不会影响其他的绘制
        canvas.save();

        //先移动到中心位置,再缩放
        canvas.scale(scale, scale, viewWidth / 2, viewHeight / 2); //canvas缩放
        canvas.translate(translateToCenterX, translateToCenterY);  //移动到控件的中心位置

        //图片着色器 着色图片
        Shader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
        mPaint.setShader(bitmapShader);
        //画圆
        canvas.drawCircle(bitmapWidth / 2, bitmapHeight / 2, minWidth / 2, mPaint);

        mPaint.setShader(null); //清除着色器

        canvas.restore(); //再恢复canvas*/

    }


}

发现了没,按这个套路,也就可以画圆角的,三角的,五角星形的 等等,任何你能画出来的图形

下面我们用方式二画一个爱心裁切出图片的效果:

为什么用方式二? 感觉高级一点

 /**
         * ___________________________________________
         *
         * 使用方式二画一个心形的图片
         */
        canvas.save();

        //先移动到中心位置,再缩放
        canvas.scale(scale, scale, viewWidth / 2, viewHeight / 2); //canvas缩放
        canvas.translate(translateToCenterX, translateToCenterY);  //移动到控件的中心位置

        //先画一个心形路径 (宽高相等,还得在图片中间的位置)
        Path path2 = new Path();
        // 要取的宽高 , 心形的宽高,  图片宽高取小
        float xinWidth = minWidth;
        //左边圆的左边 = X向中心点 - 心形宽 / 2 ;上边 = Y向中心点 - 心形宽 / 2
        float left = bitmapWidth / 2 - xinWidth / 2;
        float top = bitmapHeight / 2 - xinWidth / 2;
        path2.addArc(left, top, bitmapWidth / 2, bitmapHeight / 2, 140, 220);
        //右边圆的右边 = 左边圆的左边 + 心形宽
        path2.arcTo(bitmapWidth / 2, top, left + xinWidth, bitmapHeight / 2, 180, 220, false);
        path2.lineTo(bitmapWidth / 2, top + xinWidth);

        //图片着色器 着色图片
        Shader bitmapShader2 = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
        mPaint.setShader(bitmapShader2);

        canvas.drawPath(path2, mPaint); //画心形图片

        mPaint.setShader(null); //清除着色器

        canvas.restore();

爱心图效果:


xin.png

完事儿

相关文章

网友评论

      本文标题:cavas画圆形的图片

      本文链接:https://www.haomeiwen.com/subject/kegrfhtx.html