Invalidate doesn't cause OnDraw

2019-06-09 20:07发布

I have problem with my Android app. I've created custom view (http://syedwasihaider.github.io/blog/2015/07/12/XamarinViews/ up to step 2), overriden onDraw and I draw black screen and text "Draw {i}" where i is number that increments every time onDraw occurs. I want to call this method 30 times/second (or 60), so I've set up timer that causes Invalidate() every 33 ms.

But Invalidate() doesn't cause onDraw at all! (It's not like its a delay between invalidate and ondraw, ondraw isn't called at all). I've tried to set SetWillNotDraw(false), but it didn't work. Here's my code:

class DrawCanvas : View
{
    Context mContext;
    public DrawCanvas(Context context) : base(context)
    {
        init(context);
    }
    public DrawCanvas(Context context, IAttributeSet attrs) : base(context, attrs)
    {
        init(context);
    }
    public DrawCanvas(Context context, IAttributeSet attrs, int defStyle) : base(context, attrs, defStyle)
    {
        init(context);
    }

    private void init(Context ctx)
    {
        mContext = ctx;

        black = new Paint() { Color = Color.Black };
        white = new Paint() { Color = Color.White };

        Timer timer = new Timer(33);
        timer.Elapsed += Timer_Elapsed;
        timer.Start();
    }

    private void Timer_Elapsed(object sender, ElapsedEventArgs e)
    {
        Invalidate();
    }

    int i = 0;
    Paint black;
    Paint white;
    private void TestDraw(Canvas canvas)
    {
        canvas.DrawRect(0, 0, Width, Height, black);
        canvas.DrawText("Draw " + i, 10, 10, white);
        i++;
    }

    protected override void OnDraw(Canvas canvas)
    {
        TestDraw(canvas);
    }
}

How can I either:

Call onDraw every 33ms

OR

Get canvas that is used in onDraw method? (tried to save canvas that comes as parameter in onDraw and use it later, but there was some weird behaviour, so it didn't work).

1条回答
\"骚年 ilove
2楼-- · 2019-06-09 20:40

Call onDraw every 33ms

You could use Handler to implement this feature.

Every time your DrawCanvas execute the OnDraw method, you could send a message to Handler, when you receive the message in Handler, you could call the DrawCanvas's Invalidate method, this Invalidate method will call OnDraw method. It will keep going.

For example :

class DrawCanvas : View
{
     MyHandler mHandler;
     ...
     private void init(Context ctx)
     {
         mHandler = new MyHandler(this);
         mContext = ctx;
         black = new Paint() { Color = Color.Black,TextSize=56 };
         white = new Paint() { Color = Color.White, TextSize = 56 };
     }
     ...
     protected override void OnDraw(Canvas canvas)
     {
         TestDraw(canvas);
         mHandler.SendEmptyMessageDelayed(1,33);
     }
     ...
     public class MyHandler : Handler
     {
         private DrawCanvas drawCanvas;

         public MyHandler(DrawCanvas drawCanvas)
         {
             this.drawCanvas = drawCanvas;
         }

         public override void HandleMessage(Message msg)
         {
             base.HandleMessage(msg);
             drawCanvas.Invalidate();
         }
     }
}

Effect :

enter image description here

查看更多
登录 后发表回答