Android: прокрутка ListView клавишами громкости
Прокрутка списка кнопками громкости в приложениях на Андроиде нa самом деле не является чем-то сложным. Не зная этого, вчера я потратил какое-то время в поисках хорошего руководства на эту тему. Написав код и опубликовав Quoter в версии 1.0, я решил сам написать небольшую заметку об этом.
Итак, что нам нужно сделать, это переписать метод dispatchKeyEvent() в нашей Activity, и таким образом перехватить нажатия кнопок громкости.
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
switch (event.getKeyCode()) {
case KeyEvent.KEYCODE_VOLUME_UP:
scrollToPrevious();
return true;
case KeyEvent.KEYCODE_VOLUME_DOWN:
scrollToNext();
return true;
}
}
if (event.getAction() == KeyEvent.ACTION_UP
&& (event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_UP
|| event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_DOWN)) {
return true;
}
return super.dispatchKeyEvent(event);
}
Наш код выполняется только на событии нажатия клавиш (ACTION_DOWN). Событие ACTION_UP перехватывается для того, чтобы предотвратить системный звук нажатия клавиши. Также проверяется event.getKeyCode(), и если нажата одна из нужных клавиш, вызываются соответствующие функции. В других случаях (другие события или клавиши) событие передается стандартному обработчику.
Теперь остались только собственно функции прокрутки ListView. Проблема с ними вот в чем. Можно прокрутить список в любую точку с помощью метода scrollTo(), но нам нужно перейти не к координатам, а к конкретному элементу списка – Quoter есть приложение для чтения, и читатель хочет перейти к следующей цитате. Вот что мы для этого можем сделать:
private void scrollToNext() {
int currentPosition = getListView().getFirstVisiblePosition();
if (currentPosition == getListView().getCount() - 1)
return;
getListView().setSelection(currentPosition + 1);
getListView().clearFocus();
}
private void scrollToPrevious() {
int currentPosition = getListView().getFirstVisiblePosition();
if (currentPosition == 0)
return;
getListView().setSelection(currentPosition - 1);
getListView().clearFocus();
}
Вначале определяем позицию в списке первого видимого на экране элемента. Если это уже последний элемент в нужном направлении, ничего не делаем. В другом случае выставляем выбранный элемент списка на следующую позицию, при этом список прокручивается куда надо автоматически (как при навигации стрелками на клавиатуре). Единственная оставшаяся проблема: при выделении элемента списка он подсвечивается, что мешает читать. Снимаем выделение, убрав фокус со списка. Готово.
In English, please
Bitte, in Deutsch
По-русски, пожалуйста
Замечательно! Это то, что нужно, спасибо. Однако есть трабл…. при нажатии кнопки громкости воспроизводится системный противно-пищащий звук. Курю гугл в ожидании…
Спасибо за Ваш пример, но у меня есть замечание. Надо также обработать ACTION_UP и вернуть true, чтобы не было звука клавиши во время прокрутки. С Вашим кодом звук как раз появлялся. Проверялось на Incredible S.
Спасибо за подсказку, сейчас допишу пост.