美文网首页Android 自定义view
android 圆角处理(极简)

android 圆角处理(极简)

作者: kingple | 来源:发表于2018-06-08 15:47 被阅读509次

    前言

    • 在开发应用的过程中经常会把图片进行圆角展示,相信大家都有各自的解决方案

    常用的解决方案

    • 把要显示的图片裁剪成圆形图片,然后展示。
    • 使用一张中间镂空的图片盖在原有图片上方。
    • 重写ImageView 的onDraw方法,取到需要绘制的drawable转化为Bitmap 使用BitmapShader 绘制成圆角
      以上三种方案我在之前开发中都有用过,我最倾向于第三种,这种方法灵活,使用起来也比较简单。

    由BitmapShade得到的启发

    既然BitmapShade可以做到圆角处理那么Xfermode根据绘制图像的不同叠加显示形式应该也能做到圆角
    接下来我就进行了一些列的尝试

    继承ImageView重写onDraw

    public class MyImage extends ImageView {
    
    • 初始化画笔,设置图片绘制叠加方式PorterDuff.Mode.DST_IN,点击view切换PorterDuff.Mode
       private void initPaint(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
           if (paint == null) {
                paint = new Paint();
                paint.setAntiAlias(true);
                paint.setColor(Color.BLACK);
                paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
                setOnClickListener(new OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        if (i > modes.length - 1) i = 0;
                        paint.setXfermode(new PorterDuffXfermode(modes[i]));
                        I++;
                        invalidate();
                    }
                });
            }
        }
    
    • 重写onDraw,利用saveLayer使PorterDuff.Mode生效,把后面绘制的圆角矩形和imageView自身绘制叠加
        @Override
        protected void onDraw(Canvas canvas) {
            int count = canvas.saveLayer(0, 0, canvas.getWidth(), canvas.getHeight(), null, Canvas.ALL_SAVE_FLAG);
            super.onDraw(canvas);
            canvas.drawRoundRect(new RectF(getPaddingLeft(), getPaddingTop(), getWidth() - getPaddingRight(), getHeight() - getPaddingBottom()),
                    cornerRadius, cornerRadius, paint);
            canvas.restoreToCount(count);
        }
    

    上面的方案经过我的尝试是可以产生一些叠加效果的,但是始终没有显示出圆角图片,我甚至循环把每个PorterDuff.Mode都试了一遍,从上面代码可以看出每点击一次我会换一个Model ,最终也没能得到理想效果,我也没找到具体问题出在哪了,如果有哪位老铁清楚可以告知一二

    换一个姿势

    虽然上面的尝试没有成功,但是我仍觉得有戏,是不是换一种方式就能成功?
    查看了canvas相关的绘制方法找到了canvas.drawPath是不是用他就能达到目的?
    虽然我不太明白canvas.drawPath和canvas.drawRoundRect在绘制的过程中有什么内在的区别。
    不多说开始尝试

    public class MyImage extends ImageView {
    
    • 初始化画笔和Path设置绘制叠加模式
      private void init(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
            if (paint == null) {
                paint = new Paint();
                mClipPath = new Path();
                paint.setAntiAlias(true);
                paint.setColor(Color.YELLOW);
                paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
            }
        }
    
    
    • 当view改变大小后重新设置一些参数,主要优化性能,其实可以全部放到onDraw中。
     @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            super.onSizeChanged(w, h, oldw, oldh);
            layer = new RectF(0, 0, w, h);
            RectF pathRect = new RectF(getPaddingLeft(), getPaddingTop(), getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
            mClipPath.reset();
            mClipPath.addRoundRect(pathRect, cornerRadius, cornerRadius, Path.Direction.CW);
        }
    
    • 绘制path
      @Override
        protected void onDraw(Canvas canvas) {
            int count = canvas.saveLayer(layer, null, Canvas.ALL_SAVE_FLAG);
            super.onDraw(canvas);
            canvas.drawPath(mClipPath, paint);
            canvas.restoreToCount(count);
        }
    

    居然成功了!无图无真相?

    public class MyImage extends ImageView {
    
    以蓝色填充ImageView
    <com.xxx.xxx.xxx.MyImage
            android:layout_centerInParent="true"
            android:src="@color/colorPrimaryDark"
            android:scaleType="centerCrop"
            android:layout_width="100dp"
            android:layout_height="300dp" />
    
    QQ20180608-153432@2x.png

    附上完整代码

    package com.example.zhaoqingpu.testandroid;
    
    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.Path;
    import android.graphics.PorterDuff;
    import android.graphics.PorterDuffXfermode;
    import android.graphics.RectF;
    import android.support.annotation.Nullable;
    import android.util.AttributeSet;
    import android.widget.ImageView;
    
    public class MyImage extends ImageView {
        private Paint paint;
        private int cornerRadius = 100;
        private RectF layer;  //内容区域
        public Path mClipPath;// 剪裁区域路径
    
        public MyImage(Context context) {
            super(context);
            init(context, null, 0);
        }
    
        public MyImage(Context context, @Nullable AttributeSet attrs) {
            super(context, attrs);
            init(context, attrs, 0);
        }
    
        public MyImage(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init(context, attrs, defStyleAttr);
        }
    
        private void init(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
            if (paint == null) {
                paint = new Paint();
                mClipPath = new Path();
                paint.setAntiAlias(true);
                paint.setColor(Color.YELLOW);
                paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
            }
        }
    
        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            super.onSizeChanged(w, h, oldw, oldh);
            layer = new RectF(0, 0, w, h);
            RectF pathRect = new RectF(getPaddingLeft(), getPaddingTop(), getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
            mClipPath.reset();
            mClipPath.addRoundRect(pathRect, cornerRadius, cornerRadius, Path.Direction.CW);
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            int count = canvas.saveLayer(layer, null, Canvas.ALL_SAVE_FLAG);
            super.onDraw(canvas);
            canvas.drawPath(mClipPath, paint);
            canvas.restoreToCount(count);
        }
    }
    

    至此结束,谢谢!

    相关文章

      网友评论

        本文标题:android 圆角处理(极简)

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