ECornerImageView——椭圆角ImageView

前段时间学习了一下自定义View,再加上最近需要一个圆角ImageView就翻了翻CSDN,就这么给我翻到了一篇(来源见末尾),看了看觉得蛮简单的就在其基础上做了点修改,然后占为己有了!

思路

1.继承AppCompatImageView(不知道为什么无法继承ImageView,但无大碍)。
2.用Bitmap绘图。
3.在ImageView的四角绘制遮罩。

效果

圆角ImageView

椭圆角ImageView

选择性椭圆角ImageView

代码

一、初始化

1.获取自定义属性参数值
在values文件夹下创建attr.xml,在里面设置自定义属性

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="ECornerImageView">
        <attr name="cornerWidth" format="dimension" />
        <attr name="cornerHeight" format="dimension" />
        <attr name="cornerRadius" format="dimension" />
    </declare-styleable>
</resources>

获取自定义属性

if (attrs != null) {
            TypedArray a = context.obtainStyledAttributes
                           (attrs, R.styleable.ECornerImageView);
            cornerWidth = a.getDimensionPixelSize
                           (R.styleable.ECornerImageView_cornerWidth, cornerWidth);
            cornerHeight = a.getDimensionPixelSize
                           (R.styleable.ECornerImageView_cornerHeight, cornerHeight);
            Log.d(TAG,"cornerWidth:"+cornerWidth);
            Log.d(TAG,"cornerHeight:"+cornerHeight);
            cornerRadius = a.getDimensionPixelSize
                           (R.styleable.ECornerImageView_cornerRadius, cornerRadius);
            Log.d(TAG,"cornerRadius:"+cornerRadius);
            if (cornerRadius!=-1){
                cornerHeight = cornerRadius;
                cornerWidth = cornerRadius;
            }
            Log.d(TAG,"cornerWidth2:"+cornerWidth);
            Log.d(TAG,"cornerHeight2:"+cornerHeight);
            //回收
            a.recycle();
        } else {
            cornerWidth = CORNERWIDTH;
            cornerHeight = CORNERHEIGHT;
        }

2.Path和Paint

path = new Path();

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

        bitPaint = new Paint();

二、绘制

public void draw(Canvas canvas) {
        /*绘制图片
          界面显示图片时,需要的内存空间是按像素点的多少乘以每个像素点占用的空间大小来
          计算的。
        * Bitmap.Config ARGB_8888:每个像素占四位,即A=8,R=8,G=8,B=8,那么一个
          像素点占8+8+8+8=32位*/
        Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(),
                                                   Bitmap.Config.ARGB_8888);
        Canvas cornerCanvas = new Canvas(bitmap);
        super.draw(cornerCanvas);

        /*绘制圆角遮罩*/
        if (leftTop){
            drawLeftTop(cornerCanvas);
        }
        if (lefBottom){
            drawLeftBottom(cornerCanvas);
        }
        if (rightTop){
            drawRightTop(cornerCanvas);
        }
        if (rightBottom){
            drawRightBottom(cornerCanvas);
        }

        canvas.drawBitmap(bitmap, 0, 0, bitPaint);
        //bitPaint.setXfermode(null);

        /*在Android应用里,最耗费内存的就是图片资源。而且在Android系统中,读取位图Bitmap时,
          分给虚拟机中的图片的堆栈大小只有8M,如果超出了,就会出现OutOfMemory异常。*/
        if(bitmap != null && !bitmap.isRecycled()){

            // 回收bitmap并且置为null
            bitmap.recycle();
            bitmap = null;

        }
        /*通知垃圾回收器尽快进行回收*/
        System.gc();
    }

三、边角的遮罩绘制

用path绘制遮罩,先画竖线,再画横线,最后画椭圆形的弧线。如图红线所示。


遮罩
    /*绘制左上角圆角遮罩*/
    private void drawLeftTop(Canvas canvas) {
        /*绘制横竖两条直线*/
        path.moveTo(0, cornerHeight);
        path.lineTo(0, 0);
        path.lineTo(cornerWidth, 0);
        /*绘制椭圆的弧线*/
        path.arcTo(new RectF(0, 0, cornerWidth * 2, cornerHeight * 2), -90, -90);
        path.close();
        canvas.drawPath(path, cornerPaint);
    }

    /*绘制左下角圆角遮罩*/
    private void drawLeftBottom(Canvas canvas) {
        /*绘制横竖两条直线*/
        path.moveTo(0, getHeight() - cornerHeight);
        path.lineTo(0, getHeight());
        path.lineTo(cornerWidth, getHeight());
        /*绘制椭圆的弧线*/
        path.arcTo(new RectF(0, getHeight() - cornerHeight * 2, cornerWidth * 2, getHeight()), 90, 90);
        path.close();
        canvas.drawPath(path, cornerPaint);
    }

    /*绘制右上角圆角遮罩*/
    private void drawRightBottom(Canvas canvas) {
        /*绘制横竖两条直线*/
        path.moveTo(getWidth() - cornerWidth, getHeight());
        path.lineTo(getWidth(), getHeight());
        path.lineTo(getWidth(), getHeight() - cornerHeight);
        /*绘制椭圆的弧线*/
        path.arcTo(new RectF(getWidth() - cornerWidth * 2, getHeight() - cornerHeight * 2, getWidth(), getHeight()), -0, 90);
        path.close();
        canvas.drawPath(path, cornerPaint);
    }

    /*绘制右下角圆角遮罩*/
    private void drawRightTop(Canvas canvas) {
        /*绘制横竖两条直线*/
        path.moveTo(getWidth(), cornerHeight);
        path.lineTo(getWidth(), 0);
        path.lineTo(getWidth() - cornerWidth, 0);
        /*绘制椭圆的弧线*/
        path.arcTo(new RectF(getWidth() - cornerWidth * 2, 0, getWidth(), 0 + cornerHeight * 2), -90, 90);
        path.close();
        canvas.drawPath(path, cornerPaint);
    }

使用

1.依赖

allprojects {
        repositories {
            ...
            maven { url 'https://www.jitpack.io' }
        }
    }
dependencies {
        implementation 'com.github.Mils-liu:ECornerImageView:v1.0.0'
}

2.布局
cornerRadius为边角的半径,会覆盖cornerHeight和cornerWidth的值


image.png

3.动态设置

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        eImg = (ECornerImageView)findViewById(R.id.eimg);
        //设置哪个角为椭圆角,分别为左上,左下,右上,右下
        eImg.setCorner(false,true,true,false);
        //设置圆角半径,单位为dp,会覆盖椭圆角的宽高
        eImg.setRadius(40);
        //设置椭圆角的高,单位为dp
        eImg.setcornerHeight(40);
        //设置椭圆角的宽,单位为dp
        eImg.setcornerWidth(80);
    }

END

github地址:https://github.com/Mils-liu/ECornerImageView

来源:《android imageview 设置圆角》
链接:https://blog.csdn.net/why_111/article/details/80720043

来源:《android中path的arcTo方法的使用》
链接:https://blog.csdn.net/whyrjj3/article/details/7940385

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,723评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,080评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,604评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,440评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,431评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,499评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,893评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,541评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,751评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,547评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,619评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,320评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,890评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,896评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,137评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,796评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,335评论 2 342

推荐阅读更多精彩内容

  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,081评论 1 32
  • 1 CALayer IOS SDK详解之CALayer(一) http://doc.okbase.net/Hell...
    Kevin_Junbaozi阅读 5,118评论 3 23
  • 与封闭式基金相对应的就是开放式基金,随时可以买卖,而随着买卖,基金的资产和规模也相应扩大或减少。可分为三种类...
    cdgh阅读 323评论 0 1
  • Sublime text 3 第一步 第二步 注意 安装插件,Ctrl + Shift +P 打开命令面板,lis...
    Louis_Duan阅读 1,403评论 0 0
  • 2018.5.11,星期五,天气:晴 最美的风景,是回家的路,按照之前的安排,通勤车今天来接我们回家。 ...
    淡然5778阅读 310评论 0 2