В этой статье я расскажу о том, как сделать так, чтобы элемент в ListView оставался выделенным после того, как пользователь нажмет на него. Дело в том, что по умолчанию в Android каждый дочерний элемент списка выделяется только в тот момент, когда пользователь на него нажимает (или зажимает его). После того как он уберет с него палец — выделение исчезает. Порой в приложении необходимо выделять какой-либо элемент ListView до тех пор, пока пользователь не выберет другой и не нажмет на него. Сделать это несложно.
Предлагаю для примера создать новый проект с одним Activity. После этого нужно будет добавить в Layout-файл для Activity (по умолчанию — activity_main.xml) компонент ListView и дать ему идентификатор, например, my_listview и добавить свойство android:choiceMode="singleChoice". Также нужно будет создать layout для элементов списка (я решил назвать его listview_item.xml). В него нужно добавить LinearLayout с id item_container и текстовое поле (TextView) с id item_text.
Первым делом я задам значения цветов для выделения элемента. Для этого следует создать файл ресурсов colors.xml в папке res/values и добавить в него следующие строки:
<?xml version="1.0" encoding="utf-8"?> <resources> <color name="orange">#FF8800</color> <color name="white">#FFFFFF</color> <color name="black">#000000</color> </resources>
Для работы со списком будет использоваться класс MyAdapter, который расширяет класс BaseAdapter и переопределяет его методы. Его нужно будет создать в классе MainActivity.
Поскольку для версий Android API ниже, чем 11 свойство android:state_activated недоступно, то при отображении view-элемента я буду осуществлять проверку того, какая версия Android установлена на устройстве, и если он будет ниже чем 11, то view будет выделяться следующим образом:
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { view.setBackgroundColor(Color.WHITE); textView.setTextColor(Color.BLACK); if (mListView.isItemChecked(position)) { view.setBackgroundColor(getResources().getColor(R.color.orange)); textView.setTextColor(Color.WHITE); } }
Листинг класса MyAdapter:
class MyAdapter extends BaseAdapter { private LayoutInflater mInflater; private ArrayList<String> mItems; public MyAdapter(LayoutInflater inflater, ArrayList<String> items){ mInflater = inflater; mItems = items; } @Override public int getCount() { return mItems.size(); } @Override public Object getItem(int position) { return mItems.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { TextView textView; View view; ViewHolder holder; if (convertView == null){ convertView = mInflater.inflate(R.layout.listview_item, parent, false); textView = (TextView) convertView.findViewById(R.id.item_text); view = convertView.findViewById(R.id.item_container); textView.setText(mItems.get(position)); holder = new ViewHolder(textView, view); convertView.setTag(holder); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { view.setBackgroundColor(Color.WHITE); textView.setTextColor(Color.BLACK); if (mListView.isItemChecked(position)) { view.setBackgroundColor(getResources().getColor(R.color.orange)); textView.setTextColor(Color.WHITE); } } } else{ holder = (ViewHolder) convertView.getTag(); holder.textView.setText(mItems.get(position)); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { holder.view.setBackgroundColor(Color.WHITE); holder.textView.setTextColor(Color.BLACK); if (mListView.isItemChecked(position)) { holder.textView.setTextColor(Color.WHITE); holder.view.setBackgroundColor(getResources().getColor(R.color.orange)); } } } return convertView; } class ViewHolder{ public TextView textView; public View view; public ViewHolder(TextView tView, View v){ textView = tView; view = v; } } }
Теперь в методе onCreate нужно будет создать адаптер и назначить его ListView.
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mListView = (ListView)findViewById(R.id.my_listview); ArrayList<String> items = new ArrayList<String>(); for (int i =0; i<10; i++){ items.add("Item - " + String.valueOf(i)); } MyAdapter adapter = new MyAdapter(getLayoutInflater(), items); mListView.setAdapter(adapter); mListView.setOnItemClickListener(mItemClickListener); }
Для того, чтобы элементы списка выделялись после нажатия, нужно будет создать селектор, который будет менять цвет выделения в зависимости от условий. Для этого в папке res нужно создать папку drawable, в которой нужно создать два xml файла с типом selector. Первый нужен для того, чтобы закрашивать фон выделенного View, а второй — чтобы менять цвет текста. Я назвал их item_background_selector.xml и item_text_selector.xml
В первый файл необходимо добавить строки:
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_activated="true" android:drawable="@color/orange"></item> <item android:state_pressed="true" android:drawable="@color/orange"></item> <item android:state_pressed="false" android:drawable="@color/white"></item> </selector>
Вo второй файл:
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_enabled="true" android:state_pressed="true" android:color="@color/white" /> <item android:state_enabled="true" android:state_focused="true" android:color="@color/white" /> <item android:state_enabled="true" android:state_selected="true" android:color="@color/white" /> <item android:state_pressed="false" android:color="@color/black"></item> </selector>
После этого нужно открыть файл listview_item.xml и добавить следующее свойство для LinearLayout android:background="@drawable/item_background_selector" а для TextView добавить свойство
android:textColor="@drawable/item_text_selector"
Последнее, что осталось сделать — создать и назначить ListView обработчик нажатия на его элементы с указанием, что его нужно выделить.
public OnItemClickListener mItemClickListener = new OnItemClickListener(){ @Override public void onItemClick(AdapterView<?> adapter, View view, int position, long id) { mListView.setItemChecked(position, true); mListView.setSelected(true); } };
А в метод onCreate нужно добавить строку mListView.setOnItemClickListener(mItemClickListener);
Полный листинг класса MainActivity:
public class MainActivity extends Activity { private ListView mListView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mListView = (ListView)findViewById(R.id.my_listview); ArrayList<String> items = new ArrayList<String>(); for (int i =0; i<10; i++){ items.add("Item - " + String.valueOf(i)); } MyAdapter adapter = new MyAdapter(getLayoutInflater(), items); mListView.setAdapter(adapter); mListView.setOnItemClickListener(mItemClickListener); } public OnItemClickListener mItemClickListener = new OnItemClickListener(){ @Override public void onItemClick(AdapterView<?> adapter, View view, int position, long id) { mListView.setItemChecked(position, true); mListView.setSelected(true); } }; @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } class MyAdapter extends BaseAdapter { private LayoutInflater mInflater; private ArrayList<String> mItems; public MyAdapter(LayoutInflater inflater, ArrayList<String> items){ mInflater = inflater; mItems = items; } @Override public int getCount() { return mItems.size(); } @Override public Object getItem(int position) { return mItems.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { TextView textView; View view; ViewHolder holder; if (convertView == null){ convertView = mInflater.inflate(R.layout.listview_item, parent, false); textView = (TextView) convertView.findViewById(R.id.item_text); view = convertView.findViewById(R.id.item_container); textView.setText(mItems.get(position)); holder = new ViewHolder(textView, view); convertView.setTag(holder); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { view.setBackgroundColor(Color.WHITE); textView.setTextColor(Color.BLACK); if (mListView.isItemChecked(position)) { view.setBackgroundColor(getResources().getColor(R.color.orange)); textView.setTextColor(Color.WHITE); } } } else{ holder = (ViewHolder) convertView.getTag(); holder.textView.setText(mItems.get(position)); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { holder.view.setBackgroundColor(Color.WHITE); holder.textView.setTextColor(Color.BLACK); if (mListView.isItemChecked(position)) { holder.textView.setTextColor(Color.WHITE); holder.view.setBackgroundColor(getResources().getColor(R.color.orange)); } } } return convertView; } class ViewHolder{ public TextView textView; public View view; public ViewHolder(TextView tView, View v){ textView = tView; view = v; } } } }
Запускаем проект, проверяем, все работает! Если у вас возникли вопросы по примеру — задавайте их в комментариях.