Эффективные «скриншоты» представления?

17

TL; DR: поскольку getDrawingCache() , по-видимому, запускает полную перерисовку View при включенном аппаратном ускорении, есть ли альтернативный способ получения Bitmap (или чего-то подобного), который избегает этого, возможно, путем чтения данных, помещенных в (аппаратный, программный) слой, когда View был последний раз нарисован?

Немного предыстории:

В Android появилась возможность зеркального отображения экрана начиная с Android 3.0, например, на подключенном дисплее HDMI. Это можно использовать для презентаций, но это означает, что аудитория видит то же самое, что и докладчик, что не всегда идеально.

В Android 4.2 добавлено Presentation , чтобы приложения могли размещать произвольные элементы на «втором экране» (например, при подключенном дисплее HDMI). В этом случае иногда было бы полезно, чтобы на втором экране отображалось часть того, что находится на дисплее основного планшета. Если вы думаете о программном обеспечении для презентаций, таком как Microsoft PowerPoint, LibreOffice Impress и т. П., В типичных двухэкранных установках аудитория видит текущий слайд презентации, в то время как докладчик видит текущий слайд, а также отметки времени и заметки докладчика и ...

Для неинтерактивного контента, такого как PNG, представляющего слайд, это просто вопрос показа одного и того же изображения на обоих экранах (наряду с другими материалами на основном экране).

Однако для интерактивного контента, такого как WebView , иногда бывает сложно выполнить такое зеркалирование. Например, у нас нет хорошего способа узнать, когда содержимое WebView может измениться, поскольку это может происходить на основе материала, находящегося исключительно внутри самого WebView (например, завершение вызовов AJAX), а не того, что мы делаем отдельно. , И даже если бы мы знали , когда изменилось содержимое WebView , у нас нет хорошего способа получить какой-то другой WebView для рендеринга того же содержимого.

Итак, я решил, что попытаюсь установить MirroringFrameLayout , который будет использовать getDrawingCache() для извлечения Bitmap содержимого контейнера и передачи его кому-то, кто может отобразить его на экране (например, ImageView отображается в Presentation ).

Однако, с включенным аппаратным ускорением, setDrawingCacheEnabled(true) является чем-то нет -op :

Enabling the drawing cache is similar to setting a layer when hardware acceleration is turned off. When hardware acceleration is turned on, enabling the drawing cache has no effect on rendering because the system uses a different mechanism for acceleration which ignores the flag.

Вызов getDrawingCache() в этих случаях приводит к полному draw() View с битовой поддержкой Canvas , а не с использованием кеша. Так как draw() может быть дорогим, выполнение draw() часто (скажем, срабатывает через postOnAnimation() ) приводит к джанку.

Поэтому я пытаюсь определить, существует ли какой-либо другой «кэш чертежа», кроме getDrawingCache() , который мы можем использовать с включенным аппаратным ускорением, который можно использовать для настройки этого зеркалирования, и это более эффективно. Из того, что я вижу, такого кеша нет, поскольку слои фактически доступны только для записи с точки зрения приложений SDK. Однако я надеюсь, что, возможно, мне не хватает какого-то решения.

Заранее спасибо!

    
задан CommonsWare 21.03.2013 в 16:04
источник
  • FYI, вот репозиторий GitHub, содержащий мою реализацию: github.com/commonsguy/cwac-layouts –  CommonsWare 09.04.2013 в 22:38

1 ответ

13

Вы можете использовать setLayerType(View.LAYER_TYPE_SOFTWARE, null) , но побочным эффектом будет замедление перерисовки этого представления при каждом обновлении. Было бы намного эффективнее создать пользовательский ViewGroup , который будет рисовать ваше представление на двух холстах (по одному для каждого экрана). Вы также можете просто использовать ViewTreeObserver и при каждом обратном вызове отрисовки заставлять ваше представление отображаться на втором экране. , Я действительно рекомендую вам не пытаться злоупотреблять кэшем чертежа / типом слоя для такого случая использования.

    
ответ дан Romain Guy 21.03.2013 в 16:31
  • Безопасно ли мне отображать отдельный холст из onDraw () в пользовательской группе ViewGroup? –  CommonsWare 21.03.2013 в 16:48
  • До тех пор, пока это из потока пользовательского интерфейса, да. –  Romain Guy 21.03.2013 в 17:38
  • ОК, пока это работает. Следующий проект: получение правильного масштабирования, так как размер зеркала не может быть идентичен размеру оригинала. Чтобы процитировать страницу «Масштабирование взгляда», «Yay, math». :-) Благодаря! –  CommonsWare 21.03.2013 в 18:00
  • Привет, Android имеет возможность отображать экран с Android 3.0, например, на подключенном HDMI-дисплее. Имеет ли андроид возможность выбирать, для каких слоев нужно зеркалировать, скажем, виртуальный дисплей? –  nmxprime 13.07.2016 в 17:04