Как получить селектор элементов списка Android для использования state_checked

Разрывая мои волосы, пытаясь заставить Android ListView делать то, что я хочу.

Я хочу иметь ListView в режиме одиночного выбора с настраиваемой строкой строки, которая имеет другой цвет фона для выбранных, нажатых и отмеченных (т. Е. Выбор отображается цветом, а не галочкой – это то, что я обычно называю «Выбор», но выбор в андроиде кажется строкой, которую я собираюсь выбрать, прежде чем я ее нажму)

Я думал о попытке выбора фонового переключателя с тремя состояниями в нем. Он отлично работает для state_selected и state_pressed, но не state_checked. Поэтому я создал CheckableRelativeLayout, который расширяет RelativeLayout и реализует Checkable и используется для представления каждой строки.

Здесь показана упрощенная версия:

<my.package.CheckableRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="@drawable/bkg_selector"> > <ImageView android:id="@+id/animage" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" /> </my.package.CheckableRelativeLayout> 

Bkg_selector выглядит

 <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_pressed="true" android:drawable="@drawable/purple" /> <item android:state_checked="true" android:drawable="@drawable/red" /> <item android:state_selected="true" android:drawable="@drawable/darkpurple" /> <item android:drawable="@drawable/black" /> </selector> 

Цвета определяются в другом месте.

Это все еще не сработало. Поэтому в пользовательском ListAdapter я отслеживал строку «checked» и пытался (в getView)

If (position == checkedPosition) ret.getBackground (). SetState (CHECKED_STATE_SET);

И это ЕЩЕ НЕ работает. Как я могу заставить его делать то, что я хочу?

Вам нужно переопределить onCreateDrawableState в вашем CheckableRelativeLayout и установить для него Clickable = "true". Мой код для LinearLayout:

 public class CheckableLinearLayout extends LinearLayout implements Checkable { private boolean checked = false; public CheckableLinearLayout(Context context) { super(context, null); } public CheckableLinearLayout(Context context, AttributeSet attrs) { super(context, attrs); } private static final int[] CheckedStateSet = { R.attr.state_checked }; public void setChecked(boolean b) { checked = b; } public boolean isChecked() { return checked; } public void toggle() { checked = !checked; } @Override protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CheckedStateSet); } return drawableState; } @Override public boolean performClick() { toggle(); return super.performClick(); } 

Лучше этого вместо установки clickable = true и переопределения функции checkClick CheckableLinearLayout, удерживайте предложение Павла о переопределении onCreateDrawableState и замените CheckCheckLinearLayout на setChecked () следующим:

 private final List<Checkable> mCheckableViews = new ArrayList<Checkable>(); @Override protected void onFinishInflate() { super.onFinishInflate(); final int childCount = getChildCount(); findCheckableChildren(this); } private void findCheckableChildren(View v) { if (v instanceof Checkable && v instanceof ViewGroup) { mCheckableViews.add((Checkable) v); } if (v instanceof ViewGroup) { final ViewGroup vg = (ViewGroup) v; final int childCount = vg.getChildCount(); for (int i = 0; i < childCount; ++i) { findCheckableChildren(vg.getChildAt(i)); } } } @Override public void setChecked(boolean checked) { mChecked = checked; for (Checkable c : mCheckableViews) { c.setChecked(checked); } refreshDrawableState(); } 

Это позволит избежать проблем при нажатии и длинных обратных вызовах.

ИМХО, проще использовать пользовательский адаптер:

 class CustomAdapter extends ArrayAdapter<CustomRowItem> { Context context; public CustomAdapter(Context context, int resourceId, List<CustomRowItem> items) { super(context, resourceId, items); this.context = context; } private class ViewHolder { TextView txt; View layout; } public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = null; CustomRowItem rowItem = getItem(position); LayoutInflater mInflater = (LayoutInflater) context .getSystemService(Activity.LAYOUT_INFLATER_SERVICE); if (convertView == null) { convertView = mInflater.inflate(R.layout.сustom_list, null); holder = new ViewHolder(); holder.txt = (TextView) convertView.findViewById(R.id.сustom_list_txt); holder.layout = convertView.findViewById(R.id.сustom_list_layout); convertView.setTag(holder); } else holder = (ViewHolder) convertView.getTag(); holder.txt.setText(rowItem.getText()); if(rowItem.isChecked()) holder.layout.setBackgroundColor(-16720999); //color for checked else holder.layout.setBackgroundColor(0); //color for unchecked return convertView; } } class CustomRowItem { private boolean value; private String text; public CustomRowItem(String text, boolean value) { this.text = text; this.value = value; } public boolean isChecked() { return value; } public void setChecked(boolean checked) { value = checked; } public String getText() { return text; } void setText(String text) { this.text = text; } } 

Custom_list.xml:

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:padding="10dp" android:id="@+id/сustom_list_layout" android:orientation="vertical" > <TextView android:id="@+id/сustom_list_txt" android:textSize="20sp" android:layout_width="fill_parent" android:layout_height="fill_parent"/> </LinearLayout> 

Как использовать:

 public class ExampleAct extends Activity { final List<CustomRowItem> list = new ArrayList<CustomRowItem>(); CustomAdapter adapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.example); ListView listView=(ListView)findViewById(R.id.listView); adapter = new CustomAdapter(this, R.layout.сustom_list, list); listView.setAdapter(adapter); list.add(new CustomRowItem("unchecked item",false)); list.add(new CustomRowItem("checked item",true)); adapter.notifyDataSetChanged(); listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { //unchecked on click @Override public void onItemClick(AdapterView<?> parent, View itemClicked, int index, long id) { if(list.get(index).isChecked()) { list.get(index).setChecked(false); //uncheck adapter.notifyDataSetChanged(); } else { // other actions } }); listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { //checked on long click @Override public boolean onItemLongClick(AdapterView<?> parent, View itemClicked, int index, long id) { list.get(index).setChecked(true); //check adapter.notifyDataSetChanged(); return true; // or false for calling context menu } }); } 
Intereting Posts
Как открыть файл csv на Android Устанавливать планировщик программно в android GCM «регистрационный идентификатор» больше не регистрируется Исключение java.lang.NoClassDefFoundError: android.support.v7.appcompat.R $ стиль Android GoogleAuthUtil.getTokenWithNotification Интерактивный вызов не запускается Настройки Android Wear Watchface на хосте Значок меню не отображается на панели действий «Обрезанные или прикрепленные представления не могут быть переработаны», поскольку поддержка lib 25.0.0 Как использовать задачуCheckCheck для запуска тестов на удаленных устройствах Как получить идентификатор устройства с JNI в Android? Установка продолжительности сообщений Crouton на Android Модернизация сети делает сетевые вызовы в основном потоке? Как создать ярлык, который приводит к активности без запуска? Можно ли добавить актера на задний слой в Libgdx? Требовать разрешения только для старых версий Android: maxSdkVersion не работает?