ListView один из наиболее распространенных Андроид виджетов. Он очень гибок и легок в использовании, и невероятно мощный, но иногда бывает сложным для понимания.
Одна из особенностей связанных с ListView возникает, когда вы решили использовать измененный цвет фона. По умолчанию, как и большинство виджетов, в ListView установлен прозрачный фон, что означает, вы можете видеть объекты находящиеся за ним. По умолчанию установлен темно серый цвет (#FF191919 с темной темой.) Так же, ListView позволяет использовать затухание краев, для обозначения того что список не закончился, это показано на скриншоте ниже:

list_fade_1

Эффект затухания выполнен с использованием комбинации Canvas.saveLayerAlpha() и Porter-Duff Destination Out blending mode. Эта техника похожа на те которые объяснялись в Filthy Rich Clients и в других презентациях. К сожалению, выглядит это все с использованием измененного цвета фона не красиво. Следующие два сриншота показывают что происходит при изменении фона окна. На левой картинке показано как это выглядит по умолчанию, а на правой показан список во время прокрутки его пальцем:

list_fade_2list_fade_3

Проблема возникает из за оптимизации Android framework, включенного по умолчанию на всех экземплярах ListView (по какой то из причин я забыл включить его по умолчанию на GridView.) Как я уже упоминал ранее, эффект затухания выполнен с использованием режима Porter-Duff blending mode. Такая реализация работает очень хорошо, но к сожалению очень требовательна к ресурсам.

Так как ListView наиболее часто используется на сплошном фоне, больше нет причин использовать этот режим. Поэтому мы хотим вам представить оптимизацию, которая называется «cache color hint.» Сache color hint это цвет в RGB установленный по умолчанию для фона окна, в темной теме для Андроида это #191919. Когда он установлен, ListView (ввобщето его базовый класс View) знает, что будет рисоваться на сплошном фоне и поэтому заменяет ресурсоемкий saveLayerAlpha()/Porter-Duff рендеринг на простой градиент. Этот градиент идет от полностью прозрачного до значения установленного в cache color hint, пример можно посмотреть выше, список с темным градиентом внизу. Однако, это не объясняет, почему весь список становится черным при прокручивании.

Как я сказал до этого, ListView имеет прозрачный/полупрозрачный фон по умолчанию, как и все виджеты в андроид. Это значит что когда ListView перерисовывает своих детей, должен смешивать фон детей с фоном окна. Но эта операция очень ресурсоемкая. Для увеличения быстродействия прокрутки, Андроид фреймворк переиспользует cache color hint. Когда этот хинт установлен, фреймворк копирует каждого ребенка списка в Bitmap заполненный цветом значения из hint (это означает что другая оптимизация, называемая scrolling cache, не отключена.) ListView после этого выкидывает эти битмапы прямо на экран, потому что они должны быть не прозрачными и никакого смешивания не требуется. С тех пор как значения цвета в cache color hint установлен в #191919, у вас получается темный фон под каждым элеменом при прокрутке.

Что бы это исправить, нужно просто запретить cache color hint оптимизацию, если вы используете не однотонный фон или установить в хинт подходящий однотонный цвет. Это можно сделать в коде через setCacheColorHint или, что более предпочтительно, через XML, используя атрибут android:cacheColorHint. Для отключения оптимизации, просто укажите прозрачный цвет #00000000. На следующем снимке экрана показан список с атрибутом android:cacheColorHint=»#00000000" установленный через XML layout файл:

list_fade_4

Как вы можете видеть затухание работает отлично даже с деревянным фоном. Свойство cache color hint, мне показалось интересным, потому что оно показывает как оптимизация может сделать непростой жизнь программистов. Однако польза от стандарного поведения виджетов, перевешивает добавляемую сложность для разработчиков. На этом хотелось бы закончить.

Автор Romain Guyб, личный блог автора www.curious-creature.org
Перевел vovkab.

Google Bookmarks Digg I.ua Linkstore Myscoop Communizm Ru-marks Webmarks Ruspace Linkomatic Kli.kz Web-zakladka Zakladok.net Reddit delicious Ma.gnolia Technorati Slashdot Yahoo My Web News2.ru БобрДобр.ru Ваау! Memori.ru rucity.com МоёМесто.ru Mister Wong
by vovkab Комментириев (5) »
Рубрики: Статьи | Метки: , ,

5 Комментириев в теме “Почему мой ListView черный? Андроид оптимизация.”

  1. Orpheus:

    А как сделать лист подобный последней картинке с книгами? Чтобы на одной строке отображались два (три) элемента списка?

  2. Orpheus:

    GridView справился с задачей

  3. FrostFT:

    а есть возможность делать вложенные списки? в 2м и 3м уровнем вложенности?

  4. JuniorDeveloper:

    Блин, парни, вообще выручили, спасибо большое! Кучу времени убил на разбор траблы почему список черым становится при скролле — ладно на вашу статью наткнулся.

  5. Alex:

    Rabotaet !!!!!!!!


Оставить комментарий

Вы должны залогинитсья, что бы оставить комментарий.