Android-如何在SurfaceView中设定时间后绘制位图
为了澄清,我想做一个简单的动画,几秒钟后从一个位图切换到另一个位图,然后重复。例如,如果我画了一张皱眉的脸,我如何设置它在几秒钟后被移除,并用一张笑脸替换它Android-如何在SurfaceView中设定时间后绘制位图,android,bitmap,Android,Bitmap,为了澄清,我想做一个简单的动画,几秒钟后从一个位图切换到另一个位图,然后重复。例如,如果我画了一张皱眉的脸,我如何设置它在几秒钟后被移除,并用一张笑脸替换它 Here's some example code public class MySurface extends SurfaceView implements Runnable { SurfaceHolder ourHolder; Thread ourThread = null; boolean isRunning = true;
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();
}
}
我建议使用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) {}
}
}
导入android.app.Activity;
导入android.os.AsyncTask;
导入android.os.Bundle;
导入android.provider.Settings.System;
导入android.view.view;
公共类AsyncTaskActivity扩展活动实现OnClickListener{
@凌驾
创建时的公共void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
myBitmapTask myTask=新建myBitmapTask();
myTask.execute();
}
私有类myBitmapTask扩展了AsyncTask{
@凌驾
受保护的void onPreExecute(){}
@凌驾
受保护字符串doInBackground(无效…参数){
对于(int i=0;i<5;i++){
试一试{
睡眠(1000);
}捕捉(中断异常e){
Thread.interrupted();
}
}
返回null;
}
@凌驾
受保护的void onPostExecute(void…参数){
//做位图动画
}
@凌驾
受保护的void onProgressUpdate(void…值){}
}
}
注意:这没有经过测试,是在我的手机上输入的。对不起,我的拼写错误。我认为处理程序是最好的选择。使用子类创建如下所示的
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.sleep()启动RefreshHander代码>。延迟后,handleMessage()
将运行
现在在onDraw()
中,不要先画皱眉,然后画笑脸,只需让它画一个最初设置为皱眉的图像(位图图像;图像=皱眉;
)
使用updateImage()
将该图像更改为笑脸,以便在视图无效时,下一个onDraw()
将绘制笑脸
private void updateImage() {
image = smiley;
}
我喜欢使用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
}
公共类AsynchronousSSClassicCreated扩展异步任务{
@凌驾
受保护的void doInBackground(void…参数){
}
@凌驾
PostExecute上受保护的void(SomeClassToReturn DrawingTodo){
//这里是你可以画画的地方
}
无论如何,这就是我喜欢这样做的方式。就像我说的,这对于你的搜索可能有些过分,但它也适用于所有可能需要更多处理的情况。在这种情况下,使用Animator应该更容易。你可以交叉淡入两个位图。也可以工作。你可以只找到ViewFlipper示例伊恩。我知道你问了8个问题,但即使有5个问题得到了回答,也没有一个问题被标记为已回答。你显然是SO的新手,所以请阅读。@MarkCramer我甚至没有意识到这一点,谢谢you@user3720864没问题。如果你问了一个问题,有人给出了正确的答案,你需要用绿色的复选标记。要这样做,你需要过程是:创建一个扩展Asynctasks的新类,将onPreExecute保留为空,然后在doInBackground中让它等待(我会使用wait()?),将onProgressUpdateBlank保留为空,然后在onPostExecute中执行canvas.drawbitmap?这可能会起作用,但我认为这不是最好的方法。AsyncTask()如果您希望并行处理或在后台处理某些内容,这是非常好的,但它不一定是为计时器设计的,因为您无法控制它何时运行。使用“处理程序”可以使您以预先确定的时间间隔发送消息,这正是您想要的。还有一件事,不要调用onDraw()直接。使视图无效,这将为您调用onDraw()。我想我很接近了,但我不完全理解这一点。它在view.Invalidate()中给了我一个错误;。这是因为我使用的是SurfaceView而不是视图,还是我没有正确使用它?SurfaceView继承了android.view.view.的所有方法:。问题是您刚刚放置了“view.invalidate();”。“视图”是指向要使其无效的视图的指针。由于您的RefreshHandler实际上位于要使其无效的视图中,请仅使用“invalidate();”或“this.invalidate();”。此外,将“onDraw(c);”替换为“invalidate();”或“this.invalidate();”。我尝试切换到just invalidate();这消除了错误,但它似乎仍然崩溃()。另一方面,如果我删除了onDraw(c),什么时候才能绘制位图,就像我运行onDraw方法时那样?问题是“只有创建视图层次结构的原始线程才能接触其视图”。您只能从主线程更新UI:。两件事:1)runnable的用途是什么?我认为您可以将其完全删除。2)当视图无效时调用onDraw()。您不会像现在这样直接调用onDraw()。如果您删除runnable,显然也会解决此问题。
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
}