在RelativeLayout的Canvas上绘制在所有其他视图之后?

3

我使用RelativeLayout来绝对定位一些标准视图(如TextView)。

我想要做的是在此RelativeLayoutCanvas上绘制一个自定义线条,该线条绘制在它所有其他子视图的后面

这些其他子视图是通过显式定义RelativeLayout.LayoutParams添加的,但我想让我的自定义线条决定何时绘制自己。

我尝试将此行包装在一个带有重载的CustomView中:View.onDraw(Canvas canvas)方法并简单地添加视图而不指定任何LayoutParams,所以:

public class CustomView extends View {
  public CustomView(Context context, int x0, int y0, int x1, int y1) {
    super(context);
    setClickable(false);
    setBackgroundColor(Color.TRANSPARENT);
  }
  public void onDraw(Canvas canvas) {
    Log.i("myapp", "i'm not called! :(")
    Paint p = new Paint();
    p.setColor(Color.BLACK);
    canvas.drawLine(x0, y0, x1, y1, p);
  }
}

使用方法:

CustomView v = new CustomView(MyActivity.this, 0, 0, 100, 100);
relativeLayout.addView(v);

...但是这个onDraw方法从来没有被调用。

有办法让它起作用吗?


编辑:如果我替换为:

relativeLayout.addView(v)

使用

relativeLayout.addView(v,
  new RelativeLayout.LayoutParams(SOME_WIDTH, SOME_HEIGHT));

关键是,此时我既不知道SOME_WIDTH,也不知道SOME-HEIGHT


扩展RelativeLayout,而不是View。 - pskink
@pskink,这对于我的应用程序的“逻辑”来说不是一个好的、嗯,分解选择。这些行本身就是重要的元素,它们的放置取决于普通布局的其他子视图的放置。 - Michal Rus
嗯,我不明白,如果它依赖于子视图,那么在RelativeLayout中迭代它们并获取它们的位置,例如getTop/getLeft等。 - pskink
@psink,我知道这些位置。我只是想在RL的画布上自由绘制。 - Michal Rus
3个回答

4

试试这个自定义的RelativeLayout:

class RL extends RelativeLayout {
    private Paint mPaint;
    public RL(Context context) {
        super(context);
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setStrokeWidth(5);
        mPaint.setColor(0xffffffff);
    }

    @Override
    protected void dispatchDraw(Canvas canvas) {
        int cnt = getChildCount();
        for (int i = 0; i < cnt; i++) {
            View child = getChildAt(i);
            int l = child.getLeft();
            int t = child.getTop();
            int r = child.getRight();
            int b = child.getBottom();
            if (i % 2 == 0) {
                canvas.drawLine(l, t, r, b, mPaint);
            } else {
                canvas.drawLine(l, b, r, t, mPaint);
            }
        }
        super.dispatchDraw(canvas);
    }
}

并且通过在onCreate()方法中添加以下内容来进行测试:

RelativeLayout rl = new RL(this);
TextView tv;
List<String> list = Arrays.asList("one", "    two    ", "three", "    four    ", "fife");
int i = 0;
for (String string : list) {
    int id = 1000 + i;
    RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
    if (i != 0) {
        params.addRule(RL.BELOW, id - 1);
    }
    tv = new TextView(this);
    tv.setTextSize(48);
    tv.setTextColor(0xffff0000);
    tv.setText(string);
    rl.addView(tv, params);
    tv.setId(id);
    i++;
}
setContentView(rl);

嘿,这肯定有效:因为你是在RelativeLayout自己的dispatchDraw中进行绘制。 :) - Michal Rus
嗯,这是最自然的解决方案,为什么我要在其他地方画呢? - pskink
你好朋友,我想要缩放相对布局并画线。如何使用你的代码进行缩放? - reegan29
@reegan29 RelativLayout#setScale[X|Y] 是什么意思? - pskink
我有一个Zoom库,用于Zoom相对布局。我有一个名为“启用缩放”的按钮。当我启用缩放时,按钮文本会更改为“禁用缩放”,并且只有缩放才能启用。当我单击“禁用缩放”按钮时,绘图将启用。在启用缩放后,我可以使用我的绘图缩放布局。请帮帮我,兄弟。我已经尝试了一个星期,但无法实现。 - reegan29

0
最简单的方法是在onDraw()方法中完成背景后调用super.draw(Canvas)方法。 这将导致它最后绘制子元素。

0

所以。

最终我创建了一个CustomController,其中包含一些计算位置/大小的方法,并在创建每个CustomView(context, controller)时使用此控制器来创建RelativeLayout.LayoutParams

我想在没有指定其RelativeLayout.LayoutParams的情况下无法在RelativeLayout中拥有子视图。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接