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"/>