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
.. Я имею в виду, что в WebView
можно помещать содержимое ImageView
и TextView
, но как насчет Button
или любых других элементов интерфейса, требующих взаимодействия? Есть ли способ вообще, который мог бы решить такие проблемы, не отказываясь от макета и прокручивая все сразу?
Я узнал, что я не единственный, у кого эта проблема. Для других примеров, проверьте эти вопросы - без рабочего решения:
Ответы
Ответ 1
Проблема связана с аппаратным ускорением, которое включено по умолчанию, если уровень API >= 14.
У меня есть приложение с ScrollView
, которое содержит несколько просмотров, которые я хочу прокрутить, как единое целое, похожее на оригинальный плакат. Один из этих представлений - это веб-представление, которое обертывает его содержимое. Если аппаратное ускорение включено, а отображаемый WebView
вообще сложный (изображения, границы и т.д.), Тогда сообщение об ошибке кэша чертежа можно увидеть в LogCat. На одном экране с 12 элементами работал, а следующий экран с 13 элементами не работал. Я не думаю, что это количество элементов, которые имеют значение, но сложность финального визуализированного экрана.
Симптомы обычно представляют собой пробел WebView
- другие виды визуально присутствуют и полностью формируются. Очень редко я вижу весь экран пустым, но, возможно, это было, пока я был futzing с различными предложениями, найденными здесь на 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-устройства должны быть достаточно быстрыми, чтобы справляться с программным рендерингом. Не то, чтобы мои экраны были сложными.
Обновление APRIL 2015
К сожалению, появилось предупреждающее сообщение о том, что Samsung Galaxy 4 Mini теперь работает 4.4.2, даже если аппаратное ускорение отключено. У меня есть веб-просмотр с открытой/закрытой анимацией на панели JavaScript. Все работает отлично, за исключением того, что первоначальный макет (панель открыта) вызывает эти предупреждения, и каждый раз, когда я закрываю или открываю панель, я также получаю их. Эти предупреждения сейчас просто раздражают, приложение работает нормально.
Ответ 2
Как указывалось в других ответах, проблема возникает, когда аппаратное ускорение активно. Но отключение аппаратного ускорения для всего приложения не было решением для меня.
Я решил, что смогу решить проблему, установив 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>
Обратите внимание, что это может иметь негативные последствия для производительности, поскольку рендеринг в программном обеспечении обычно медленнее.
Ответ 3
webView.setLayerType(WebView.LAYER_TYPE_NONE, null);
работал у меня. В зависимости от аппаратного обеспечения, для дополнительного буферного экрана нет памяти, так как WebView визуализируется полностью, когда он встроен в другое представление прокрутки.
Я считаю ошибкой в Android, что он автоматически не возвращается к этому (медленнее, но работает).
Ответ 4
Я создал что-то подобное, и все, что мне было нужно, это добавить его в мой WebView
:
android:layout_height="match_parent"
Ответ 5
Это работает для меня:
<WebView
android:id="@+id/wv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="horizontal"/>