54

I have found many posts on stackoverflow but I still cannot solve my problem. Here is my code piece:

public class MyView extends RelativeLayout {

Button b1;
Button b2;
Context sContext;
public static int i = 0;
private int w = 400;
private int h = 400;
private int w2 = 100;
private int h2 = 100;

public MyView(Context context) {
    super(context);
    sContext = context;
    init();
}

public MyView(Context context, AttributeSet attrs) {
    super(context, attrs);
    sContext = context;
    init();
}

private void init() {
    b1 = new Button(sContext);
    addView(b1);
    b1.setBackgroundColor(Color.YELLOW);

    b1.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {

            if (w >= 600) {
                MyView.this.setBackgroundColor(Color.GREEN);
                //b1.setBackgroundColor(Color.RED);
            } else {
                MyView.this.setX(100);
            }

            MyView.this.invalidate();
            w += 100;
            w2 += 20;
        }

    });
}

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    //b1.setBackgroundColor(Color.RED);
    Toast.makeText(sContext, ""+i, Toast.LENGTH_SHORT).show();
    ++i;
}
}

Would you please explain why onDraw is not called the first three times I press b1? Because I called invalidate everytime I press b1. Thank you very much!

darklord
  • 5,077
  • 12
  • 40
  • 65
  • http://stackoverflow.com/questions/17576970/android-when-ondraw-is-called/17577083#17577083. check this might help – Raghunandan Jul 11 '13 at 14:16

5 Answers5

99

By default all ViewGroup sub-classes do not call their onDraw method, you should enable it by calling setWillNotDraw(false) link

Rany Albeg Wein
  • 3,304
  • 3
  • 16
  • 26
Tomas Žemaitis
  • 1,797
  • 11
  • 5
24

Borrowing from the link @

Android Custom Layout - onDraw() never gets called

Try the below it works

1.If you're extending a ViewGroup (in your case a RelativeLayout) you should override dispatchDraw() instead of onDraw().

Discussion on the topic @

https://groups.google.com/forum/?fromgroups=#!topic/android-developers/oLccWfszuUo

protected void dispatchDraw (Canvas canvas)

Called by draw to draw the child views. This may be overridden by derived classes to gain control just before its children are drawn (but after its own view has been drawn).

Parameters

canvas the canvas on which to draw the view

Example

public class Hello  extends Activity {

    private MyView myView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

                super.onCreate(savedInstanceState);
                Log.e("hello", "hello");
                this.myView = new MyView(this);
                setContentView(this.myView);

    }
     public class MyView extends RelativeLayout
       {

      private Paint myPaint = new Paint();
      private int[] numbers;
      public MyView(Context paramContext)
      {
        super(paramContext);
        Log.e("MyView", "MyView");
        setFocusable(true);
        setBackgroundResource(R.drawable.ic_launcher);
      }
      @Override
      protected void dispatchDraw(Canvas canvas){         

            super.dispatchDraw(canvas);     
            Log.i("...............","drawing");   
        }

  }
}

2.If you Override onDraw in the constructor call setWillNotDraw(false) then it should work.

http://developer.android.com/reference/android/view/View.html#setWillNotDraw(boolean)

public MyView(Context context) {
super(context);
sContext = context;
init();
setWillNotDraw(false); 
}
Community
  • 1
  • 1
Raghunandan
  • 132,755
  • 26
  • 225
  • 256
  • +1000 thanks ! even if it's not the right answer, dispatchDraw() made it for me ! :D – ahmed_khan_89 Mar 06 '15 at 21:04
  • 1
    @ahmed_khan_89 what do you mean its not the right answer. The answer is right. there are 2 ways of solving pointed out in the answer – Raghunandan Mar 07 '15 at 03:05
  • sorry for the misunderstanding. I meant that the answer was not selected as the right answer by the guy who asked the question. I didn't mean that the answer was wrong. – ahmed_khan_89 Mar 07 '15 at 03:18
14

You need to call setWillNotDraw(false); in order for your onDraw method to be called:

private void init() {
  setWillNotDraw(false);
  ...
}
CodingIntrigue
  • 75,930
  • 30
  • 170
  • 176
0

I was having OnDraw not called in C# using 4.1 Jelly Bean API 16. I switched from compiling with API 16 SDK to compiling with 7.1 Nougat SDK. It solved the problem completely. I still have in manifest min sdk of API 16 and it runs fine in my Jelly Beam avd.

0

In my case onDraw was not called because I returned 0 as width or height of view.

Fartab
  • 4,725
  • 2
  • 26
  • 39