“Полотно: намагається намалювати занадто великий растровий малюнок”, коли розмір дисплея Android N встановлений більше, ніж Малий


83

У мене є опублікований додаток, який аварійно завершує роботу під час запуску на Android N, коли нещодавно введене Display sizeналаштування ОС встановлено як занадто велике.

Коли я заглядаю в logcat, я бачу таке повідомлення:

java.lang.RuntimeException: Canvas: trying to draw too large(106,975,232 bytes) bitmap.

Я простежив проблему до ImageView у першій діяльності, що показує приємне велике фонове зображення. Зображення, про яке йде мова, має розмір 2048x1066 і знаходиться в моєму загальному drawablesкаталозі, тому незалежно від щільності воно буде використано.

Все працює нормально, коли Display sizeналаштування встановлено Small. Але коли я піднімаюся Default, він перестає працювати. Якщо потім я поміняю зображення на менше, воно працює Default, але якщо я підійду Large, воно знову перестане працювати.

Я припускаю, що регулювання Display sizeвгору змушує ваш пристрій поводитися як фізично менший пристрій з більшою щільністю пікселів. Але я не розумію, що я маю тут робити. Якщо я вкладаю поступово менші зображення для поступово вищої роздільної здатності, це не буде добре виглядати на насправді великих дисплеях. Або я чогось не розумію?

Будь-які вказівки були б дуже вдячні.


25
"Зображення, про яке йде мова, має розмір 2048x1066 і знаходиться в моєму загальному каталозі малюнків, тому незалежно від щільності воно буде використано" - res/drawable/це синонім res/drawable-mdpi/. Якщо ви хочете, щоб зображення не масштабувалося на основі щільності, використовуйте res/drawable-nodpi/абоres/drawable-anydpi/ .
CommonsWare

3
"Ви хочете сказати, що зображення розміром 100x100 пікселів, що живе в різних каталогах ресурсів, насправді масштабується, щоб створити його віртуальну версію з різною роздільною здатністю, перш ніж переходити до макета?" - це залежить від щільності у вас і на якому пристрої ви працюєте. Якщо є точний збіг, нічого не передискретизується. Якщо немає точного збігу, зображення сусідньої щільності передискретизується. Отже, якщо у вас є лише res/drawable/foo.png(він же res/drawable-mdpi/foo.png), а ваш пристрій є xhdpi, зображення буде подвоєне по обох осях, забираючи в 4 рази більше пам'яті.
CommonsWare

4
Значення 106975232 у вашій помилці виявляється рівно 49-кратним дозволом зображення, що передбачає 7-кратну повторну вибірку по обох осях. Це набагато вище, ніж я міг би очікувати. Я ще не мав можливості пограти з налаштуваннями розміру дисплея в Android 7.0, тож додам це до свого постійно зростаючого списку справ ...
CommonsWare

6
Приємний улов на 49x! Думаю, я можу пояснити, чому вона така висока. Майте на увазі, що це число - байти. Це зображення є 24-бітним, але воно, ймовірно, зчитується із 32 бітами на піксель. Це зробить 8732672 байта в пам’яті, що входить у цю цифру рівно 12,25 рази, що, в свою чергу, передбачає масштабування в 3,5 рази по кожній осі. Цей пристрій xxhdpi, тому, здається, це могло бути приблизно правильно. У будь-якому випадку, я навіть не здогадувався, що ресурси будуть перероблені таким чином. Дякуємо за допомогу! (До речі, переміщення зображення до drawable-nodpi справді це виправляє.)
Брайан Рак,

1
Ви дійсно повинні прийняти відповідь Джохана
С. Джейкоб Пауелл,

Відповіді:


167

Я мій випадок, переміщаючи (Hi-Res) сплеск растрового зображення з Drawable з розтяжною-xxhdpi було рішення.

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

Екран заставки у моєму випадку має роздільну здатність xxhdpi, і його помилково помістили у малюнок папки, замість витяжки-xxhdpi . Це змусило Android припустити, що заставний екран має роздільну здатність mdpi і масштабує зображення до 3 * 3 рази, ніж це потрібно, і намагається створити растрове зображення.


1
я здогадуюсь: отже, андроїд масштабує зображення з xxhdpi на hdpi, наприклад, щоб було світліше зображення? як ви сказали з 3 * 3 -> 1/1 до 1/3, наприклад?
Ninja Coding

Як зазначає kalsara Magamage, це зараз mipmap-xxhdpi.
Дана Робінсон,

37

Я вирішив проблему після додавання наведеного нижче коду до тегу програми файлу маніфесту між рядками android:.

android:hardwareAccelerated="false"

3
Ну, витративши кілька годин, це рішення працює для проблем з мобільними телефонами xiaomi та Samsung.
Шихаб Уддін,

4
Це призведе до відключення всіх висот CardView. Тож правильним рішенням буде масштабування растрового зображення до меншого розміру.
Sachin Soma

1
Замість того, щоб вимикати апаратне прискорення на рівні програми, керуючи ним у Activity, Window, View, рівень корисності буде більш корисним.
Мухаммадшер

1
Але є ще якась проблема, яка виникає після цього android:hardwareAccelerated="false" . показує непарний вигляд на якомусь пристрої з рівнем API нижче 22.
Принц Долакія,

3
Не робіть цього, це уповільнює роботу вашої програми.
Куріо

11

Не знаю, чи комусь це допоможе, але я просто залишу це тут. У моєму випадку - проблема була лише на пристроях Sumsung з Android 7, і проблема полягала в пропорціях заставки. після зміни висоти до 1024 пікселів - все працює нормально


Моєю проблемою було растрове зображення (jpg, png) у папці, що можна малювати (без суфікса). Це моя дурість, але, можливо, це комусь допомагає :-)
гінго

Це корисно! Та сама проблема лише у Samsung ... Що у вас було спочатку і як ви її виправили?
M'hamed

Ви намагалися завантажити зображення з URL-адреси. Я стикаюся з тією ж проблемою лише з Samsung Galaxy S6 на Android 7. Я завантажую зображення в RecyclerView. Я все ще не можу цього зрозуміти. @ M'hamed
Rohit Singh

9

Перемістіть своє зображення в графічний файл в mipmap-xxhdpi. Ваше зображення має формат растрових зображень, тому ви повинні помістити своє зображення в папку mipmap, тоді воно буде працювати


1
AFAIK папка mipmap призначена лише для піктограм панелі запуску. Я ніколи не використовував його ні для чого іншого. Дивіться stackoverflow.com/a/28065664/4034572
Альберт Віла Кальво

Так, це спрацювало для мене. У мене були розміри зображень близько 1 Мб, і я розмістив їх у mipmap-xxhdpi


3

якщо ви використовуєте Пікассо, перейдіть на Glide, як це.

Видалити Пікассо

Picasso.get().load(Uri.parse("url")).into(imageView)

Змінити ковзання

Glide.with(context).load("url").into(imageView)

Більш ефективний


Я все ще отримую помилку навіть після переходу на Glide від Пікассо. На телефоні Samsung J6. І Moto Z2 :(
Рохіт Сінгх,

2

Є кілька сценаріїв, коли оригінальний растровий малюнок потрібно втягувати в ImageViews, програми для редагування фотографій тощо ...,

як відсік, згаданий вище

android:hardwareAccelerated="false"

спричинить поганий досвід користувальницького інтерфейсу, Ви можете встановити hardwareAccelerated Лише одну вибрану діяльність, де буде намальовано зображення з високою роздільною здатністю

<application android:hardwareAccelerated="true">
    <activity ... />
    <activity android:hardwareAccelerated="false" />
</application>

0

Файли піктограм занадто великі, щоб Android могла ефективно та плавно завантажувати їх. Android визнає це за допомогою своїх розумних алгоритмів.

Ви можете змінити розмір файлів значків за допомогою Final Android Resizer by asystat. Змініть їх розмір до "xhdpi" або нижче.

Розмістіть розміри фотографій у малюнку або перезапишіть їх над наявними великими файлами значків.

Тоді все готово.


0

якщо ви використовуєте glide і ви завантажуєте 1k зображень за раз або деякі зображення, то це проблема glide або що ви робите для використання для встановлення подання зображення. ви можете вирішити це, просто застосувавши тип масштабу в glide.


0

У моєму випадку я просто змінив полотно зображення, яке використовується у фоновому режимі за допомогою Paint3d (або ви можете використовувати будь-яке інше). Тут я ділюся скріншотом, просто пройдіть його.


Будь ласка, використовуйте коментарі, щоб поділитися своїми думками.
Аджай Сіван,

0

це вирішується зменшенням розміру зображень до нижчого розміру.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.