WebView в ScrollView: "Просмотр слишком большой, чтобы поместиться в кэш чертежа" - как переделать макет?
У меня есть макет с ScrollView
, который содержит следующие представления: ImageView
, TextView
, WebView
, TextView
, (Это потому, что я хотел бы прокрутить все вместе, а не только содержимое WebView
)
После загрузки некоторого HTML в WebView
Я получаю следующее:
WARN/View(632): View too large to fit into drawing cache, needs 14236800 bytes, only 1536000 available
... и содержание WebView
не будет отображаться После удаления ScrollView
, предупреждение исчезает, и все хорошо, за исключением того, что я теряю нужную функциональность прокрутки.
Первое: я знаю, что пытаюсь использовать ScrollView
внутри другого ScrollView
в целом это плохо, но я не уверен на 100%, что в каждом случае есть эквивалентное решение без использования ScrollView
... Я имею в виду, конечно, можно положить содержимое ImageView
с и TextView
в WebView
, но что насчет Button
s или любые другие элементы интерфейса, требующие взаимодействия? Есть ли вообще способ решить такие проблемы, не отказываясь от макета и не прокручивая все сразу?
Я узнал, что я не единственный с этой проблемой. Для других примеров, проверьте эти вопросы - пока без рабочего решения:
5 ответов
Проблема связана с аппаратным ускорением, которое по умолчанию включено, если уровень API>= 14.
У меня есть приложение с ScrollView
он содержит несколько представлений, которые я хочу прокрутить как единое целое, похожее на оригинальный постер - одно из этих представлений - это веб-представление, которое оборачивает свое содержимое. Если аппаратное ускорение включено и отображается WebView
в целом сложный (изображения, границы и т. д.), то сообщение об ошибке кэша чертежа можно увидеть в LogCat. Некоторый экран с 12 пунктами работал, в то время как следующий экран с 13 пунктами не работал. Я не думаю, что это количество элементов, которые имеют значение, но сложность окончательного отображения экрана.
Симптомы, как правило, пустые WebView
- другие виды визуально присутствуют и полностью сформированы. Очень редко я вижу весь экран пустым, но это могло случиться, когда я размышлял с различными предложениями, найденными здесь на SO.
Сообщение не всегда видно. Например, я вижу проблему на Samsung Galaxy 4 Mini под управлением 4.2.2, в то время как на других устройствах 4.x, таких как мой дешевый китайский клон Samsung S3 под управлением 4.1.2, все в порядке. Я не видел его ни на одном устройстве 1.x или 2.x.
Я попытался выборочно отключить аппаратное ускорение для различных представлений и макетов в иерархии представлений, но в итоге просто разочаровался в аппаратном ускорении для всего приложения в файле манифеста и увидел, сколько часов я потратил на отслеживание этого.
После отключения аппаратного ускорения все проблемы исчезли. Я не вижу заметных различий в производительности ни на одном из моих устройств. Предположительно, устройства 1.x и 2.x никогда не использовали аппаратное ускорение, и мои устройства 4.x должны быть достаточно быстрыми, чтобы справляться только с программным рендерингом. Не то чтобы мои экраны были такими сложными.
Обновление апреля 2015
К сожалению, предупреждающее сообщение возвращается на Samsung Galaxy 4 Mini, который работает под управлением 4.4.2 даже с отключенным аппаратным ускорением. У меня есть веб-просмотр с анимацией открытия / закрытия панели JavaScript. Все работает нормально, за исключением того, что первоначальный макет (панель открыта) вызывает эти предупреждения, и каждый раз, когда я закрываю или открываю панель, я также получаю их. Эти предупреждения сейчас просто раздражают, приложение работает нормально.
webView.setLayerType(WebView.LAYER_TYPE_NONE, null);
работал на меня. В зависимости от аппаратного обеспечения, не хватает памяти для дополнительного внеэкранного буфера, поскольку WebView отображается полностью, когда встроен в другое представление прокрутки.
Я считаю ошибкой в Android то, что она автоматически не прибегает к этой (более медленной, но работающей) опции.
Как уже говорилось в других ответах, проблема возникает при активном аппаратном ускорении. Но отключение аппаратного ускорения для всего приложения не было для меня решением.
Я решил, что смогу решить проблему, установив android:layerType="software"
к ScrollView
, который просто отключает аппаратное ускорение для ScrollView
и его содержание.
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layerType="software">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
...
</FrameLayout>
<WebView
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</ScrollView>
Обратите внимание, что это может иметь негативные последствия для производительности, поскольку рендеринг в программном обеспечении обычно медленнее.
Я создал что-то подобное, и все, что мне нужно было добавить это к моему WebView
:
android:layout_height="match_parent"
Это работает для меня:
<WebView
android:id="@+id/wv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="horizontal"/>