Android View.getDrawingCache повертає null, тільки null


97

Будь-хто, будь ласка, спробує пояснити мені чому

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!!!
}

ЗАВЖДИ реєструє, що кеш-пам'ять малювання є нульовим, і встановлює біт-карту нульовою?

Чи потрібно насправді малювати подання перед тим, як встановити кеш?

Дякую!


1
stackoverflow.com/questions/9791714/… уникати getDrawingCache()використання View#drawдля Canvasпідходу
Yuraj

Відповіді:


240

У мене також була ця проблема і я знайшов таку відповідь:

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
Вимірювання WebView залежить від розміру вмісту, тому, якщо веб-сторінка ще не завантажена, ви отримаєте міру 0. Спробуйте передати реальний розмір замість НЕВЕРЕДОВАНО, наприклад MeasureSpec.makeMeasureSpec (800, MeasureSpec.EXACTLY);
Marcio Covre

3
Усе одно повертає null навіть за допомогою MeasureSpec.EXACTLY.

На досить великому погляді це для мене не спрацювало. (Можливо, тому, що у мене є телефон з дуже обмеженими ресурсами пам'яті). Відповідь нижче від cV2 для мене добре спрацював.
Simon Forsberg

@nininho як отримати доступ до зображень без використання методу getdrawingchache ()?
Gorgeous_DroidVirus

Це добре працює. Але це впливає на інтерфейс користувача. Будь ласка, допоможіть вирішити цю проблему.
Вівек Раві

58

якщо getDrawingCacheзавжди returning nullхлопці: використовуйте це:

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

Довідка: https://stackoverflow.com/a/6272951/371749


1
Хороший. Цей працював на мене, в той час як інші - ні. Чи є причина використовувати значення getLayoutParamsзамість v.getWidth () та v.getHeight ()?
Саймон Форсберг

вибачте, особисто я не можу вам допомогти з вашим запитанням: '(-> приємно, що це спрацювало :)
cV2

@ cV2 я отримав креслення на зображеннях, але мені потрібно отримати getdrawingcache на запущеному поверховому перегляді .. тоді що я можу робити далі?
Gorgeous_DroidVirus

4
я отримую виняток ширина та висота повинні бути> 0 .............................. private void takeScreenShot () {for (int i = 1; i <4; i ++) {// startDialog (); Перегляд подання = ScreenShotActivity.this.findViewById (R.id.relativelayout); Bitmap bitmap = loadBitmapFromView (view);}}
akash yadav

2
Я думаю, що "ширина і висота винятку повинні бути> 0" виникає, коли ваше ImageViewзображення ще не отримало зображення, тому воно, схоже, дорівнює 0. Це буде відтворюватися по-різному для коду різних людей, але переконайтеся, що ваш дзвінок loadBitmapFromView()обов'язково після у вас ImageViewє зображення.
Azurespot

6

Основна причина, через яку люди отримують нуль, полягає в тому, що вигляд не має розмірів. Усі спроби, використовуючи view.getWidth (), view.getLayoutParams (). Width і т.д., включаючи view.getDrawingCache () та view.buildDrawingCache (), марні. Отже, спочатку потрібно встановити параметри подання, наприклад:

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

(Ви вже встановили "ширину" та "висоту", як вам подобається, або отримали їх за допомогою WindowManager тощо)


Переглянути root = currActivity.getWindow (). GetDecorView (). FindViewById (android.R.id.content); root.setDrawingCacheEnabled (істина); root.layout (0, 0, 480, 854); mBitmap = root.getDrawingCache ();
Narender Gusain

4

Я використовую це замість цього.

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

3

Найкраще працювати 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

Якщо подання, яке ви хочете зловити, дійсно відображається на екрані, але воно повертає нуль. Це означає, що ви ловите подання перед тим, як менеджер вікон створить його. Деякі макети дуже складні. Якщо макет включає вкладені макети, layout_weight..etc, це призводить до того, що кілька разів ретрансляція отримає точно розмір. Найкраще рішення - почекати, поки менеджер вікон закінчить роботу, а потім отримати знімок екрана. Спробуйте помістити getDrawingCache () в обробник.


1

Відповіді @ cV2 та @ nininho працюють на мене.

Однією з інших причин, за якими я з'ясував важкий шлях, було те, що я мав формувати подання, яке має ширину і висоту 0 ( тобто уявіть, що TextView містить текст рядка з порожнього рядка ). У цьому випадку getDrawingCache поверне значення null, тому просто переконайтеся, що це перевірено. Сподіваюся, що хтось допомагає там.


1

Помилка може бути причиною того, що ваш Перегляд занадто великий, щоб вміститись у кеш-пам'ять малювання .

Пояснення моєї проблеми "View.getDrawingCache повертає нуль" із моїх журналів:

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

Документи Android також говорять : пристрої Android можуть мати лише 16 МБ пам'яті, доступної для однієї програми. Ось чому ви не можете завантажувати великі растрові карти.


1

Я намагаюся створити n кількість зображень динамічно на основі перегляду.

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

Я думаю, що цей код комусь допоможе.


-1

Це простий та ефективний спосіб отримати растровий малюнок

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();
    }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.