8

在此代碼中,我想在兩個ImageView的頂部之間畫一條線。但是,在運行應用程序時,在調用invalidate()之後,自定義視圖顯示爲純黑色。Android自定義視圖在調用無效後顯示純黑色

這裏是我的代碼:

public class ArrowView extends RelativeLayout { 
    public Paint paint; 
    public Bitmap eraser; 
    public Canvas cacheCanvas; 

    public float leftX; 
    public float leftY; 

    public float rightX; 
    public float rightY; 

    public boolean update = false; 

    public ImageView iv_leftArrow; 
    public ImageView iv_rightArrow; 

    private int w; 
    private int h; 

    LayoutInflater mInflater; 

    public ArrowView(Context context) { 
     super(context); 
     this.setWillNotDraw(false); 
     mInflater = LayoutInflater.from(context); 
     init(); 
    } 

    public ArrowView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     this.setWillNotDraw(false); 
     mInflater = LayoutInflater.from(context); 
     init(); 
    } 

    public ArrowView(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
     this.setWillNotDraw(false); 
     mInflater = LayoutInflater.from(context); 
     init(); 
    } 

    @Override 
    public void onSizeChanged(int w, int h, int oldW, int oldH) { 
     this.w = w; 
     this.h = h; 
     super.onSizeChanged(w, h, oldW, oldH); 
    } 

    public void init() { 
     View v = mInflater.inflate(R.layout.arrow_view, this, true); 
     paint = new Paint(Paint.ANTI_ALIAS_FLAG); 
     paint.setColor(Color.BLACK); 
     paint.setStrokeWidth(5); 
     v.setBackgroundColor(Color.TRANSPARENT); 

     eraser = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); 

     iv_leftArrow = (ImageView) v.findViewById(R.id.iv_leftarrow); 
     iv_rightArrow = (ImageView) v.findViewById(R.id.iv_rightArrow); 

     cacheCanvas = new Canvas(); 
     cacheCanvas.setBitmap(eraser); 
    } 

    public void setCoordinates(float leftX, float leftY, float rightX, float rightY) { 
     this.leftX = leftX; 
     this.leftY = leftY; 
     this.rightX = rightX; 
     this.rightY = rightY; 
    } 

    @Override 
    public void onDraw(Canvas c) { 
     super.onDraw(c); 
     setCoordinates(iv_leftArrow.getX() + iv_leftArrow.getWidth()/2, iv_leftArrow.getY(), iv_rightArrow.getX() + iv_rightArrow.getWidth()/2, iv_rightArrow.getY()); 
     if (update) { 
      c.drawLine(leftX, leftY, rightX, rightY, paint); 
      update = false; 
     } 
     cacheCanvas.drawPath(p, paint); 
    } 
} 

有什麼理由自定義視圖顯示調用invalidate()後爲純黑色?

+1

你在哪裏設置「更新」爲true? –

+0

在調用'invalidate()'之前,我從我的'CollectingDetail'活動中設置了它。也許我會在調用CollectingDetail中的setArrow()之前調用它。 –

+0

在最後一行:'cacheCanvas.drawPath(p,paint);'你怎麼能找到** p **的值? –

回答

0

如您所知,invalidate()用於通過致電onDraw來更新視圖。

我認爲你在做的是在更新設置爲true之前調用它 - 所以你的onDraw方法通過聲音的錯誤更新運行。

1

通常,系統會自動爲您的小部件處理調整大小,隱藏,顯示和大量其他內容,但如果繪製像素或後備數據的底層緩衝區已更改或陳舊(有時會交換圖像資源在視圖上或原始數據集更改)。發生這種情況的原因是操作系統無法知道數據是以特定方式更改的。

在您處理繪圖的這些情況下,您必須通過Widget.invalidate()告訴系統它的底層數據不處於良好狀態,並且重繪在主線程上像您一樣排隊提及。根據系統實現和Android版本,跟蹤系統更改的內容會有所不同,但我通常所做的是假定系統資源(字節數組,字符數組,資源索引,上下文的手動繪圖)未被跟蹤,並且需要無效其他一切都將由系統處理。

來源:When it's necessary to execute invalidate() on a View?