在自定义视图中绘制时支持 RTL 语言环境

Supporting RTL locales when drawing in custom views

当我使用 Canvas 在我的自定义视图中绘制时,是否有一种简单的方法可以在不手动反转坐标计算的情况下为 RTL 语言环境进行绘制?

作为一个非常人为的例子,这是一个自定义视图,在 onDraw() 中包含以下内容:

int w = getWidth();
int h = getHeight();
canvas.save();

mPaint.setColor(Color.RED);
canvas.drawRect(0, 0, w / 2, h, mPaint);
mPaint.setColor(Color.BLUE);
canvas.drawRect(w / 2, 0, w, h, mPaint);

int size = h / 4;
mPaint.setColor(Color.GREEN);
int paddingEnd = ViewCompat.getPaddingEnd(this);
canvas.translate(-paddingEnd, getPaddingTop());
canvas.drawRect(w - size, 0, w, size, mPaint);

canvas.restore();

在 LTR 和 RTL 布局中显示完全相同:

我知道您可以使用 Matrix 或 canvas.scale() 翻转 Canvas,但这对于更复杂的场景来说不是一个可行的选择,例如在 [=25 上绘制文本或其他 Drawables =].

在 Canvas 上完成 RTL 绘图的最佳方法是什么?我真的必须计算 X 轴坐标的反转值吗?

据我所知,框架中没有任何东西可以自动处理 canvas 的转换(对于绘图,如本例)或处理定位视图(对于布局)。换句话说,我必须自己使用 View.getLayoutDirection() 来确定布局方向并进行相应的计算。由于大多数绘图代码都使用对象的 left 位置,因此您通常可以执行类似

的操作
if (isRtl) {
    left = width - shapeWidth - left;
}

其中 width 是 canvas 的宽度(或您正在绘制的 canvas 的面积,例如,如果您已经减去 left 和右填充),shapeWidth 是形状宽度。然后将形状宽度添加到 left 以获得 right 值。

类似的方法可用于布置子视图。

您只需在 onDraw() 中调用 canvas.scale() 即可水平翻转所有进一步绘图操作的结果。

@Override
protected void onDraw(Canvas canvas) {
    canvas.save()

    boolean isRtl = getLayoutDirection == View.LAYOUT_DIRECTION_RTL
    if (isRtl) canvas.scale(-1f, 1f, (float) width / 2, (float) height / 2)

    //
    // do all your custom drawing here
    //

    canvas.restore()
}