Intereting Posts
Пользовательская анимация для просмотра Получение ERR_CACHE_MISS на window.open Android Market – единственные отчеты о сбоях, которые я получаю, находятся на платформах «OTHER» Как писать содержит запрос в SQLite fts3 полнотекстовый поиск Как программировать круглые углы и задавать произвольные фоновые цвета Как определить, было ли отклонено уведомление? Android-эмулятор не запускается вообще Как возможно, что приложение Google Fit измеряет количество шагов все время без отвода батареи? Ошибка приложения при сканировании AppIndexing Как я могу обнаружить любую версию в своем приложении? Как я могу добавить файлы .so в проект библиотеки андроидов, используя gradle 0.7+ Неверная транзакция связывания при динамическом размещении растрового изображения в виджетах Android: установить границу между кнопками с LayoutParams Как рисовать путь, когда я двигаюсь, начиная с моего текущего местоположения, используя Карты Google Debug android: подключитесь к sqlite db на телефоне

Android listSelector все еще частично отображается, когда элемент прокручивается

На изображении показана проблема: элемент Venus прокручивается, но его выделение видно.

Элемент Венеры прокручивается, но его выбор видим

Я посмотрел на Hanged listSelector в ListView, и я использую фигуры / градиент, как это было рекомендовано, но все равно не повезло.

Устройство: MS VS Emulator для Android, Android 4.2 XHDPI API-17
IDE: Android Studio 2. на Windows 7 WM.

Макет, основная деятельность

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <ListView android:id="@android:id/list" android:layout_width="match_parent" android:layout_height="wrap_content" android:choiceMode="singleChoice" android:drawSelectorOnTop="false" android:scrollingCache="false" android:animationCache="false" android:listSelector="@drawable/list_selector"> </ListView> </LinearLayout> 

Селектор списка

 <?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/item_pressed" /> <item android:drawable="@drawable/item_selected" /> </selector> 

Drawables, item_pressed

 <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" > <gradient android:angle="90" android:endColor="#0000ff" android:startColor="#0000ff" /> </shape> 

item_selected

 <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" > <gradient android:angle="90" android:endColor="#00ff00" android:startColor="#00ff00" /> </shape> 

И код операции

 package com.example.listdemo; import android.app.ListActivity; import android.os.Bundle; import android.widget.ArrayAdapter; public class MainActivity extends ListActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ArrayAdapter adapter = ArrayAdapter.createFromResource(this, R.array.Planets, R.layout.myitem); setListAdapter(adapter); } } 

Где Planets – это всего лишь массив строк (Солнце, Меркурий, Венера, Земля, Марс, Юпитер …), а myitem – это только myitem изображение с пользовательской высотой.

Где я ошибаюсь, пожалуйста?

EDIT Чтобы прояснить вопрос, речь идет о поведении списка по умолчанию. android:state_xxx идет о элементе выбора списка без атрибутов android:state_xxx . Не обращайте особого внимания на подходящее имя. Я готов переименовать @drawable/item_selected в @drawable/item_default . Дайте мне знать, если это поможет прояснить проблему, и я ее переименую.

Solutions Collecting From Web of "Android listSelector все еще частично отображается, когда элемент прокручивается"

Tl; dr Не устанавливать Default Drawable в вашем селекторе списка.

Эта проблема возникает, когда вы предоставляете селектору списка по умолчанию Drawable. Под этим я подразумеваю, что в определении селектора списка у вас есть тег item без требования штата, который делает этот item непреднамеренно по умолчанию . Здесь вы можете узнать больше о селекторах.

Ваш код выбора списка:

 <?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/item_pressed" /> <item android:drawable="@drawable/item_selected" /> <-- this is what I'm referring to </selector> 

Исправить

Проблема, с которой вы столкнулись, вызвана тем, что селектор списка всегда отображается (даже если селектор не находится на экране). Обычно это не проблема, поскольку селектор списков прозрачен (и, следовательно, невидим). Однако, поскольку вы предоставили селектору списка фон по умолчанию, это означало, что всякий раз, когда селектор списка находился на экране, он был бы виден, вызывая странное поведение, которое вы наблюдали. Вместо этого вы действительно хотите только показать этот фон, когда элемент действительно выбран.

Для этого сначала нужно удалить фон по умолчанию из селектора списков. Затем нам нужен новый способ указать выбранные элементы. Поскольку вы указали android:choiceMode="singleChoice" в ListView, ListView будет обрабатывать ваши элементы списка, как список флажков. Таким образом, когда пользователь проверяет один из элементов, активированное состояние будет установлено в true. Тем не менее, TextViews не будет показывать никаких визуальных эффектов при активации по умолчанию. Чтобы отобразить определенный фон при выборе, нам нужно использовать макет элемента списка, который может отображать активированное состояние. Один из способов сделать это – изменить фон представления элемента ListView на селектор и определить Drawable, который вы хотите использовать для активированного состояния.

Например:

Код адаптера:

 ArrayAdapter adapter = ArrayAdapter.createFromResource(this, R.array.Planets, R.layout.myitem); 

myitem.xml:

 <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@android:id/text1" style="?android:attr/spinnerItemStyle" android:singleLine="true" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/item_background" android:paddingTop="16dp" android:paddingBottom="16dp"/> 

item_background.xml:

 <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/item_selected" android:state_activated="true" /> </selector> 

Или если вы ленивы:

 ArrayAdapter adapter = ArrayAdapter.createFromResource(this, R.array.planets_array, android.R.layout.simple_list_item_activated_1); 

дальнейшее чтение

Из документации Android не совсем очевидно, что то, что я сказал, верно, поэтому вы можете спросить, действительно ли мой ответ правдоподобен. Этот раздел посвящен тем, кто ищет надежный ответ и очень любопытный.

Чтобы понять, как работает селектор списков и как он запрограммирован, нам нужно будет погрузиться в исходный код Android. Для начала мясо логики ListView фактически хранится в классе AbsListView (в случае, если у вас нет загруженного источника, вы можете сослаться на это ). Копаясь в источнике этого класса, мы найдем несколько полезных полей / функций, относящихся к селектору:

  • mSelector : это Drawable селектора (тот, который вы указываете с помощью android:listSelector )
  • mSelectorRect : в этом поле определяется, где выполняется селектор, и насколько велика селектор
  • mSelectedPosition : Сохраняет индекс выбранного элемента (это поле фактически объявлено еще глубже в классе AdapterView )
  • positionSelector(...) : обновления, в которых должен быть выбран селектор
  • drawSelector(...) : Рисует селектор
  • trackMotionScroll(...) : Содержит логику поведения прокрутки ListView

Теперь, когда у нас есть понимание среды, мы можем, наконец, понять основную логику поведения селектора списков. Все это сводится к этим небольшим строкам кода в trackMotionScroll(...) :

 boolean trackMotionScroll(int deltaY, int incrementalDeltaY) { ... if (!inTouchMode && mSelectedPosition != INVALID_POSITION) { // if we are not in touch mode and there is a selected item then // we do a quick check if the selected item is on screen final int childIndex = mSelectedPosition - mFirstPosition; if (childIndex >= 0 && childIndex < getChildCount()) { // if the selected item is on screen, we move the selector to // where the selected item is positionSelector(mSelectedPosition, getChildAt(childIndex)); } } else if (mSelectorPosition != INVALID_POSITION) { // if we are in touch mode and there is a selected item then // we do a quick check if the selected item is on screen final int childIndex = mSelectorPosition - mFirstPosition; if (childIndex >= 0 && childIndex < getChildCount()) { // if the selected item is on screen, we move the selector to // where the selected item is positionSelector(INVALID_POSITION, getChildAt(childIndex)); } } else { // otherwise, if nothing is selected, hide the selector (don't draw it) mSelectorRect.setEmpty(); } ... } 

Исходный фрагмент выше был отредактирован из оригинала, чтобы включить комментарии.

Именно здесь мы, наконец, находим логику, объясняющую наблюдаемое поведение: Селектор списков скрыт только тогда, когда mSelectorPosition == INVALID_POSITION или на английском языке, когда нет выбранных элементов. В противном случае он позиционируется в выбранном элементе, если элемент находится на экране, иначе изменения не будут внесены в его положение.

Поэтому, когда вы просматриваете ListView и выбранный элемент отключается, селектор списков просто остается в последнем месте, в котором выбранный элемент объяснял выбранный селектор списка призраков .

Последние мысли

От работы с ListViews с момента его введения я должен сказать, что все это не очень хорошо спроектировано, и оно может быть чрезвычайно затруднительным. Я настоятельно рекомендую использовать его преемника, RecyclerView , когда это возможно.

Возможно, вы можете попробовать добавить android: layerType = "software" в ListView.

 <ListView android:layerType="software" android:id="@android:id/list" android:layout_width="match_parent" android:layout_height="wrap_content" android:choiceMode="singleChoice" android:drawSelectorOnTop="false" android:scrollingCache="false" android:animationCache="false" android:listSelector="@drawable/list_selector"> </ListView>