autojs画圆润的圆角矩形

690 阅读4分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第7天,点击查看活动详情 >>

牙叔教程 简单易懂

问题

以cardView为例

我们放大四个角看看

左上角

右上角

仔细看可以看到, 直线与圆弧的, 刚刚连接的部位, 有一点点不圆润, 我们今天就处理这个问题

cardView的圆角是怎么弄的

    public void draw(Canvas canvas) {
        final Paint paint = mPaint;

        final boolean clearColorFilter;
        if (mTintFilter != null && paint.getColorFilter() == null) {
            paint.setColorFilter(mTintFilter);
            clearColorFilter = true;
        } else {
            clearColorFilter = false;
        }

        canvas.drawRoundRect(mBoundsF, mRadius, mRadius, paint);

        if (clearColorFilter) {
            paint.setColorFilter(null);
        }
    }
...
final RoundRectDrawable background = new RoundRectDrawable(backgroundColor, radius);
cardView.setCardBackground(background);

使用canvas画的圆角矩形

我们今天的主题就是用canvas画圆角矩形, 要圆润的那种

为什么圆角不圆润

这要从一条直线说起,

首先我们画一条直线

"ui";
importClass(android.graphics.PorterDuff);
importClass(android.graphics.Color);
/* -------------------------------------------------------------------------- */
ui.layout(
    <vertical gravity="center_horizontal">
        <canvas id="board" w="300dp" h="300dp"></canvas>
    </vertical>
);
let paint = new Paint();
paint.setColor(Color.RED);
paint.setStrokeWidth(2);
ui.board.on("draw", function (canvas) {
    canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
    canvas.drawLine(0, 0, canvas.getWidth(), canvas.getHeight(), paint);
});

这是一条普通的直线

角度不适合这个教程, 我们把直线画到中间

paint.setStrokeWidth(60);
ui.board.on("draw", function (canvas) {
    canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
    canvas.drawLine(0, canvas.getHeight() / 2, canvas.getWidth(), canvas.getHeight() / 2, paint);
});

这条线的高度是60px

现在直线在中间, 我在底部画一条同样高度是60px的直线

canvas.drawLine(0, canvas.getHeight() / 2, canvas.getWidth(), canvas.getHeight() / 2, paint);
canvas.drawLine(0, canvas.getHeight(), canvas.getWidth(), canvas.getHeight(), paint);

底部的直线高度还是60, 但是我们能看见的只有30, 另外一半在画板外面

直线就是这样的, 下面我们来看看圆角矩形

绘制圆角矩形的方法

函数名称:public void drawRoundRect (RectF rect, float rx, float ry, Paint paint)

参数说明:

rect:RectF对象。

rx:x方向上的圆角半径。

ry:y方向上的圆角半径。

paint:绘制时所使用的画笔。

先构造rect

let rect = new RectF(0, 0, board.getWidth(), board.getHeight());

再画圆角矩形

canvas.drawRoundRect(rect, rx, ry, paint);

可以看到, 这个圆角矩形, 也就是这个圆, 它在上下左右贴近正方形四边的时候, 笔画变细了,

因为有一半漏到画板外面了, 我们也看不见

我们修改一下画板高度, 看看圆角矩形的样子

\

从图中可以看到, 圆角矩形挨着长方形四条边的地方, 都有半截漏到了画板外面,

但是有一部分是没有漏到外面的, 那就是四个角的四条弧,

这就是为什么觉得圆角不圆润的原因,

这就是为什么感觉圆弧比直线粗一点的原因所在

解决圆角矩形直线和圆弧粗细不一样的方法

那这个问题怎么解决呢?

我们把四条边的直线, 往里面推一推, 压一压, 都看见不就好啦!

这个主要是修改参数rect, 左上右下都往里面压30px

let k = 30;
let rect = new RectF(0 + k, 0 + k, board.getWidth() - k, board.getHeight() - k);

\

和上面的圆角矩形比一下, 这个效果要好很多

实际效果

我们来给textview添加圆角背景

function setBackground(view, offset) {
    offset = offset || 0;
    let rect = new RectF(0 + offset, 0 + offset, view.getWidth() - offset, view.getHeight() - offset);
    let rx = view.height;
    let ry = rx;
    var drawable = new android.graphics.drawable.Drawable({
        draw: function (canvas) {
            canvas.drawRoundRect(rect, rx, ry, paint);
        },
    });
    view.setBackgroundDrawable(drawable);
}

看上去没什么区别,

我们再用另外一种办法试试: 裁剪画布

function setBackground(view, offset) {
    offset = offset || 0;
    let rect = new RectF(0 + offset, 0 + offset, view.getWidth() - offset, view.getHeight() - offset);
    let rx = view.height;
    let ry = rx;
    let path = new Path();
    path.addRoundRect(rect, rx, ry, Path.Direction.CW);
    var drawable = new android.graphics.drawable.Drawable({
        draw: function (canvas) {
            canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
            canvas.clipPath(path);
            canvas.drawColor(Color.BLUE);
        },
    });
    view.setBackgroundDrawable(drawable);
}

除了背景小了一圈, 圆弧那里, 还是没有看到什么特别明显的区别, 该有锯齿还是有锯齿

我们再用空心描边试试

paint.setStyle(Paint.Style.STROKE);

从图中可以看出, 之所以没有区别, 是因为画笔描边, 就算超出了view的区域, 仍然是可见的,

除非你限制view区域之外的描边看不见.

黑色是view的区域, 为什么画笔的描边在区域之外还能显示呢?

当我把圆角矩形向左挪动100个像素的时候, 画笔的描边就只显示view的黑色区域内部了, 这样我觉得才是正常的;

我觉得这是autojs的bug,

view绘制的时候, 只能在view内部, 正常是不应该超出view区域, 否则会遮挡其他控件.

环境

雷电模拟器:9.0.17
Android版本: 9
Autojs版本: 9.2.10

名人名言

思路是最重要的, 其他的百度, bing, stackoverflow, github, 安卓文档, autojs文档, 最后才是群里问问 --- 牙叔教程

声明

部分内容来自网络 本教程仅用于学习, 禁止用于其他用途

微信公众号 牙叔教程