java.lang.Исключение IllegalArgumentException: ширина и высота должны быть > 0

#android #android-layout #bitmap

#Android #android-layout #растровое изображение

Вопрос:

У меня есть приложение в playstore, которое выдает следующую ошибку на очень немногих устройствах.

 java.lang.IllegalArgumentException: width and height must be amp;> 0
    at android.graphics.Bitmap.createBitmap(Bitmap.java:829)
    at android.graphics.Bitmap.createBitmap(Bitmap.java:808)
    at android.graphics.Bitmap.createBitmap(Bitmap.java:775)
    at com.my.app.fragments.ImageFragment$MyAsyncTask$1.void run()(SourceFile:209)
    at android.os.Handler.handleCallback(Handler.java:745)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:171)
    at android.app.ActivityThread.main(ActivityThread.java:5454)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
    at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:102)
  

Ошибка возникает в этой строке в onPostExecute в MyAsyncTask

 c.drawBitmap(Bitmap.createBitmap(linearLayout.getWidth(), linearLayout.getHeight(), Bitmap.Config.RGB_565), 0, 0, p);
  

Это мой код

В моем ImageFragment in onCreateView я делаю это

     ImageView img = (ImageView) rootView.findViewById(R.id.img);
    final LinearLayout view= (LinearLayout) rootView.findViewById(R.id.view);
    MyAsyncTask asyncTask= new MyAsyncTask(img, view);
    asyncTask.execute(number);
  

Затем в AsyncTask

 class MyAsyncTask extends AsyncTask<Integer, Void, Bitmap> {
        private final WeakReference<ImageView> imageViewReference;
        private LinearLayout linearLayout;

        public MyAsyncTask(ImageView imageView, LinearLayout linearLayout) {
            imageViewReference = new WeakReference<>(imageView);
            this.linearLayout = linearLayout;
        }

        // Decode image in background.
        @Override
        protected Bitmap doInBackground(Integer... params) {

            // Code skipped
            return bitmap;
        }

        @Override
        protected void onPostExecute(Bitmap bitmap) {
            if (bitmap != null) {
                final ImageView imageView = imageViewReference.get();
                if (imageView != null) {
                    imageView.setImageBitmap(bitmap);
                    blurred = CommonUtils.fastblur(bitmap, 0.2f, 20);
                    final Bitmap resultBitmap = Bitmap.createBitmap(blurred.getWidth(), blurred.getHeight(), Bitmap.Config.ARGB_8888);

                    final Canvas c = new Canvas(resultBitmap);
                    c.drawBitmap(blurred, 0, 0, null);

                    final Paint p = new Paint();
                    p.setAlpha(127);

                    linearLayout.post(new Runnable() {
                        @Override
                        public void run() {
                            c.drawBitmap(Bitmap.createBitmap(linearLayout.getWidth(), linearLayout.getHeight(), Bitmap.Config.RGB_565), 0, 0, p);
                            // Rest code skipped
                        }
                    });
                }
            }
        }
    }
  

После прочтения многих сообщений stackoverflow об этой проблеме я обнаружил, что это происходит, если представление еще не готово, и, следовательно, его следует использовать с методом post представления с вашим собственным runnable. Но я не могу понять, почему это все еще вызывает эту ошибку на некоторых устройствах, а именно Samsung . У кого-нибудь есть идея, как это можно исправить? Любое предложение будет оценено. Спасибо!!

Ответ №1:

Ваша задача выполняется слишком быстро на этих устройствах, и LinearLayout макет все еще не был выполнен. Вы можете использовать ViewTreeObserver :

 ViewTreeObserver vto = linearLayout.getViewTreeObserver(); 
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() { 
    @Override 
    public void onGlobalLayout() { 
        linearLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this); 
        int width  = linearLayout.getMeasuredWidth();
        int height = linearLayout.getMeasuredHeight(); 
        c.drawBitmap(Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565), 0, 0, p);
        // Rest code skipped
    }
});
  

Комментарии:

1. Спасибо за ответ. Я бы определенно попробовал это. Кстати, почему ViewTreeObserver должен работать?

2. Потому что вы пытаетесь получить размер макета до того, как макет был вычислен (т. Е. Вы все еще не знаете размеры, потому что Android все еще не вычислил их). ViewTreeObserver позволяет получать обратный вызов, когда это происходит: «View tree observer используется для регистрации прослушивателей, которые могут получать уведомления о глобальных изменениях в дереве просмотра. Такие глобальные события включают, но не ограничиваются, компоновкой всего дерева , началом прохода рисования, изменением режима касания …. » developer.android.com/reference/android/view /…

3. Кстати, я отредактировал ответ, чтобы исправить несколько ошибок в имени переменной.

4. Спасибо за ответ, попробую и приму его, если это сработает, большое спасибо!!