티스토리 뷰

리스트 화면이 사라졌어요.

개발할 때 많이 쓰는 것 중 하나인 리스트 뷰
배경은 희색, 글자색은 검정색으로 설정했는데 리스트를 스크롤 하면 리스트뷰가 검은색이 되면서 아무것도 보이지 않는다. 뭐니 이게???
화면을 유심히 들여다 보니 구분선은 흐릿하게 보였다. 아무래도 스크롤시 배경색이 검은색으로 바뀌는 것 같다...

어찌할꼬???

음..다행이 이 상황은 많은 사람들이 겪는 문제인가 보다. Android developer 사이트에 이 문제에 대한 해결책이 나와있다.
한 번 살펴보자.^^(난번역...ㅠㅠ;;)

ListView Backgrounds: An Optimization

ListView 에서 가장 많이 발생되는 공통적인 문제 중 하나는 사용자정의 백그라운드를 사용할 때 이다. 많은 안드로이드 위젯들처럼 기본적으로 ListView 는 투명 백그라운드를 사용한다. 이 말은 기본 윈도우의 백그라운드 (매우 검은 회색(#FF191919 with the current dark theme)) 을 보게된다는 것이다. 추가로 ListView는 fading edges를 기본으로 사용한다. 따라서 다름과 같은 화면을 볼 수 있다. — 첫번째 글자 아이템은 점차로 검은색 속으로 사라진다. 이 기술은 컨테이너가 스크롤 되는 것을 나타내기 위해 시스템을 통해 사용된다.

Android's default ListView

사라짐 효과는 Canvas.saveLayerAlpha() 와 the Porter-Duff Destination Out blending mode 의 조합을 이용해 구현하다.

불행히도, 이것은 ListView 에서 사용자 백그라운드를 사용할 때나 윈도우의 배경을 바꿀 때 어그러진다. 다음 두 화면은 윈도우의 배경을 바꿨을 때를 보여준다. 왼쪽 화면은 기본 모습이고 오른쪽 화면은 터치 제스쳐로 스크롤할 때를 나타낸다.

Dark fade Dark list

이 렌더링 문제는 안드로이드 프레임워크가 기본으로 리스트뷰의 모든 인스턴트에 적용한 최적화때문에 일어난다. 이전에 이미 언급했듯이 사라짐 효과는 Porter-Duff blending mode를 사용해 구현한다. 이것은 실제로 잘 동작하지만 불행히도 비용이 많이 들고 그리는 속도를 약간 떨어뜨릴 수 있다 .왜냐하면 offscreen 비트맵에서 렌더링의 일부분을 캡쳐해야 하고 나머지 부분을 블랜딩하기 때문이다.(이것은 메모리에서 readbacks 을 암시한다.)

리스트뷰는 대부분의 시간이 solid background에서 표시되서, expensive route 로 내려갈 이유가 없다.(??) 때문에 "cache color hint"라 불리는 최적화가 소개되었던 것이다. cache color hint는 RGB color set로 윈도우의 백그라운드 색상(#191919 in Android's dark theme)이 기본으로 설정되어 있다. 이 hint가 설정되면, 리스트뷰는 solid background에서 그려질 것이고, 비용이 많이드는 saveLayerAlpha()/Porter-Duff 렌더링은 간단한 gradient로 대체된다. 이 gradient는 fully transparent에서 cache color hint value 값으로 간다. 그리고 이것은 위에 보이는 이미지처럼 보인다. 그러나 여전히 전체 리스트가 스크롤할때 검게 보이는지 설명하지 못한다.

이 전에 언급했듯이, 리스트뷰는 기본세팅이 transparent/translucent 백그라운드이다. 이는 안드로이드 UI의 모든 기본 위젯 속성이다. 따라서 라스트뷰가 자신의 자식뷰를 다시 그릴때, 자식들이 윈도우의 백그라운드와 섞이게 된다. 다시한번 얘기하면, 이것들은 메모리에서 비용이 많이 드는 readbacks을 요구함으로, 스크롤이나 파일링처럼 초당 상당이 많은 그림작업을 할 때는 상당히 괴롭게 된다.

스크롤링 동작에서 그리기 성능을 높이기 위해서, 안드로이드 프레임워크는 cache color hint를 재사용한다. 이 hint가 설정되면, 프레임워크는 리스트의 자식들을 각각 hint 값을 가진 비트맵으로 복사한다. 그런다음 리스트뷰는 스크린에 직업 이 비트맵들을 blits 한다. 그리고 비트맵은 불투명이기 때문에 블렌딩할 필요가 없다. 또한 기본적인 cache color hint는 #191919 이므로, 각 아이템이 스크롤링 되는 뒤에서 dark 백그라운드는 얻는다.

드디어 해결책~~

이 문제를 해결하기위해서는 1) cache color hint optimization를 사용하지 않거나, 2) non-solid color background를 사용한다면 hint를 적당한 solid color value로 설정한다.
1) optimization 를 비활성화시키려면 간단하게 transparent color #00000000 를 사용한다. android:cacheColorHint="#00000000"
2) 코드(setCacheColorHint(int))나 xml ( android:cacheColorHint 속성)에서 설정할 수 있다.

댓글