Android Custom View with Handler

2019-08-22 21:51发布

问题:

I am looking for an easy way to animate custom views in Android. I am trying to avoid using the animator object but want to work with raw threads. What I have done is created a custom view by creating a class that extends android.view.View. I then override the onDraw method and use the canvas to draw a rect. What I would like is the rect to shrink, so I keep a variable that represents the x value of the right hand side of the rectangle. I would then like the the rectangle's right edge shrink in over time. What I would have liked to do is create a new thread, start it and have it change the value of the rectangle. That all works except the view doesn't get updated until you call View.invalidate. The problem is that I can't call that from the thread that I spawned because it is not the UI thread. I read solutions on using Handlers... but I am still unsure if that is the correct solution and then how to use them.

package com.example.practicum;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.View;

public class TimerControl extends View implements Runnable, Handler.Callback
{
    private Paint paint;
    private Rect rect;
    private Thread t;
    private Handler h;

    public TimerControl(Context context, AttributeSet attrs)
    {
        super(context, attrs);
        // TODO Auto-generated constructor stub



        paint = new Paint();
        paint.setColor(Color.BLUE);
        rect = new Rect(0,0,60,60);
        t = new Thread(this);
        t.start();


        h = new Handler(this);
        //h.post(this);
    }

    @Override
    public void onDraw(Canvas canvas)
    {
        canvas.drawRect(rect, paint);
    }

    @Override
    public void run()
    {
        rect.right = rect.right-1;
        while(true)
        {
            rect.right = rect.right-1;
            this.invalidate();
            try
            {
                Thread.sleep(5000);
                h.sendEmptyMessage(0);
            } 
            catch (InterruptedException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    @Override
    public boolean handleMessage(Message msg)
    {

        return false;
    }

}

回答1:

you can define a global Handler (in the UI thread):

Handler mHandler = new Handler();

then, from your thread, call:

mHandler.post(new Runnable() {
    public void run() {             
        // call some method on the UI thread
    }
});