[Android]【安卓】自定义圆角图片,可在xml中设置任意角是否为圆角

[Android]【安卓】自定义圆角图片,可在xml中设置任意角是否为圆角

本篇博客已收录到我的安卓开发小结中——点击【安卓开发小结】
  • 本篇博客有参考博客【android自定义一圆角ImageView
  • 较原博客,本篇博客有如下改进:
    1、可在xml中设置四个角中的任意一个角是否为圆角。
    2、将px改为dp。
    3、增加原理说明。

修改后代码如下:

1、在values文件夹下,新建一个attrs.xml资源文件。
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="C2RoundAngleImageView">
        <attr name="roundWidth2" format="dimension" />
        <attr name="roundHeight2" format="dimension" />
        <attr name="leftUpCorner" format="boolean" />
        <attr name="rightUpCorner" format="boolean" />
        <attr name="leftDownCorner" format="boolean" />
        <attr name="rightDownCorner" format="boolean" />
    </declare-styleable>
</resources>
2、自定义View。
public class C2RoundAngleImageView extends ImageView {

    private Paint paint;
    private int roundWidth = 10;
    private int roundHeight = 10;
    private boolean rightUpCorner = true;
    private boolean leftUpCorner = true;
    private boolean rightDownCorner = true;
    private boolean leftDownCorner = true;
    private Paint paint2;
    private static Context context;

    public C2RoundAngleImageView(Context context) {
        super(context);
        init(context, null);
    }

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

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

    private void init(Context context, AttributeSet attrs) {
        this.context = context;
        if(attrs != null) {
            //Point1
            TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.C2RoundAngleImageView);
            roundWidth= a.getDimensionPixelSize(R.styleable.C2RoundAngleImageView_roundWidth2, roundWidth);
            roundHeight= a.getDimensionPixelSize(R.styleable.C2RoundAngleImageView_roundHeight2, roundHeight);
            rightUpCorner = a.getBoolean(R.styleable.C2RoundAngleImageView_rightUpCorner,true);
            rightDownCorner = a.getBoolean(R.styleable.C2RoundAngleImageView_rightDownCorner,true);
            leftUpCorner = a.getBoolean(R.styleable.C2RoundAngleImageView_leftUpCorner,true);
            leftDownCorner = a.getBoolean(R.styleable.C2RoundAngleImageView_leftDownCorner,true);
        }else {
            //Point2
            float density = context.getResources().getDisplayMetrics().density;
            roundWidth = (int) (roundWidth*density);
            roundHeight = (int) (roundHeight*density);
        }

        paint = new Paint();
        paint.setColor(Color.WHITE);
        paint.setAntiAlias(true);
        //Point3
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));

        paint2 = new Paint();
        paint2.setXfermode(null);
    }

    @TargetApi(Build.VERSION_CODES.KITKAT)
    @Override
    public void draw(Canvas canvas) {
        //Point4
        Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_4444);
        try {
            Canvas canvas2 = new Canvas(bitmap);
            //Point5
            super.draw(canvas2);
            if(leftUpCorner){
                //Point6
                drawLiftUp(canvas2);
            }
            if(leftDownCorner){
                drawLiftDown(canvas2);
            }
            if(rightUpCorner){
                drawRightUp(canvas2);
            }
            if(rightDownCorner){
                drawRightDown(canvas2);
            }
            //Point7
            canvas.drawBitmap(bitmap, 0, 0, paint2);
            bitmap.recycle();
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }

    private void drawLiftUp(Canvas canvas) {
        Path path = new Path();
        path.moveTo(0, roundHeight);
        path.lineTo(0, 0);
        path.lineTo(roundWidth, 0);
        path.arcTo(new RectF(
                        0,
                        0,
                        roundWidth * 2,
                        roundHeight * 2),
                -90,
                -90);
        path.close();
        canvas.drawPath(path, paint);
    }

    private void drawLiftDown(Canvas canvas) {
        Path path = new Path();
        path.moveTo(0, getHeight()-roundHeight);
        path.lineTo(0, getHeight());
        path.lineTo(roundWidth, getHeight());
        path.arcTo(new RectF(
                        0,
                        getHeight()-roundHeight*2,
                        0+roundWidth*2,
                        getHeight()),
                90,
                90);
        path.close();
        canvas.drawPath(path, paint);
    }

    private void drawRightDown(Canvas canvas) {
        Path path = new Path();
        path.moveTo(getWidth()-roundWidth, getHeight());
        path.lineTo(getWidth(), getHeight());
        path.lineTo(getWidth(), getHeight()-roundHeight);
        path.arcTo(new RectF(
                getWidth()-roundWidth*2,
                getHeight()-roundHeight*2,
                getWidth(),
                getHeight()), 0, 90);
        path.close();
        canvas.drawPath(path, paint);
    }

    private void drawRightUp(Canvas canvas) {
        Path path = new Path();
        path.moveTo(getWidth(), roundHeight);
        path.lineTo(getWidth(), 0);
        path.lineTo(getWidth()-roundWidth, 0);
        path.arcTo(new RectF(
                        getWidth()-roundWidth*2,
                        0,
                        getWidth(),
                        0+roundHeight*2),
                -90,
                90);
        path.close();
        canvas.drawPath(path, paint);
    }

}
  • Point1:在这里接收xml里设置的参数。
  • Point2:在这里将px转化为dp。
  • Point3:设置画笔的Xfermode类型为PorterDuff.Mode.DST_OUT,这种模式可以理解为在不相交的地方绘制源图像
    这里写图片描述
  • Point4:根据canvas的尺寸创建一个可以修改的Bitmap对象。
  • Point5:根据Bitmap对象创建一个canvas2画布,并让本将draw到canvas上的View画到canvas2的bitmap上,可看源码:
    public void draw(Canvas canvas) {
        final int privateFlags = mPrivateFlags;
        final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
                (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
        mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;

        /*
         * Draw traversal performs several drawing steps which must be executed
         * in the appropriate order:
         *
         *      1. Draw the background
         *      2. If necessary, save the canvas' layers to prepare for fading
         *      3. Draw view's content
         *      4. Draw children
         *      5. If necessary, draw the fading edges and restore layers
         *      6. Draw decorations (scrollbars for instance)
         */
         ... ...
         }
  • Point6:在左上角绘制一个待切除的Path闭合路径,并与画布进行Xfermode处理,切出圆角,bitmap的轮廓随着canvas2一同改变。
  • Point7:将切割好圆角的bitmap绘制到要展现的画布canvas上。
    这里写图片描述
3、在xml中使用。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:round="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical">
    <!-- 列表图片 -->
    <com.example.weihy.mygithubproject.C2RoundAngleImageView
        android:id="@+id/c2lamp_recipe_img"
        android:layout_width="300dp"
        android:layout_height="160dp"
        android:scaleType="centerCrop"
        android:src="@drawable/coffee"
        round:leftUpCorner="false"
        round:rightDownCorner="false"
        round:roundHeight2="50dp"
        round:roundWidth2="50dp"
        />
</LinearLayout>
4、效果图。

这里写图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值