2013-01-09 3 views
3

У меня проблема с простым ListView на телефоне Samsung.Элемент ListView state_selected потерян на реальном устройстве

Я создаю новый ListView программно. Элементы простые TextView. Я положил слушателя в моем списке зрения:

listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { 
     @Override 
     public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 
      view.setSelected(true); 
     } 
    }); 

TextView (т.е. пункты ListView) используют ColorStateList как TextColor (нажатие -> Зеленый; выбрано -> Синий; по умолчанию -> Red).

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

На моем устройстве Samsung элементы по умолчанию краснеют, когда я нажимаю один, он становится зеленым, а когда я его отпускаю, он снова становится красным (т. Е. Не выбран).

Это, кажется, ошибка в реализации приложения Samsung ListView (это обычная реализация и так сложно отслеживать без исходного кода).

EDIT: не ошибка, но немного другое поведение из-за сенсорным режим (смотрите ссылку в общепринятом ответе)

У вас есть какие-либо идеи о том, как обойти эту ошибки/ поведения?

Дополнительное ограничение: я не могу использовать селектор x, потому что получаю цвет для использования только во время выполнения.

Мое устройство является Samsung GT-B5330, API 15. (но я ожидаю, что это происходит на большинстве устройств Samsung)

Вот полный (компилируется) код

import android.R; 
import android.app.Activity; 
import android.content.res.ColorStateList; 
import android.database.DataSetObserver; 
import android.graphics.Color; 
import android.os.Bundle; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.AdapterView; 
import android.widget.ListAdapter; 
import android.widget.ListView; 
import android.widget.RelativeLayout; 
import android.widget.TextView; 

public class TestActivity extends Activity { 

public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    RelativeLayout rootLayout = new RelativeLayout(this); 
    setContentView(rootLayout); 

    //create listView 
    ListView listView = new ListView(this); 
    listView.setAdapter(new MyListAdapter()); 
    listView.setDivider(null); 
    listView.setDividerHeight(0); 
    listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE); 
    listView.setItemsCanFocus(false); 
    listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { 
     @Override 
     public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 
      view.setSelected(true); 
     } 
    }); 
    listView.setBackgroundColor(Color.WHITE); 

    //positionning listView 
    RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(100,200); 
    lp.setMargins(50,50,10,10); 
    rootLayout.addView(listView, lp); 
} 



private class MyListAdapter implements ListAdapter{ 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     ColorStateList colorStateList = new ColorStateList(
       new int[][]{ 
         new int[]{R.attr.state_pressed}, 
         new int[]{R.attr.state_selected}, 
         new int[]{-R.attr.state_selected}, 
       }, 
       new int[]{ 
         Color.GREEN, 
         Color.BLUE, 
         Color.RED}); 
     TextView textView = new TextView(parent.getContext()); 
     textView.setText("Item " + position); 
     textView.setTextColor(colorStateList); 
     return textView; 
    } 

    @Override 
    public boolean areAllItemsEnabled() { 
     return true; 
    } 

    @Override 
    public boolean isEnabled(int position) { 
     return true; 
    } 

    @Override 
    public void registerDataSetObserver(DataSetObserver observer) { 
    } 

    @Override 
    public void unregisterDataSetObserver(DataSetObserver observer) { 
    } 

    @Override 
    public int getCount() { 
     return 10; 
    } 

    @Override 
    public Object getItem(int position) { 
     return "data "+position; 
    } 

    @Override 
    public long getItemId(int position) { 
     return position; 
    } 

    @Override 
    public boolean hasStableIds() { 
     return true; 
    } 


    @Override 
    public int getItemViewType(int position) { 
     return position; 
    } 

    @Override 
    public int getViewTypeCount() { 
     return getCount(); 
    } 

    @Override 
    public boolean isEmpty() { 
     return getCount()>0; 
    } 
} 
} 
+0

Есть ли у GT-5330 аппаратная клавиатура? Я нашел GT-B5330, у которого есть один, но нет информации о только GT-5330, о котором вы упоминали. –

+0

Да, у него есть аппаратная клавиатура, и я редактирую свой пост, чтобы установить правильную ссылку. (извините) – ben75

ответ

1

У меня нет устройства samsung под рукой (Galaxy Nexus dosen't count, у него простой Android, и он отлично работает с вашим примером), поэтому я не могу проверить свои предположения, но кажется, что ListView оставляет выбранное состояние после того, как он был выпущен. Вы можете проверить его с помощью HierarchyViewer (используйте Romain Guy ViewServer, если ваш телефон не укоренен).

Опасно полагаться на выбор, имеющий сенсорный экран из-за TouchMode (см. http://android-developers.blogspot.ru/2008/12/touch-mode.html). В двух словах: у вас нет концепции выбора (или фокуса, кстати), когда пользователь взаимодействует с сенсорным экраном. Эмулятор обычно имеет D-pad, поэтому он может иметь несколько другое поведение.

Итак, мое предложение для вас состоит в том, чтобы использовать state_checked вместо state_selected. У Android есть CheckedTextView, которые могут вам помочь. Просто позвоните в ListView's setItemChecked.Это решение также имеет хорошие свойства сохранения позиции позиции между изменениями конфигурации и автоматического снятия отметки с ранее отмеченного элемента при нажатии другого элемента (если используется CHOICE_MODE_SINGLE).

Если это неприемлемо, и вам нужно придерживаться state_selected, тогда вы можете обернуть свой TextView в LinearLayout, он должен предотвратить исчезновение выбора. Но не забывайте, что ListView повторно использует один и тот же вид для других элементов списка, когда он выходит из экрана, поэтому вам нужно отслеживать состояние выбора в своем адаптере для его правильной установки.

+0

+1 за все, что в этом посте. Использование state_checked отлично работает. Все ссылки действительно полезны. Большое спасибо. – ben75

0

Я могу подтвердить, Я испытал подобную ошибку только на устройствах Samsung (Nexus, S3, Note2). Элемент Listview имеет цвет фона по умолчанию, поэтому в моем случае черный. Но случайным образом он становится красным. Если я установил для фона listviewitem явно черное, я не испытал ошибку. Честно говоря, я не знаю, как обходиться в вашем случае, но определить цвета всего штата может вам помочь.

Смежные вопросы