8

W tym kodzie chciałbym narysować linię między dwoma najwyżej położonymi obrazami. Jednak po uruchomieniu aplikacji niestandardowy widok jest wyświetlany na czarnym tle po wywołaniu invalidate().Niestandardowy widok Androida wyświetla się na czarno po wywołaniu unieważniaj

Oto mój kod:

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); 
    } 
} 

Czy jest jakiś powód, dla którego widok niestandardowy jest wyświetlany jako stałe czarnym po wywołaniu invalidate()?

+1

Gdzie można ustawić "Update" true? –

+0

Ustawiam go z mojej działalności 'CollectingDetail' tuż przed wywołaniem' invalidate() '. Być może spróbuję wywołać to przed wywołaniem 'setArrow()' w CollectingDetail. –

+0

W ostatnim wierszu: 'cacheCanvas.drawPath (p, paint) ;, jak mogłeś znaleźć wartość ** p **? –

Odpowiedz

0

Jak wiadomo, invalidate() służy do aktualizacji widoku przez połączenie z numerem onDraw.

To, co myślę, że robisz, to było wywoływanie go przed ustawieniem aktualizacji na true - więc twoja metoda onDraw została uruchomiona z fałszywą aktualizacją przez dźwięki tego.

1

Zwykle system automatycznie zmienia rozmiar, ukrywanie, pokazywanie i wiele innych rzeczy dla widgetów, ale czasami ma problemy, jeśli bufor bazowy dla narysowanych pikseli lub danych kopii zapasowej zmienił się lub jest nieaktualny (zamieniasz zasób obrazu w widoku lub zmianach surowych zbiorów danych). Dzieje się tak, ponieważ nie ma sposobu, aby system operacyjny mógł wiedzieć, że dane zmieniły się w określony sposób.

W tych przypadkach, gdy masz do czynienia z rysowaniem, musisz poinformować system, że jego dane bazowe nie są w dobrym stanie z Widget.invalidate(), a ponowne rysowanie zostanie umieszczone w kolejce w głównym wątku, tak jak Ty wzmiankowany. W zależności od implementacji systemu i wersji systemu Android, śledzenie zmian w systemie jest różne, ale normalnie zakładam, że zasoby systemowe (tablice bajtów, tablice znaków, indeksy zasobów, ręczne rysowanie w kontekście) nie są śledzone i wymagają unieważnienia a wszystko inne będzie obsługiwane przez system.

Źródło: When it's necessary to execute invalidate() on a View?