更新
我的小橱窗存放在Bitbucket上
https://bitbucket.org/solvapps/animationtest
我有一个带有视图的活动。 Contentview
设置为此视图。
public class MainActivity extends AppCompatActivity {
private MyView myView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myView = new MyView(this);
setContentView(myView);
startMovie();
}
public void startMovie(){
MovieTask movieTask = new MovieTask(myView, this);
movieTask.doInBackground(null);
}
}
MovieTask是一个Asynctask并定期刷新视图。 但invalidate()不会刷新视图。
public class MovieTask extends AsyncTask<String, String, String> {
MyView drawingView;
MainActivity mainActivity;
public MovieTask(MyView view, MainActivity mainActivity){
this.mainActivity = mainActivity;
this.drawingView =view;
}
@Override
protected String doInBackground(String... strings) {
for(int i=20;i<100;i++){
drawingView.myBall.goTo(i,i);
publishProgress();
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return null;
}
@Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
mainActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
Log.v("DEBUG_DRAW","in onProgressUpdate()");
drawingView.invalidate();
}
});
}
}
有人可以帮忙吗?
答案 0 :(得分:7)
了解如何启动AsyncTask
:
public void startMovie() {
MovieTask movieTask = new MovieTask(myView, this);
movieTask.doInBackground(null);
}
您正在手动调用名为MovieTask
的某个类中的方法,因此您在同一个线程上运行代码。显然,这不是你的意图,你打算在后台线程上运行计算代码。
正确启动AsyncTask
的方法正在使用execute(Params...)
:
public void startMovie() {
MovieTask movieTask = new MovieTask(myView, this);
movieTask.execute("");
}
现在你将获得理想的效果。
P.S。
请不要使用该代码:您不需要启动后台线程来执行此类操作。作为替代方案,请考虑Animators API。
在setBall(int pos)
类中声明MyBall
方法:
public class MyView extends View {
...
public void setBall(int pos) {
myBall.setX(pos);
myBall.setY(pos);
invalidate();
}
}
然后将startMovie()
更改为以下内容:
public void startMovie() {
// "ball" means, that Animators API will search for `public setBall(int)` method inside MyView.java and call that method
ObjectAnimator ball = ObjectAnimator.ofInt(myView, "ball", 20, 100);
ball.setDuration(1000);
ball.start();
}
你会得到相同的动画而没有讨厌的代码。
答案 1 :(得分:0)
有两种可能的情况,首先如documents中所述:
void invalidate() 使整个视图无效。如果视图可见, onDraw(android.graphics.Canvas)将在某个时刻被调用 将来
因此,请尝试在onResume
中运行您的代码,View
可能尚未显示。
其次View#invalidate
告诉系统在主UI线程空闲时重绘视图。也就是说,调用invalidate会在所有其他即时工作完成后重新绘制您的视图。
如果您希望定期更新视图,请使用Handler#postDelay
或在单独的线程中运行,并使用View#postInvalidate
更新View
并触发对{{1}的调用}}