Здравствуй, Хабрахабр!
В этой статье я опишу способ обработки нажатия на отдельную часть элемента списка. Кого заинтересовало, прошу под кат.
Недавно передо мной встала задача: реализовать возможность нажатия на отдельный View в элементе списка. Сложность заключалась в том, что метод onListItemClick() вызывается при нажатии на любую часть элемента списка (неважно, какой View находится под пальцем). Поискав решение, я ничего полезного не нашёл. Проведя несколько экспериментов, я всё-таки достиг цели.
Создадим проект. Имя, пакет, версия ANDROID – на ваше усмотрение. Сначала разметка для элемента списка и Activity:
res/layout/row.xml
MainActivity.java
Я специально использую ListActivity, чтоб сократить урок. Использовать мы будем, разумеется, свой кастомный адаптер. Чтобы не морочиться с SimpleAdapter и его ArrayList<Map<String, Object>> или BaseAdapter с его обязательными методами, я наследую свой адаптер от ArrayAdapter. Я не стал добавлять ViewHolder – он нам сейчас не нужен. Ну и наконец-то, сам код адаптера:
MyListAdapter.java
Давайте разбираться, что мы здесь накодили. В методе getView(int position, View convertView, ViewGroup parent) мы создаём вьюху для каждого элемента списка и там же находим кнопку и присваиеваем ей обработчик нажатия. Когда кнопку нажимают, появляется тост с позицией этого элемента. Как видите, всё очень просто! Правда, при этом почему-то перестаёт работать onListItemClick(ListView l, View v, int position, long id) (по крайней мере у меня). Поэтому придётся кодить обработку нажатия на нужную кнопку и на все остальные View в самом адаптере :(. Но можно сделать, как я написал выше — присвоить всем элементам OnClickListener, а потом смотреть — если наша кнопка, то одно действие, иначе — другое. А ещё лучше вынести все другие вьюхи в отдельный LinearLayout или RelativeLayout и присваивать слушатель только ему.
Ну вот в общем-то и всё. Буду рад, если этот пост поможет кому-нибудь.
В этой статье я опишу способ обработки нажатия на отдельную часть элемента списка. Кого заинтересовало, прошу под кат.
ПРЕДИСТОРИЯ
Недавно передо мной встала задача: реализовать возможность нажатия на отдельный View в элементе списка. Сложность заключалась в том, что метод onListItemClick() вызывается при нажатии на любую часть элемента списка (неважно, какой View находится под пальцем). Поискав решение, я ничего полезного не нашёл. Проведя несколько экспериментов, я всё-таки достиг цели.
СОЗДАНИЕ ПРОЕКТА
Создадим проект. Имя, пакет, версия ANDROID – на ваше усмотрение. Сначала разметка для элемента списка и Activity:
res/layout/row.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" > <TextView android:id="@ +id/text_view" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" /> <Button android:id="@+id/btn_position" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="позиция" /> </LinearLayout>
MainActivity.java
import android.os.Bundle; import android.app.ListActivity; public class MainActivity extends ListActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); String[] objects = new String[] {"iOS", "Windows Mobile", "Windows Phone", "Android", "Symbian", "Java", "Ubuntu", "Windows", "Linux", "Mac OS", "DOS", "ChromeOS"}; MyListAdapter adapter = new MyListAdapter(this, objects); setListAdapter(adapter); } }
Я специально использую ListActivity, чтоб сократить урок. Использовать мы будем, разумеется, свой кастомный адаптер. Чтобы не морочиться с SimpleAdapter и его ArrayList<Map<String, Object>> или BaseAdapter с его обязательными методами, я наследую свой адаптер от ArrayAdapter. Я не стал добавлять ViewHolder – он нам сейчас не нужен. Ну и наконец-то, сам код адаптера:
MyListAdapter.java
import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; public class MyListAdapter extends ArrayAdapter<String> implements OnClickListener { private Context context; private String[] objects; public MyListAdapter(Context c, String[] data) { super(c, IGNORE_ITEM_VIEW_TYPE, data); context = c; objects = data; } public View getView(int position, View convertView, ViewGroup parent) { LayoutInflater inflater = LayoutInflater.from(context); View view = inflater.inflate(R.layout.row, null, true); TextView text_view = (TextView) view.findViewById(R.id.text_view); text_view.setText(objects[position]); text_view.setOnClickListener(this); Button btn_position = (Button) view.findViewById(R.id.btn_position); btn_position.setTag(String.valueOf(position)); btn_position.setOnClickListener(this); return view; } public void onClick(View view) { if (view.getId() == R.id.btn_position) { Toast.makeText(context, "position = " + view.getTag().toString(), Toast.LENGTH_SHORT).show(); } else { Toast.makeText(context, "onListItemClick", Toast.LENGTH_SHORT).show(); } }
Давайте разбираться, что мы здесь накодили. В методе getView(int position, View convertView, ViewGroup parent) мы создаём вьюху для каждого элемента списка и там же находим кнопку и присваиеваем ей обработчик нажатия. Когда кнопку нажимают, появляется тост с позицией этого элемента. Как видите, всё очень просто! Правда, при этом почему-то перестаёт работать onListItemClick(ListView l, View v, int position, long id) (по крайней мере у меня). Поэтому придётся кодить обработку нажатия на нужную кнопку и на все остальные View в самом адаптере :(. Но можно сделать, как я написал выше — присвоить всем элементам OnClickListener, а потом смотреть — если наша кнопка, то одно действие, иначе — другое. А ещё лучше вынести все другие вьюхи в отдельный LinearLayout или RelativeLayout и присваивать слушатель только ему.
Ну вот в общем-то и всё. Буду рад, если этот пост поможет кому-нибудь.