Неожиданные результаты при создании селектора из кода, а не из XML
У меня возникли проблемы с преобразованием некоторых рабочих XML-файлов в код. У меня есть ListView, и мне нужно иметь возможность переключать его нажатые / проверенные отрисовки во время выполнения из ресурсов, не известных в продвинутом (поэтому, почему бы не использовать XML);
Следующая конфигурация прекрасно работает:
main.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:orientation="vertical" >
<ListView
android:id="@+id/listView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:choiceMode="singleChoice" >
</ListView>
</LinearLayout>
selector.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/blue" android:state_pressed="true"/>
<item android:drawable="@drawable/green" android:state_checked="true"/>
<item android:drawable="@drawable/orange"/>
</selector>
list_row.xml:
<?xml version="1.0" encoding="utf-8"?>
<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@drawable/selector"
android:padding="10dp" />
Main.java:
public class Main extends Activity {
StateListDrawable selector;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ListView listView1 = (ListView) findViewById(R.id.listView1);
StringAdapter adapter = new StringAdapter(this, R.layout.list_row);
adapter.add("one"); adapter.add("two"); adapter.add("three"); adapter.add("four");
adapter.add("five"); adapter.add("six"); adapter.add("seven"); adapter.add("eight");
adapter.add("nine"); adapter.add("ten"); adapter.add("eleven"); adapter.add("twelve");
listView1.setAdapter(adapter);
}
private class StringAdapter extends ArrayAdapter<String>{
public StringAdapter(Context context, int textViewResourceId) {
super(context, textViewResourceId);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final CheckedTextView tv = (CheckedTextView ) inflater.inflate(R.layout.list_row, parent, false);
tv.setText(getItem(position));
return tv;
}
}
}
Результат такой: отличный (нажал: синий, проверил: зеленый, остальное: оранжевый):
Однако, если я удалю
android:background="@drawable/selector
из list_row_xml и примените его с помощью кода:
Drawable blue = getResources().getDrawable(R.drawable.blue);
Drawable green = getResources().getDrawable(R.drawable.green);
Drawable orange = getResources().getDrawable(R.drawable.orange);
selector = new StateListDrawable();
selector.addState(new int[] { android.R.attr.state_pressed }, blue);
selector.addState(new int[] { android.R.attr.state_checked }, green);
selector.addState(new int[] { }, orange);
tv.setBackgroundDrawable(selector);
Я получаю следующее (все получают state_pressed drawable, синий):
Есть идеи, что пошло не так? Я почти уверен, что преобразовал селектор в код соответствующим образом... Спасибо.
1 ответ
Я скопировал ваш код, и все работает нормально. Вы должны убедиться, что создали новый экземпляр selector
в getView()
хоть. В противном случае, если вы используете тот же selector
для всех ваших предметов нажатие одного предмета повлияет на все ваши предметы.
Вот то, что ваш getView()
метод должен выглядеть так
@Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final CheckedTextView tv = (CheckedTextView) inflater.inflate(R.layout.list_row, parent, false);
tv.setText(getItem(position));
Drawable blue = getResources().getDrawable(R.drawable.blue);
Drawable green = getResources().getDrawable(R.drawable.green);
Drawable orange = getResources().getDrawable(R.drawable.orange);
selector = new StateListDrawable();
selector.addState(new int[] { android.R.attr.state_pressed }, blue);
selector.addState(new int[] { android.R.attr.state_checked }, green);
selector.addState(new int[] {}, orange);
tv.setBackgroundDrawable(selector);
return tv;
}
Конечно, есть некоторая оптимизация, которую вы можете сделать, но это сработает.