Я придумал универсальное и многоразовое решение. Вместо расширения конкретного адаптера списка и модификации метода getView()
я создал новый класс, реализующий интерфейс ListAdapter
, который слепо пересылает почти все на другой ListAdapter
, за исключением getView()
. Это выглядит следующим образом:
public class SubClickableListAdapter implements ListAdapter {
public static interface OnSubItemClickListener {
public void onSubItemClick(View subView, int position);
}
private ListAdapter other;
private SparseArray<OnSubItemClickListener> onClickListeners;
public SubClickableListAdapter(ListAdapter other) {
this.other = other;
onClickListeners = new SparseArray<OnSubItemClickListener>();
}
public void setOnClickListener(int id, OnSubItemClickListener listener) {
onClickListeners.put(id, listener);
}
public void removeOnClickListener(int id) {
onClickListeners.remove(id);
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
View view = other.getView(position, convertView, parent);
for(int i = 0; i < onClickListeners.size(); i++) {
View subView = view.findViewById(onClickListeners.keyAt(i));
if (subView != null) {
final OnSubItemClickListener listener = onClickListeners.valueAt(i);
if (listener != null) {
subView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
listener.onSubItemClick(v, position);
}
});
}
}
}
return view;
}
// other implemented methods
}
Другие реализованные методы просто выглядеть следующим образом одно:
@Override
public Object getItem(int position) {
return other.getItem(position);
}
Чтобы использовать его, просто экземпляр его подачи любого другого ListAdapter
(будь то ArrayAdapter
или SimpleCursorAdapter
или что-нибудь еще). Затем вызовите setOnClickListener()
для каждого вида, где вы хотите прослушивать клики, указав свой идентификатор в параметре id
, и ваш слушатель в параметре listener
. Чтобы получить идентификатор строки для выбранной строки, вызовите метод ListView (getItemIdAtPosition(position)
), который вам нужно получить другим способом, поскольку он не указан как параметр для вашего обратного вызова, но это не должно быть большой проблемой в большинстве случаев).
Преимущество этого решения в том, что его можно использовать с любым ListAdapter
. Поэтому, если ваше приложение имеет несколько ListView
, каждый из которых использует разные основные виды или даже различные адаптеры, вам не нужно создавать новый класс адаптера для каждого из них.
Проблема с этим будет такой же, как со всеми другими решениями: OnItemClick()
из ListView
не будет вызываться, если вы нажмете на представление, на которое вы зарегистрировали прослушиватель. Для просмотров, которые вы не зарегистрировали слушателя, этот обратный вызов будет вызван.Так, например, у вас есть активность для вашего элемента списка, который содержит два текстовых поля и кнопку, и вы регистрируете прослушиватель для кнопки, а затем нажатие на кнопку не вызывает OnItemClick()
из ListView
, но вместо этого ваш обратный вызов , Нажав нигде, звоните OnItemClick()
.
Это работало нормально, по проблемам я переключился на ImageButton. И это не сработало, как ожидалось. Для других см. Этот вопрос также: http://stackoverflow.com/questions/6116583/android-listview-custom-adapter-imagebutton – Henrik