私はViewまたはSurfaceViewのためにテストするための同様の実装を開発しています。私はカスタムビューアニメーションは、カスタムSurfaceViewアニメーションよりもスムーズですか?
public class TimerView extends View {
private Paint mPiePaint;
private RectF mShadowBounds;
private float diameter;
int startCount = 0;
private PanelThread thread;
public TimerView(Context context) {
super(context);
init();
}
public TimerView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public TimerView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
@TargetApi(VERSION_CODES.LOLLIPOP)
public TimerView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init();
}
private void init() {
mPiePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPiePaint.setStyle(Paint.Style.FILL);
mPiePaint.setColor(0xff000000);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
// Account for padding
float xpad = (float)(getPaddingLeft() + getPaddingRight());
float ypad = (float)(getPaddingTop() + getPaddingBottom());
float ww = (float)w - xpad;
float hh = (float)h - ypad;
// Figure out how big we can make the pie.
diameter = Math.min(ww, hh);
mShadowBounds = new RectF(0, 0, diameter, diameter);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (startCount == 360) startCount= 0;
canvas.drawArc(mShadowBounds,
0, startCount, true, mPiePaint);
invalidate();
startCount++;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int minw = getPaddingLeft() + getPaddingRight() + getSuggestedMinimumWidth();
int w = resolveSizeAndState(minw, widthMeasureSpec, 1);
int h = resolveSizeAndState(MeasureSpec.getSize(w), heightMeasureSpec, 0);
setMeasuredDimension(w, h);
}
}
以下のように表示を実装し、カスタムビュー(TimerView)があることを示している私は
class PanelThread extends Thread {
private SurfaceHolder surfaceHolder;
private TimerSurfaceView panel;
private boolean starRunning = false;
public PanelThread(SurfaceHolder surfaceHolder, TimerSurfaceView panel) {
this.surfaceHolder = surfaceHolder;
this.panel = panel;
}
public void setRunning(boolean run) { //Allow us to stop the thread
starRunning = run;
}
@Override
public void run() {
Canvas c;
while (starRunning) { //When setRunning(false) occurs, starRunning is
c = null; //set to false and loop ends, stopping thread
try {
c = surfaceHolder.lockCanvas(null);
synchronized (surfaceHolder) {
//Insert methods to modify positions of items in onDraw()
panel.drawSomething(c);
}
} finally {
if (c != null) {
surfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
}
結果、以下のよう
public class TimerSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
private Paint mPiePaint;
private RectF mShadowBounds;
private float diameter;
int startCount = 0;
private PanelThread thread;
public TimerSurfaceView(Context context) {
super(context);
init();
}
public TimerSurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public TimerSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
@TargetApi(VERSION_CODES.LOLLIPOP)
public TimerSurfaceView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init();
}
private void init() {
getHolder().addCallback(this);
mPiePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPiePaint.setStyle(Paint.Style.FILL);
mPiePaint.setColor(0xff000000);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
// Account for padding
float xpad = (float)(getPaddingLeft() + getPaddingRight());
float ypad = (float)(getPaddingTop() + getPaddingBottom());
float ww = (float)w - xpad;
float hh = (float)h - ypad;
// Figure out how big we can make the pie.
diameter = Math.min(ww, hh);
mShadowBounds = new RectF(0, 0, diameter, diameter);
}
protected void drawSomething(Canvas canvas) {
canvas.drawColor(0xFFEEEEEE);
if (startCount == 360) startCount= 0;
canvas.drawArc(mShadowBounds,
0, startCount, true, mPiePaint);
startCount++;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int minw = getPaddingLeft() + getPaddingRight() + getSuggestedMinimumWidth();
int w = resolveSizeAndState(minw, widthMeasureSpec, 1);
int h = resolveSizeAndState(MeasureSpec.getSize(w), heightMeasureSpec, 0);
setMeasuredDimension(w, h);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
setWillNotDraw(false); //Allows us to use invalidate() to call onDraw()
thread = new PanelThread(getHolder(), this); //Start the thread that
thread.setRunning(true); //will make calls to
thread.start(); //onDraw()
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// tell the thread to shut down and wait for it to finish
// this is a clean shutdown
boolean retry = true;
while (retry) {
try {
thread.join();
retry = false;
} catch (InterruptedException e) {
// try again shutting down the thread
}
}
}
}
そしてSurfaceViewスレッド以下のように私の表面図を実装しましたサーフェスビューよりも滑らかです(https://www.youtube.com/watch?v=s9craUgY3I4)。 http://stackoverflow.com/questions/23893266/why-surfaceview-is-slower-than-a-custom-view
によると、SurfaceViewは遅くなりますが、滑らかになるはずです。
SurfaceViewで、以前の描画を消去するために再描画する必要がありますかcanvas.drawColor(0xFFEEEEEE);
drawSomething
は機能しますか?私がTimerViewで行ったように、ちょうどinvalidate()
onDraw
の間にそれを再クロールの必要性を排除する方法はありますか?
私が直面しているもう1つの問題は、アプリケーションがバックグラウンドに戻り、TimerSurfaceViewのdrawSomthing
はnull Canvasを受け取り、TimerView onDraw()は無効化せず、アニメーションも停止します。それがどこにあっても続けるために必要なことはありますか?
UIの仕事とそうでない場合は、そのフレームワークがうまく動作しないので、あなたは、メインスレッド上のすべてのアニメーションを行うべきであると述べた、私は承知していますそのSurfaceビューは遅いです。私の調査は、SurfaceViewがView onDrawと同じくらい滑らかではない理由です... SufaceViewを使用している主な理由は、操作を別のプロセスにスレッド化し、Viewよりもスムーズにアニメーション化できるからです。 – Elye
また、ディスプレイのリフレッシュの期限が間に合わない場合は、ジャンクを使用します。各フレームを60fpsでレンダリングするには16.7msが必要です。また、大型ディスプレイでのソフトウェアレンダリングには問題があります。極端な場合:SurfaceViewへのソフトウェアレンダリングに200ms(5fps)かかる場合、フレームあたり10msしかかからないカスタムビューへのハードウェアレンダリングよりもスムーズに見えません。マルチスレッドは銀色の弾丸ではありません。 – fadden