Aşağıdaki gibi basit bir onDraw yöntemim var ('SurfaceView' içinde), 'startCount' 1'den 360'a geçecek, dolu daire çizilecektir. Bir döngü tamamlandıktan sonra ve tamamlandıktan sonra. Radar dedektörün hareket etmesi gibi, yeniden başlayıp tekrar tekrar kendini yeniden çizecek.SurfaceView onDraw, zaman zaman çizmeden önce kendini yenilemez ... neden?
Garip şeyler, tam bir döngüden sonra, zaman zaman yenilenmez, dolayısıyla büyük siyah daire bunun yerine gösterilir.
https://youtu.be/sc56FYUqV7M biçiminde, ilk 2 döngü beklediğim şeydir. Ancak ikinci döngüyü tamamladığında, ileriye doğru hareket eden tüm siyah kalır, bu da önceki çizimi kaldırmadığı için gariptir. İkinci devrede yaptığı gibi kendini tekrar etmeyi bekliyorum.
Bu, her zaman ikinci döngüden sonra gerçekleşmez. Bazen, herhangi bir müdahale olmaksızın (yani cihaza dokunmamak), meydana gelmeden önce birçok döngüden sonra bir süre beklemelidir. Ne zaman olacağını tahmin etmek zor.
Bunun nedeni nedir? Bu konuda nasıl hata ayıklanır?
Özel Yüzey Görünümü için komple kodunun altına Ekli (Bilginize. Ben 'Görünüm' sınıfında 'onDraw'da' aynı algoritmayı kullanabilir. Bu sorun. Hiç olmaz) ve Konu bulunuyor kodu.
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);
setZOrderOnTop(true);
getHolder().setFormat(PixelFormat.TRANSLUCENT);
}
@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);
//canvas.drawColor(0xFFEEEEEE);
if (startCount == 360) startCount= 0;
canvas.drawArc(mShadowBounds,
0, startCount, true, mPiePaint);
}
public void incrementCount() {
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
if (thread != null) {
boolean retry = true;
while (retry) {
try {
thread.setRunning(false); //Tells thread to stop
thread.join(); //Removes thread from mem.
retry = false;
} catch (InterruptedException e) {
// try again shutting down the thread
}
}
thread = null;
}
}
}
Ve Konu sınıfı
class PanelThread extends Thread {
private SurfaceHolder surfaceHolder;
private TimerSurfaceView panel;
private boolean startRunning = false;
public PanelThread(SurfaceHolder surfaceHolder, TimerSurfaceView panel) {
this.surfaceHolder = surfaceHolder;
this.panel = panel;
}
public void setRunning(boolean run) { //Allow us to stop the thread
startRunning = run;
}
@Override
public void run() {
Canvas c;
while (startRunning) { //When setRunning(false) occurs, startRunning 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.incrementCount();
panel.postInvalidate();
}
} finally {
if (c != null) {
surfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
}
Teşekkürler fadden. Size iyi bir açıklama yapabilmeniz için size bir vesile veriyorum ve şu anda yüzey ve görünüm var. SurfaceView'ı kullandığımızda, geçersiz kılmayı ve onDraw'u geçersiz kılmanın önüne geçmemeliyiz? ... Ve her bir yüzeyin her onDraw'ın başlangıcında manuel olarak temizlenmesi gerekiyor mu? – Elye
Üzgünüz, size birkaç tıklamadan sonra bu görünümün yenilenmemesiyle ilgili olarak hala bilmediğim için size bir kene vermedim. – Elye
Invalidate/onDraw, Çizim üzerinde çizim yapmak içindir. Yüzey için lockCanvas/unlockCanvasAndPost'u kullanırsınız. Yüzeyde çizerken, her pikseli kirli doğrultuda (lockCanvas'a ilettiğiniz argüman) güncellemeniz gerekir; null geçiyorsunuz, bu da tüm Canvas'ları silmeniz gerektiği anlamına geliyor. Bu, Yüzey iki veya üç kez tamponlanmış olduğundan gereklidir. Bence güncellemenizin neden başarısız olduğunu tespit ettim; Cevabımı ekleyeceğim. – fadden