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

ВСЕГДА регистрирует, что кеш рисования имеет значение NULL, и устанавливает для растрового изображения значение NULL?

Должен ли я рисовать представление до того, как будет установлен кеш?

Спасибо!


Ответы:


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 01

3
По-прежнему возвращает null даже с MeasureSpec.EXACTLY.

При достаточно большом обзоре это не сработало для меня. (Возможно, потому, что у меня телефон с очень ограниченными ресурсами памяти). Ответ ниже cV2 отлично работал у меня.
Саймон Форсберг

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

Это работает хорошо. Но это сказывается на пользовательском интерфейсе. Пожалуйста, помогите решить эту проблему.
Vivek Ravi

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 при запуске SurfaceView .. что мне делать дальше?
Gorgeous_DroidVirus

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

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 ();
Нарендер Гусейн 01

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

Если вид, который вы хотите поймать, действительно отображается на экране, но возвращает значение null. Это означает, что вы ловите представление до того, как оконный менеджер его сгенерирует. Некоторые макеты очень сложные. Если макет включает вложенные макеты, layout_weight..etc, это заставляет ретранслятор несколько раз получить точный размер. Лучшее решение - дождаться завершения работы оконного менеджера, а затем сделать снимок экрана. Попробуйте в обработчике поставить getDrawingCache ().


1

Ответы @ cV2 и @ nininho работают для меня.

Одна из других причин, по которой я узнал на собственном горьком опыте, заключалась в том, что представление, которое у меня было, генерировало представление с шириной и высотой 0 ( т.е. представьте, что у меня есть TextView со строковым текстом пустой строки ). В этом случае getDrawingCache вернет null, поэтому обязательно проверьте это. Надеюсь, что это поможет некоторым людям.


1

Ошибка может быть из-за того, что ваш вид слишком велик, чтобы поместиться в кеш чертежа .

Я получил объяснение моей проблемы "View.getDrawingCache возвращает null" из моих журналов:

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.