Android 圆角imageview与lin15开发记录总结

写lin16的时候,遇到个特殊的需求,要一个圆角view放图,使得图也是圆角,而且最关键的是,还得支持自由改变高度而图片不会变形。

之前写过一篇这样的博客,就是lin15时的特殊需求,在这里也一样,只是需要圆角。

一开始找了很多的方案,什么用path画圆角,还有用Xfermode重叠剪掉,以及Android自带的BitmapShader。

但是第一个方案不支持锯齿处理,剪出来的图圆角处其实是有着非常明显的锯齿,很不美观,而且由于动态的高度也导致其无法快速处理。

第三种方案也一样,另外确实也不好处理,最后选择了第二种。

在lin16上,我是这样解决的

            int sc = canvas.saveLayer(0, 0, width, limitHeight, null);
            //画源图像,为一个圆角矩形
            canvas.drawRoundRect(new RectF(0, 0, width, limitHeight), radius, radius, paint);
            //设置混合模式
            paint.setXfermode(xfermode);
            //画目标图像
            canvas.drawBitmap(drawableToBitamp(getDrawable()), 0, 0, paint);
            // 还原混合模式
            paint.setXfermode(null);
            canvas.restoreToCount(sc);

其中limitHeight就是动态的高度,从外部不断改变这个高度达到改变图片显示的目的。

我本以为这样也可以给lin15加上圆角,毕竟之前也有用户反馈希望添加圆角。

但情况远没有我想的那么简单,今天在给lin15做圆角的时候,发现在lin16的方案在这里并不适用,因为lin16的圆角方案是一刀切,直接弄了一个圆角矩形,而lin15的圆角是底部两个角是圆角,上面两个角还是正常的直角。

这种样子可不能单单给两个角弄成圆角,而剩下的两个角不变,思来想去,还是在lin15上改变了方案。

当时我的方案如下


            Bitmap bitmapFrame = makeRoundRectFrame(width, limitHeight);

            int sc = canvas.saveLayer(0, 0, width, limitHeight, null, Canvas.ALL_SAVE_FLAG);

            canvas.drawBitmap(bitmapFrame, 0, 0, paint);
            // 利用Xfermode取交集(利用bitmapFrame作为画框来裁剪bitmapOriginal)
            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
            canvas.drawBitmap(drawableToBitamp(getDrawable()), 0, 0, paint);

            paint.setXfermode(null);
            canvas.restoreToCount(sc);

当然也是从网上获得的方案,大致也能实现相关功能,而且在makeRoundRectFrame里对圆角做了处理,如下

        private Bitmap makeRoundRectFrame(int w, int h) {
        Bitmap bm = Bitmap.createBitmap(w, h, Bitmap.Config.RGB_565);
        Canvas c = new Canvas(bm);
        Path path = new Path();
        path.addRoundRect(new RectF(0, 0, w, h), radiusArray, Path.Direction.CW);
        Paint bitmapPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        bitmapPaint.setColor(Color.GREEN); // 颜色随意,不要有透明度。
        c.drawPath(path, bitmapPaint);

        XposedBridge.log("lin16---->>>"+bm.getByteCount());

        return bm;
    }

但是,but,这并不是我想要的,在我4C炸弹上测试的时候我发现开启圆角功能后,下拉变得更加卡顿了,于是就想优化一下这代码,仔细一看才发现这两断代码竟绘制了两个bitmap,而且从输出的日志来看,这bitmap大得惊人,这用久了不oom才怪,吓得我赶紧改代码,重新找别的方案代替。

只可惜这期间找了很多方案,比如path,我甚至都想舍弃防锯齿来达到目的了,只可惜path方案并不能实现,幸好不能实现,不然现在可就用着一个不咋地的方案了。

最后兜兜转转还是回到了最初的lin16方案,因为在网上无意间看到的,出处在这里 Android圆角图片和圆形图片实现总结,里面提到了如何使用这个方案达到两个角是圆角,而剩下两个角还是直角。

最后的解决方案如下:

            int sc = canvas.saveLayer(0, 0, width, limitHeight, null);
            //画源图像,为一个圆角矩形
            canvas.drawRoundRect(new RectF(0, 0, width, limitHeight), radius, radius, paint);

            // 利用画笔绘制顶部上面直角部分,关键代码
            canvas.drawRect(new RectF(0, 0, width, limitHeight - radius), paint);

            //设置混合模式
            paint.setXfermode(xfermode);
            //画目标图像
            canvas.drawBitmap(drawableToBitamp(getDrawable()), 0, 0, paint);
            // 还原混合模式
            paint.setXfermode(null);
            canvas.restoreToCount(sc);

只多加了一行代码,就搞定了这个问题,累死我了。

lin15的开发真的要结束了,我也分出了一个分支名为lin15,之后lin15就是这条分支了,master分支将在合并lin15分支后不再更新。

alt

lin15,这是我第一个XP模块,当初用lineageOS15的时候,就想让快速设置面板能放点图片美化一下,于是lin15应运而生,丢到酷安后也引来了很多人的反馈,甚至在GitHub上都有歪果仁找我,希望能够出一个英文版的。

期间发生过很多事,但都不及一开始的时候阅读源码让我头疼,可最让我头疼的事情,也让我收获最多,阅读源码的日子里,痛并快乐着,很多不理解的东西现在都能一目了然了,这项技能,也只有通过之后才能掌握。

lin15后,lin16也诞生了,因为有过前车之鉴,lin16的开发并没有什么太大的困难,顺利完成初版后,似乎也没有什么想要添加的功能的。

我的寒假计划其实除了lin16外,还有我的毕设,结果现在假期末了都还没开始设计,感觉要凉啊。

有缘再见

暂无评论
发表新评论