0

私は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()は無効化せず、アニメーションも停止します。それがどこにあっても続けるために必要なことはありますか?

答えて

1

私はあなたがにリンクされている質問に答え、コメントで述べたように:キャンバスプレーンビューにされたレンダリング中

キャンバスSurfaceViewにレンダリングするには、ハードウェアアクセラレーションではありません。

(小さなデバイスでは4Kディスプレイの必然的なドライブのために)ディスプレイのピクセル数が高くなると、ソフトウェアレンダリングが遅くなります。 CPU性能とメモリ帯域幅の増加はこれを相殺しますが、一部のデバイスではうまく機能しません。

これはさまざまな方法で補償できます。たとえば、 using setFixedSize() to limit the pixel countですが、ハードウェアアクセラレーションによるレンダリングが一般に良いアプローチです。

CPUによってフレームレートが制限されている場合は、同じCPUコアを使用したいものがジャンクを起こす可能性があります。別のスレッドにSurfaceViewレンダラを置くことができますが、デバイスの制限を押しても面倒ではありません。ディスプレイは一定のレートで更新されています。期限を一貫して満たしていなければ、アニメーションはスムーズではありません。 (いくつかの追加の考えがthis appendixで見つけることができます。)

+0

UIの仕事とそうでない場合は、そのフレームワークがうまく動作しないので、あなたは、メインスレッド上のすべてのアニメーションを行うべきであると述べた、私は承知していますそのSurfaceビューは遅いです。私の調査は、SurfaceViewがView onDrawと同じくらい滑らかではない理由です... SufaceViewを使用している主な理由は、操作を別のプロセスにスレッド化し、Viewよりもスムーズにアニメーション化できるからです。 – Elye

+0

また、ディスプレイのリフレッシュの期限が間に合わない場合は、ジャンクを使用します。各フレームを60fpsでレンダリングするには16.7msが必要です。また、大型ディスプレイでのソフトウェアレンダリングには問題があります。極端な場合:SurfaceViewへのソフトウェアレンダリングに200ms(5fps)かかる場合、フレームあたり10msしかかからないカスタムビューへのハードウェアレンダリングよりもスムーズに見えません。マルチスレッドは銀色の弾丸ではありません。 – fadden

0

Androidの開発者Yaは

+1

Androidデベロッパーはどういう意味ですか?ソースを追加する必要があります。 –

関連する問題