У меня есть список, полный элементов, после того, как пользователи выбирают элемент, который он загорается, а затем он возвращается в нормальное состояние. Есть ли способ сделать так, чтобы, когда пользователь выбирает элемент в моем ListView, он остается выбранным и выделяется?
ListView остается выбранным?
Ответ 1
По-видимому, "исчезающий отбор" - по дизайну; это называется "сенсорный режим". Я прочитал этот документ и до сих пор не знаю, почему они думали, что это хорошая идея. Я предполагаю, что, поскольку Android изначально был предназначен для устройств с маленькими экранами, они ожидали, что вы заполнили экран списком, а затем, когда пользователь нажмет на элемент, перейдите в новый список на другом экране. Таким образом, пользователь не будет знать, что Android потерял отслеживание выбранного элемента.
Но это поведение довольно неприятно, если, например, вы хотите, чтобы пользователь выбирал элемент, а затем показывал информацию об этом элементе на том же экране. Если выбор исчезает, как пользователь должен знать, что он нажал (если, конечно, у пользователей есть область внимания золотых рыбок)?
Одним из возможных решений является изменение всех элементов списка на переключатели. Мне не очень нравится это решение, потому что оно отвлекает экранную недвижимость. Я бы предпочел просто использовать цвет фона, чтобы показать, какой элемент выбран. До сих пор я видел одно решение, но оно не совсем полное или общее. Итак, вот мое решение:
1. В вашем файле макета XML
Перейдите к элементу ListView и следующему атрибуту: android:choiceMode="singleChoice"
. Я не совсем уверен, что это делает (сам по себе он не позволяет пользователю ничего выбирать), но без этого атрибута код ниже не работает.
2. Определите следующий класс
Он используется для отслеживания выбранного элемента, а также позволяет моделировать передачу по ссылке в Java:
public class IntHolder {
public int value;
public IntHolder() {}
public IntHolder(int v) { value = v; }
}
3. Поместите следующий код где-нибудь
Я предполагаю, что вы поместили его в свою активность, но он может пойти в любом классе:
static void setListItems(Context context, AdapterView listView, List listItems, final IntHolder selectedPosition)
{
setListItems(context, listView, listItems, selectedPosition,
android.R.layout.simple_list_item_1,
android.R.layout.simple_spinner_dropdown_item);
}
static void setListItems(Context context, AdapterView listView, List listItems, final IntHolder selectedPosition,
int list_item_id, int dropdown_id)
{
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> list, View lv, int position, long id) {
selectedPosition.value = position;
}
});
ArrayAdapter<CharSequence> adapter = new ArrayAdapter<CharSequence>(context, list_item_id, listItems) {
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View itemView = super.getView(position, convertView, parent);
if (selectedPosition.value == position)
itemView.setBackgroundColor(0xA0FF8000); // orange
else
itemView.setBackgroundColor(Color.TRANSPARENT);
return itemView;
}
};
adapter.setDropDownViewResource(dropdown_id);
listView.setAdapter(adapter);
}
Этот код выполняет две функции: привязывает элементы списка (например, List<String>
) к вашему элементу ListView и переопределяет ArrayAdapter.getView()
код, который изменяет фон выбранного элемента.
4. Используйте этот код для настройки своего списка
Например:
ListView _list;
IntHolder _selectedItem = new IntHolder(-1); // nothing selected at first
@Override
protected void onCreate(Bundle savedInstanceState) {
...
_list = (ListView)findViewById(R.id.list);
List<String> items = Arrays.asList("Item 1", "Item 2", "Item 3");
setListItems(this, _list, items, _selectedItem);
}
Это все! Вышеизложенное предполагает, что вам нужен отдельный выбор. С некоторыми небольшими изменениями в getView() вы могли бы также поддерживать многоэкранный выбор, но, скорее всего, вы должны использовать флажки.
Предупреждение: это решение нуждается в дальнейшем развитии. Если пользователь использует клавиши со стрелками или кнопки для выбора элемента, этот элемент будет не выбран с точки зрения IntHolder. Если пользователь нажимает кнопку без метки (то, что имя этой кнопки? "Enter"?), Тогда элемент станет "официально", но тогда у вас есть другая проблема, потому что если пользователь снова использует клавиши со стрелками, это будет выглядеть как и два элемента. Оставьте комментарий, если вы выясните, как сохранить "внутренний выбор" в IntHolder, синхронизированный с "выбором клавиатуры" или тем, что он вызвал. Во всяком случае, что называется?
Ответ 2
В ListView есть атрибут listSelector:
Drawable используется для указания текущего выбранного элемента в списке.
http://developer.android.com/reference/android/widget/AbsListView.html#attr_android:listSelector
ИЗМЕНИТЬ после Stan комментарий
Чтобы убедиться, что a ListView
остается выбранным, вы должны
① Установите атрибут вида choiceMode
через xml или программно.
② Используйте адаптер, который использует представления, которые реализуют интерфейс Checkable
, например CheckedTextView
(внутри simple_list_item_single_choice
макет).
Файл TestActivity.java
public class TestActivity extends Activity {
private static final int SINGLE_CHOICE = android.R.layout.simple_list_item_single_choice;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test);
String[] items = {"test 1", "test 2", "test 3"};
ListAdapter adapter = new ArrayAdapter<String>(this, SINGLE_CHOICE, items);
ListView list = (ListView) findViewById(R.id.testList);
list.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
list.setAdapter(adapter);
}
}
Ответ 3
Здесь более простое решение, чем Qwertie's:
Не полагайтесь на данный механизм выбора. Сделайте это самостоятельно.
View mSelectedItemView = null; //class member variable
View mTouchedItemView = null; //class member variable
ListView v = (ListView) getActivity().findViewById(R.id.listView);
// select on click
v.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapter,
View clickedViewItem, int position, long id) {
if (mSelectedItemView != null)
selectedItemView.setBackgroundColor(Color.WHITE);
clickedViewItem.setBackgroundColor(Color.YELLOW);
mSelectedItemView = clickedViewItem;
}
});
// highlight on touch
v.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (v instanceof ListView) {
ListView listView = (ListView) v;
// Find the child view that was touched (perform a
// hit test)
Rect rect = new Rect();
int childCount = listView.getChildCount();
int[] listViewCoords = new int[2];
v.getLocationOnScreen(listViewCoords);
int x = (int) event.getRawX() - listViewCoords[0];
int y = (int) event.getRawY() - listViewCoords[1];
View child;
for (int i = 0; i < childCount; i++) {
child = listView.getChildAt(i);
child.getHitRect(rect);
if (rect.contains(x, y)) {
View touchedView = child;
if (event.getAction() == MotionEvent.ACTION_DOWN) {
touchedView
.setBackgroundColor(Color.RED);
mTouchedItemView = touchedView;
} else if (event.getAction() == MotionEvent.ACTION_UP) {
mTouchedItemView
.setBackgroundColor(Color.WHITE);
}
}
}
}
return false;
}
});
Также этот метод касается только кликов и не будет работать, если пользователь использует клавиши со стрелками.
Отказ от ответственности: Де-подсветка после касания не работает надежно.
Кредиты для трогательной части идут на ozik.dev: Получить элемент из списка только с OnTouchListener
Ответ 4
просто добавьте это в свой макет списка.
android:listSelector="@drawable/selector_expandable_listview"
android:drawSelectorOnTop="true"
Ответ 5
Используйте файл Selector.XML и этот код:
//SetOnClickListner to catch Events
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
view.setSelected(true);
}
});
Ответ 6
Просто добавьте это в свой ListView:
android:listSelector="@color/my_color"
Ответ 7
Этот ответ работает, попробуйте этот
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long arg3)
{
for(int a = 0; a < parent.getChildCount(); a++)
{
parent.getChildAt(a).setBackgroundColor(Color.TRANSPARENT);
}
view.setBackgroundColor(Color.GREEN);
}