Android - Trigger a loop that repeatedly redraws in a listener (force invalidate even though UI thread is busy)

StackOverflow https://stackoverflow.com/questions/19530045

Question

I have a view that contains a user's drawing. When clicking a 'play' button I want to have a loop that draws the image from start to finish.

In attempting to do this I basically have a loop inside of an onClickListener for the play button that essentially invalidates the view, waits, sets the next set of points and invalidates again.

The problem is that the image doesn't actually redraw until after the entire image is draw. So essentially nothing happens and then it's all of a sudden done. After doing some research, my assumption is that invalidate is telling the main UI thread to redraw when it gets time, but it's already hung up on dealing with the listener, so it doesn't actually draw until the loop is finished. I've tried calling onDraw directly, using postInvalidate, and just about any other ridiculous thing I can think of, but I'm not sure how to get this to work.

Here are some code snippets:

In my PaintActivity(Which has a PaintAreaView) The scrubber indicates the progress of the drawing. The first to lines in onProgressChanged works when I manually use the seek bar, but not when pressing play, which is why I tried adding all the extras.

        _scrubber.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
        @Override
        public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
            _paintAreaView.setPointsToDraw(_scrubber.getProgress());
            _paintAreaView.invalidate();
            _mainViewGroup.invalidate();
            _paintAreaView.postInvalidate();
            _mainViewGroup.postInvalidate();
            _paintAreaView.drawPoints(_paintAreaView.getCanvas());
            _paintAreaView.invalidate();
        }...

My Play Button stuff:

        play.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            ...
            playDrawing();
            ...
        }
    });

    private void playDrawing()
{
    int endPoint = getPaintPointCount();

    while(_scrubber.getProgress() < endPoint)
    {
        _scrubber.incrementProgressBy(1);

        try{
            Thread.sleep(10);
        }catch(InterruptedException e)
        {
            Thread.currentThread().interrupt();
        }
        //_paintAreaView.setPointsToDraw(_scrubber.getProgress());
        //_paintAreaView.invalidate();
        //_mainViewGroup.invalidate();
        if(_isPaused)
            break;
    }
}

I'm not a huge fan of using that sleep, but I've struggled with other solutions and that's my next thing to research. But for this question, incrementing the progress bar does successfully call onProgressChanged, but again it just isn't drawing the view until it's out of that play button click listener.

If I have to wait until I'm out of the listener to get this to work, I'm new enough that I'm not sure how I would approach that.

Sorry for my bad code, any help is much appreciated to help me understand what's happening here and what I need to understand to get this to work.

Thank you!

Était-ce utile?

La solution

I got it to work, I'm not sure if all I did was necessary, but here are the changes I made based on my Main UI thread theory being the problem.

I created a class Thread member variable:

private Thread _drawThread;

In onCreate():

_drawThread = new Thread(){
    public void run(){
        playDrawing();
    }
};

play Button onClick:

play.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
         ...
         _drawThread.start();
    }
});

Seems to be doing just what I want! Except the app crashes the second time I hit play :) From here I don't think it'll be to bad to figure out that issue though.

EDIT----- Creating the Thread in my play button onClickListener instead of having it be a member variable fixed the crashing. I incorrectly assumed the thread would be destroyed as soon as the listener went out of scope on the main thread, but I guess that's not the case.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top