Здравствуй!
В этой статье я опишу способ обработки нажатия на отдельную часть элемента списка. Кого заинтересовало, прошу под кат.
ПРЕДИСТОРИЯ
Недавно передо мной встала задача: реализовать возможность нажатия на отдельный 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 и присваивать слушатель только ему.
Ну вот в общем-то и всё. Буду рад, если этот пост поможет кому-нибудь.
Автор: ED98
Лучше вместо этого костыля использовать ImageView вместо кнопок. Ему вполне легко можно придать вид кнопки, а onListItemClick при этом работает. Часто бывает что невозможно в классе адаптера реализовать то, что необходимо сделать по клику элемента списка.