Android-如何在SurfaceView中设置一段时间后绘制位图

时间:2014-07-28 23:36:36

标签: android bitmap

为了澄清,我有兴趣做一个简单的动画,几秒后从一个位图变为另一个位图,然后重复。例如,如果我画了一张皱眉的脸,我怎么能把它设置为几秒后被移除,并用笑脸取代它?

Here's some example code



public class MySurface extends SurfaceView implements Runnable {

SurfaceHolder ourHolder;
Thread ourThread = null;
boolean isRunning = true;

Bitmap frowny;
Bitmap smiley;

public MySurface(Context context) {
    super(context);
    init(context);

}

public MySurface(Context context, AttributeSet attrs) {
    super(context, attrs);
    init(context);
}

public MySurface(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    init(context);
}

private void init(Context context) {
    // do stuff that was in your original constructor...
    ourHolder = getHolder();
    ourThread = new Thread(this);
    ourThread.start();

    frowny = BitmapFactory.decodeResource(getResources(),
            R.drawable.frowny);
    smiley = BitmapFactory
            .decodeResource(getResources(), R.drawable.smiley);


}

public void pause() {
    isRunning = false;
    while (true) {
        try {
            ourThread.join();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        break;
    }
    ourThread = null;
}

public void resume() {
    isRunning = true;

}

@SuppressLint("WrongCall")
public void run() {
    // TODO Auto-generated method stub
    while (isRunning) {
        if (!ourHolder.getSurface().isValid()) {
            continue;
        }

        Canvas c = ourHolder.lockCanvas();
        onDraw(c);
        ourHolder.unlockCanvasAndPost(c);

    }

}

@Override
protected void onDraw(Canvas canvas) {
    // TODO Auto-generated method stub
    super.onDraw(canvas);

    canvas.drawBitmap(frowny, (getWidth/2), (getHeight/2), null);

    //wait a period/remove frowny

    canvas.drawBitmap(smiley, (getWidth/2), (getHeight/2), null);



    postInvalidate();

  }

}

3 个答案:

答案 0 :(得分:0)

我建议使用AsyncTask。在doInBackground方法中,设置一个计时器,然后在onPostExecute方法中,进行动画。

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.Settings.System;
import android.view.View;

public class AsyncTaskActivity extends Activity implements OnClickListener {

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
  myBitmapTask myTask = new myBitmapTask();
  myTask.execute();
}

private class myBitmapTask extends AsyncTask<Void, Void, Void> {

    @Override
    protected void onPreExecute() {}

    @Override
    protected String doInBackground(Void... params) {
        for (int i = 0; i < 5; i++) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                Thread.interrupted();
            }
        }
        return null;
    }

    @Override
    protected void onPostExecute(Void... Params) {
        // do bitmap animation
    }

    @Override
    protected void onProgressUpdate(Void... values) {}
}
}

注意:这未经过测试,并且已在我的手机上输入。对不起任何错别字。

答案 1 :(得分:0)

我认为Handler是最佳选择。使用子类来创建RefreshHander,如下所示:

class RefreshHandler extends Handler {
    @Override
    public void handleMessage(Message msg) {
        updateImage(); // change your frown to a smiley
        view.invalidate(); // trigger onDraw()
    }

    public void sleep() {
        this.removeMessages(0);
        sendMessageDelayed(obtainMessage(0), DELAY, 0)); // how long to wait in ms
    }
}

使用private RefreshHandler redrawHandler = new RefreshHandler();创建一个redrawHandler,然后使用redrawHandler.sleep();启动RefreshHander。在DELAY之后,handleMessage()将会运行。

现在在onDraw(),而不是绘制皱眉然后笑脸,只需要绘制一张最初设置为皱眉(Bitmap image; image = frown;)的图像。

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    canvas.drawBitmap(image, (getWidth/2), (getHeight/2), null);
}

使用updateImage()将该图片更改为笑脸,以便在视图无效时,下一个onDraw()将绘制笑脸。

private void updateImage() {
    image = smiley;
}

答案 2 :(得分:0)

我喜欢使用asyncTask方法,因为它可能对您的应用程序来说太过分了,但您可以将相同的代码用于其他更多处理密集型任务。在我的活动中,我通常做的就是这样。

public void callAsynchronousClass() {
    final Handler handler = new Handler();
    Timer timer = new Timer();
    TimerTask doAsynchronousTask = new TimerTask() {
        @Override
        public void run() {
            handler.post(new Runnable() {
                @Override
                public void run() {
                    if (processing) {
                        try {
                            AsynchronousClassICreated myAsyncTask = new
                                    AsynchronousClassICreated();
                        myAsyncTask.execute();                            
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        });

    }
};
timer.schedule(doAsynchronousTask, 0, timeUntilUpdate);

通过这种方式,您仍然可以根据需要进行尽可能多的处理,然后让计时器根据需要多次重复调用任务。 然后你就可以在asyncTask中使用on post execute方法了。

public class AsynchronousssClassICreated extends AsyncTask<Void, Void, theDrawingToDo>{
    @Override
    protected void doInBackground(Void... params) {
    }

    @Override
    protected void onPostExecute(SomeClassToReturn theDrawingToDo) {
          //here is where you can do some drawing
    }

无论如何,这就是我喜欢做这样的事情。就像我说的那样,对于你所寻找的东西来说可能有些过分,但它适用于你可能还需要更多处理的各种情况。