Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/210.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android-如何在SurfaceView中设定时间后绘制位图_Android_Bitmap - Fatal编程技术网

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
    }