вторник, 26 ноября 2013 г.

HListView и ViewPager

Есть такой хороший контрол для андроида: HListView (либа: HorizontalVariableListView). Это горизонтальный ListView.

Есть, конечно Gallery. Но этот контрол считается deprecated, начиная с апи 16, плюс его логика такова, что он будет центровать дочерние элементы. Да и баг есть. Не очень корректно отрабатывается detachViewsFromParent, но это уже совсем другая история.

Главное, что HorizontalVariableListView со своей задачей справляется. Я как понимаю это просто взяли код ListView и адаптировали его. Т.е. там своя цепочка классов: HListView - AbsHListView - AdapterView, ну а дальше уже стандартный ViewGroup. Но жить это не мешает.

Интересная ситуация возникла, когда я поместил HListView внутри ViewPager. Были реализованы табы и на одном из них был такой контрол. Была даже более сложно: обычный ListView, каждый элемент которого - это в свою очередь HListView.

Всё работало хорошо на 4-ке. Когда же попробовал на 2-ке. Балалайка: вместо скролинга элемента ListView, переворачивалась другая страница ViewPager. Проблема была бы у любого девайса с апи < 14.

Одно из решений: перегрузить canScroll. Вот источник на SO
@Override
 protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) {
  return super.canScroll(v, checkV, dx, x, y) || (checkV && customCanScroll(v));
 }

 protected boolean customCanScroll(View v) {
  return (v instanceof HorizontalScrollView || v instanceof AbsHListView);
 }

В данном случае решение SO чуть подправлено для правильный работы.

Суть проблемы заключается в том, что в реализации canScroll ViewPager есть строка:
ViewCompat.canScrollHorizontally(v, -dx);
canScrollHorizontally всегда возвращает false, и только с 14 сдк метод перегружен и возвращается View::canScrollHorizontally