Michal Rus
Michal Rus

Reputation: 1848

Drawing on RelativeLayout's Canvas behind all other views?

I'm using RelativeLayout to absolutely position some standard views (like TextView).

What I'd like to do is to draw a custom line on this RelativeLayout's Canvas using Canvas.drawLine that is drawn behind all its other subviews.

These other subviews are added with explicitely defining RelativeLayout.LayoutParams, but I'd like to leave the decision of where to paint itself to my custom line.

I tried wrapping this line in a CustomView with overloaded View.onDraw(Canvas canvas) method and simply adding the view without specifying any LayoutParams, so:

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);
  }
}

And usage:

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

... but this onDraw method is never called.

Is there a way to make this work?


Edit: works if I substitute:

relativeLayout.addView(v)

with

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

The point is, I know neither SOME_WIDTH, nor SOME-HEIGHT at that point.

Upvotes: 3

Views: 4243

Answers (3)

Jarris
Jarris

Reputation: 1

Easiest way is to call the super.draw(Canvas) method after you finished your background in the onDraw() method. That will cause it to draw the children last.

Upvotes: 0

Michal Rus
Michal Rus

Reputation: 1848

So.

I ended up creating a CustomController which has some methods to calculate position/size and using this controller when creating RelativeLayout.LayoutParams for each CustomView(context, controller).

I guess you cannot have a subview in a RelativeLayout without specifying its RelativeLayout.LayoutParams.

Upvotes: 0

pskink
pskink

Reputation: 24740

try this custom 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);
    }
}

and test it ba adding the following in onCreate() method:

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);

Upvotes: 4

Related Questions