Android自定义View_菱形图片

作者: 付十一v | 来源:发表于2019-01-16 20:17 被阅读14次
    自定义菱形图片.png

    前言

    在实际项目中,用户头像,音乐专辑都有可能用到圆形,菱形等无规则图像,需要自己自定义View实现相应的功能。

    思路

    需求:制作圆角菱形的图片
    思路:
    1、绘制出圆角矩形的遮罩层;
    2、将矩形旋转45°;
    3、使用画笔的PorterDuffXfermode的SRC_IN属性;
    4、将图片绘制遮罩层上。

    PorterDuffXfermode

    PorterDuffXfermode在网上有许多讲解它的文章,这里只讲解最常用的两种模式SRC_IN和DST_IN。
    SRC_IN:【本文所用的模式】显示底层图像和上方图像的相交区域,且显示的是上方图像。如图所示,先绘制出黄色的底层图像,再绘制出蓝色的图像,设置的模式为SRC_IN,则显示的是两张图像相交的扇形区域,且为上层蓝色图像。

    Picture.png SRC_IN.png
    DST_IN:显示底层图像和上方图像的相交区域,且显示的是底层图像。如图所示,先绘制出黄色的底层图像,再绘制出蓝色的图像,设置的模式为DST_IN,则显示的是两张图像相交的扇形区域,且为底层黄色图像。
    DST_IN.png

    实现

    1、根据图片的大小绘制出圆角矩形的遮罩层;

    //        创建图片
            mImageBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.picture);
    //        获取图片的宽高
            mWidth = mImageBitmap.getWidth();
            mHeight = mImageBitmap.getHeight();
            mMaskBitmap = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888);
            Canvas maskCanvas = new Canvas(mMaskBitmap);
    
            mPaint = new Paint();
            mPaint.setColor(Color.YELLOW);
            mPaint.setAntiAlias(true);
    //        画布先平移后旋转
            maskCanvas.translate(mWidth / 2, 0);
            maskCanvas.rotate(45);
            int rectSize = (int) (mWidth / 2 / Math.sin(Math.toRadians(45)));
    //        绘制圆角矩形
            maskCanvas.drawRoundRect(0, 0, rectSize, rectSize, 50, 50, mPaint);
    

    2、设置两张图像的显示模式为SRC_IN;

     mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
    

    3、这里需要注意的是因为使用的是同一个画布Canvas,在绘制圆角矩形时已经将画布旋转45°并且平移,这里就需要将画布旋转平移回到初始状态,不然图片就会跟着旋转,就会如下图所示。


    RotatePicture.png
    //        画布先旋转后平移,防止图片也跟着旋转
            maskCanvas.rotate(-45);
            maskCanvas.translate(-mWidth / 2, 0);
    

    4、绘制上层图片

    maskCanvas.drawBitmap(mImageBitmap, 0, 0, mPaint);
    

    5、最后在onDraw方法中绘制出最后的图片;

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

    总结

    设计无规则图形,方法大同小异,可使用PorterDuffXfermode的不同模式实现不同的效果。需要注意的是由于底层和上层的图像都是同一个Canvas绘制,绘制底层时已经改变了方向,后面绘制上层时需要回复到初始状态。另外也可以另写方法创建新的Canvas绘制上层图像,就不必恢复。


    源码

    public class CustomDiamondImage extends View {
        private Paint mPaint;
    
        private int mWidth;
        private int mHeight;
        private Bitmap mMaskBitmap;
        private Bitmap mImageBitmap;
    
        public CustomDiamondImage(Context context) {
            super(context);
        }
    
        public CustomDiamondImage(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            canvas.drawBitmap(getBitmap(), 0, 0, null);
        }
    
        private Bitmap getBitmap() {
    //        创建图片
            mImageBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.picture);
    //        获取图片的宽高
            mWidth = mImageBitmap.getWidth();
            mHeight = mImageBitmap.getHeight();
            mMaskBitmap = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888);
            Canvas maskCanvas = new Canvas(mMaskBitmap);
    
            mPaint = new Paint();
            mPaint.setColor(Color.YELLOW);
            mPaint.setAntiAlias(true);
    //        画布先平移后旋转
            maskCanvas.translate(mWidth / 2, 0);
            maskCanvas.rotate(45);
            int rectSize = (int) (mWidth / 2 / Math.sin(Math.toRadians(45)));
    //        绘制圆角矩形
            maskCanvas.drawRoundRect(0, 0, rectSize, rectSize, 50, 50, mPaint);
    //        设置混合显示模式为SRC_IN
            mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
    //        画布先旋转后平移,防止图片也跟着旋转
            maskCanvas.rotate(-45);
            maskCanvas.translate(-mWidth / 2, 0);
            maskCanvas.drawBitmap(mImageBitmap, 0, 0, mPaint);
    
            return mMaskBitmap;
        }
    }
    

    欢迎关注我的公众号:小猿说,大家一起学习交流。


    公众号

    相关文章

      网友评论

        本文标题:Android自定义View_菱形图片

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