Android View.getDrawingCache zwraca wartość null, tylko wartość null


97

Czy ktoś mógłby mi spróbować wyjaśnić dlaczego

public void addView(View child) {
  child.setDrawingCacheEnabled(true);
  child.setWillNotCacheDrawing(false);
  child.setWillNotDraw(false);
  child.buildDrawingCache();
  if(child.getDrawingCache() == null) { //TODO Make this work!
    Log.w("View", "View child's drawing cache is null");
  }
  setImageBitmap(child.getDrawingCache()); //TODO MAKE THIS WORK!!!
}

ZAWSZE rejestruje, że pamięć podręczna rysunku ma wartość null, i ustawia wartość mapy bitowej na wartość null?

Czy muszę narysować widok przed ustawieniem pamięci podręcznej?

Dzięki!


1
stackoverflow.com/questions/9791714/ ... unikaj getDrawingCache()używania View#drawdo Canvaspodejścia
Yuraj

Odpowiedzi:


240

Miałem również ten problem i znalazłem odpowiedź:

v.setDrawingCacheEnabled(true);

// this is the important code :)  
// Without it the view will have a dimension of 0,0 and the bitmap will be null          
v.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), 
            MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight()); 

v.buildDrawingCache(true);
Bitmap b = Bitmap.createBitmap(v.getDrawingCache());
v.setDrawingCacheEnabled(false); // clear drawing cache

1
Pomiar WebView zależy od rozmiaru zawartości, więc jeśli strona internetowa nie jest jeszcze załadowana, otrzymasz miarę 0. Spróbuj przekazać rzeczywisty rozmiar do pomiaru zamiast UNSPECIFIED, jak MeasureSpec.makeMeasureSpec (800, MeasureSpec.EXACTLY);
Marcio Covre

3
Nadal zwraca wartość null, nawet z MeasureSpec.EXACTLY.

Przy wystarczająco dużym widoku to nie zadziałało. (Możliwe, że mam telefon z bardzo ograniczonymi zasobami pamięci). Odpowiedź poniżej przez cV2 działała dobrze dla mnie.
Simon Forsberg

@nininho jak uzyskać możliwość rysowania z imageview bez użycia metody getdrawingchache ()?
Gorgeous_DroidVirus

To dobrze działa. Ale ma to wpływ na interfejs użytkownika. Proszę o pomoc w rozwiązaniu tego problemu.
Vivek Ravi

58

jeśli getDrawingCacheto zawsze returning nullfaceci: użyj tego:

public static Bitmap loadBitmapFromView(View v) {
     Bitmap b = Bitmap.createBitmap( v.getLayoutParams().width, v.getLayoutParams().height, Bitmap.Config.ARGB_8888);                
     Canvas c = new Canvas(b);
     v.layout(0, 0, v.getLayoutParams().width, v.getLayoutParams().height);
     v.draw(c);
     return b;
}

Źródła: https://stackoverflow.com/a/6272951/371749


1
Dobry. Ten pracował dla mnie, podczas gdy inne nie. Czy jest jakiś powód, aby używać wartości z getLayoutParamszamiast v.getWidth () i v.getHeight ()?
Simon Forsberg

przepraszam, osobiście nie mogę Ci pomóc z pytaniem: '(-> fajnie, że zadziałało :)
cV2

@ cV2 Mam rysunek na obrazach, ale muszę pobrać getdrawingcache podczas uruchamiania surfaceview .. co mogę teraz zrobić?
Gorgeous_DroidVirus

4
Otrzymuję wyjątek szerokość i wysokość muszą być> 0 .............................. private void takeScreenShot () {for (int i = 1; i <4; i ++) {// startDialog (); Widok widoku = ScreenShotActivity.this.findViewById (R.id.relativelayout); Bitmap bitmap = loadBitmapFromView (zobacz);}}
akash yadav

2
Myślę, że `szerokość i wysokość wyjątku muszą być> 0` pojawia się, gdy ImageViewnie otrzymałeś jeszcze obrazu, więc wydaje się, że jest równe 0. To wyglądałoby inaczej dla kodu różnych osób, ale upewnij się, że wywołanie loadBitmapFromView()jest zdecydowanie po Twój ImageViewzawiera obraz.
Azurespot

6

Podstawowym powodem uzyskania wartości zerowej jest to, że widok nie jest zwymiarowany. Wszystkie próby użycia view.getWidth (), view.getLayoutParams (). Width itp., W tym view.getDrawingCache () i view.buildDrawingCache (), są bezużyteczne. Dlatego musisz najpierw ustawić wymiary do widoku, np:

view.layout(0, 0, width, height);

(Już ustawiłeś 'szerokość' i 'wysokość' jak chcesz lub otrzymałeś je z WindowManager, itp.)


Wyświetl root = currActivity.getWindow (). GetDecorView (). FindViewById (android.R.id.content); root.setDrawingCacheEnabled (true); root.layout (0, 0, 480, 854); mBitmap = root.getDrawingCache ();
Narender Gusain

4

Zamiast tego używam tego.

myView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            Bitmap bitmap = Bitmap.createBitmap(myView.getDrawingCache());
        }
    });

3

Pracuj najlepiej 4me

    Bitmap bitmap = Bitmap.createBitmap( screen.getMeasuredWidth(), screen.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap);
    screen.layout(0, 0, screen.getMeasuredWidth(), screen.getMeasuredHeight());
    screen.draw(canvas);

2

Jeśli widok, który chcesz złapać, naprawdę pojawia się na ekranie, ale zwraca wartość null. Oznacza to, że przechwytujesz widok, zanim Menedżer okien go wygeneruje. Niektóre układy są bardzo skomplikowane. Jeśli układ zawiera zagnieżdżone układy, layout_weight..etc, powoduje kilka razy, że relayout uzyskuje dokładny rozmiar. Najlepszym rozwiązaniem jest poczekanie, aż menedżer okien zakończy pracę, a następnie wykonanie zrzutu ekranu. Spróbuj umieścić getDrawingCache () w module obsługi.


1

Odpowiedzi @ cV2 i @ nininho działają dla mnie.

Jednym z innych powodów, dla których odkryłem na własnej skórze, było to, że widok, który miałem, generował widok o szerokości i wysokości 0 ( tj. Wyobraź sobie, że masz TextView z tekstem łańcucha pustego ciągu ). W takim przypadku getDrawingCache zwróci wartość null, więc po prostu sprawdź to. Mam nadzieję, że to pomoże niektórym ludziom.


1

Błąd może być spowodowany tym, że widok jest zbyt duży, aby zmieścić się w pamięci podręcznej rysunków .

Otrzymałem wyjaśnienie mojego problemu „View.getDrawingCache zwraca wartość null” z moich dzienników:

W/View: View too large to fit into drawing cache, needs 19324704 bytes, only 16384000 available

Dokumentacja systemu Android mówi również : urządzenia z systemem Android mogą mieć zaledwie 16 MB pamięci dostępnej dla jednej aplikacji. Dlatego nie możesz załadować dużej mapy bitowej.


1

Próbuję utworzyć liczbę n obrazów dynamicznie na podstawie widoku.

LayoutInflater infalter=(LayoutInflater)getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final View addview=infalter.inflate(R.layout.barcode_image_list_row_item, null);
final ImageView imv=(ImageView) addview.findViewById(R.id.imageView1);
final TextView tv=(TextView) addview.findViewById(R.id.textView1);

try {         
    final Bitmap bitmap = encodeAsBitmap(""+value, BarcodeFormat.CODE_128, 600, 300);

    if (bitmap != null) {
        // TODO Auto-generated method stub
        imv.setImageBitmap(bitmap);
        tv.setText(value);

        addview.setDrawingCacheEnabled(true);

        // this is the important code :)  
        // Without it the view will have a dimension of 0,0 and the bitmap will be null          
        addview.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), 
                        MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
        addview.layout(0, 0, addview.getMeasuredWidth(), addview.getMeasuredHeight()); 

        addview.buildDrawingCache(true);
        Bitmap b = Bitmap.createBitmap(addview.getDrawingCache());
        addview.setDrawingCacheEnabled(false); // clear drawing cache
        // saving the bitmap   
        savebarcode(b,value);
    }
} catch (WriterException e) {
    e.printStackTrace();
}

Myślę, że ten kod komuś pomoże ...


-1

To prosty i skuteczny sposób na uzyskanie mapy bitowej

public void addView(View v) {
        v.setDrawingCacheEnabled(true);
        v.buildDrawingCache();

        Bitmap bitmap = v.getDrawingCache();

        if(bitmap == null) {
            // bitmap is null
            // do whatever you want
        } else {
            setImageBitmap(bitmap);
        }
        v.setDrawingCacheEnabled(false);
        v.destroyDrawingCache();
    }
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.