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"/>
Другие вопросы по тегам