РЕДАКТИРОВАТЬ - см. Комментарии, это решение может быть неправильным
Я знаю этот вопрос древним, но это первый результат в Google, и я работаю над приложением, которое также использует Spinners в ListView. Я использовал пример кода из здесь , чтобы начать. Я надеюсь, что этот пример отвечает на ваш вопрос. Я не реализовывал CheckBox, но они очень похожи на Spinner - намного проще, на самом деле. В этом примере есть ListView с TextView и Spinner. Всякий раз, когда пользователь изменяет выбор в счетчике, TextView изменяется, чтобы отразить это.
Я разделил этот проект на 3 класса:
- ListViewTestActivity - основная деятельность
- DataAdapter - расширяет ArrayAdapter и работает для отображения элементов в ListView
- DataHolder - простой объект, который просто содержит некоторую информацию об элементе. Это может быть реализовано многими другими способами в соответствии с вашими потребностями.
Есть также 3 ключевых файла Android XML, которые я изменил / создал:
- main.xml - модифицированный - основной макет
- rowview.xml - добавлено - макет для каждого элемента в ListView
- strings.xml - изменено - файл строк Android по умолчанию
Для начала снизу вверх этот файл main.xml содержит только один ListView и ничего больше:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical"
android:layout_width="fill_parent" android:layout_height="fill_parent">
<ListView android:id="@+id/listView1" android:layout_height="match_parent" android:layout_width="match_parent" />
</LinearLayout>
А вот и rowview.xml. Помните, что это представление дублируется для каждой строки в ListView:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="wrap_content" android:weightSum="1">
<TextView android:layout_width="wrap_content"
android:layout_height="match_parent" android:id="@+id/text"
android:layout_weight="0.5" android:textSize="25sp" />
<Spinner android:layout_width="0dp" android:layout_height="wrap_content"
android:id="@+id/spin" android:prompt="@string/choice_prompt"
android:layout_weight="0.5" />
</LinearLayout>
Файл strings.xml. Все, что я добавил, был массив для содержимого счетчика:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello">Hello World, ListViewTestActivity!</string>
<string name="app_name">ListViewTest</string>
<string name="choice_prompt">Select a choice</string>
<string-array name="choices">
<item>Alpha</item>
<item>Bravo</item>
<item>Charlie</item>
</string-array>
</resources>
Теперь самое интересное. Класс ListViewActivity:
public class ListViewTestActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ListView listView = (ListView) findViewById(R.id.listView1);
DataHolder data = new DataHolder(this);
DataHolder data1 = new DataHolder(this);
DataHolder data2 = new DataHolder(this);
DataHolder data3 = new DataHolder(this);
DataHolder data4 = new DataHolder(this);
DataAdapter d = new DataAdapter(this, R.layout.rowview, new DataHolder[] { data, data1, data2, data3, data4 });
listView.setAdapter(d);
}
}
Это довольно просто, вы просто получаете список, создаете новый адаптер и устанавливаете адаптер ListView на тот, который вы создали. Это класс DataHolder:
public class DataHolder {
private int selected;
private ArrayAdapter<CharSequence> adapter;
public DataHolder(Context parent) {
adapter = ArrayAdapter.createFromResource(parent, R.array.choices, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
}
public ArrayAdapter<CharSequence> getAdapter() {
return adapter;
}
public String getText() {
return (String) adapter.getItem(selected);
}
public int getSelected() {
return selected;
}
public void setSelected(int selected) {
this.selected = selected;
}
}
Все, что делает класс DataHolder, - это содержит адаптер Spinner и любую другую информацию, которую вы, возможно, захотите сохранить для каждой записи в ListView (например, вы можете захотеть сохранить, проверена она или нет). И, наконец, настоящее «мясо» приложения, класс DataAdapter:
public class DataAdapter extends ArrayAdapter<DataHolder> {
private Activity myContext;
public DataAdapter(Activity context, int textViewResourceId, DataHolder[] objects) {
super(context, textViewResourceId, objects);
myContext = context;
}
// We keep this ViewHolder object to save time. It's quicker than findViewById() when repainting.
static class ViewHolder {
protected DataHolder data;
protected TextView text;
protected Spinner spin;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = null;
// Check to see if this row has already been painted once.
if (convertView == null) {
// If it hasn't, set up everything:
LayoutInflater inflator = myContext.getLayoutInflater();
view = inflator.inflate(R.layout.rowview, null);
// Make a new ViewHolder for this row, and modify its data and spinner:
final ViewHolder viewHolder = new ViewHolder();
viewHolder.text = (TextView) view.findViewById(R.id.text);
viewHolder.data = new DataHolder(myContext);
viewHolder.spin = (Spinner) view.findViewById(R.id.spin);
viewHolder.spin.setAdapter(viewHolder.data.getAdapter());
// Used to handle events when the user changes the Spinner selection:
viewHolder.spin.setOnItemSelectedListener(new OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
viewHolder.data.setSelected(arg2);
viewHolder.text.setText(viewHolder.data.getText());
}
@Override
public void onNothingSelected(AdapterView<?> arg0) {
}
});
// Update the TextView to reflect what's in the Spinner
viewHolder.text.setText(viewHolder.data.getText());
view.setTag(viewHolder);
Log.d("DBGINF", viewHolder.text.getText() + "");
} else {
view = convertView;
}
// This is what gets called every time the ListView refreshes
ViewHolder holder = (ViewHolder) view.getTag();
holder.text.setText(getItem(position).getText());
holder.spin.setSelection(getItem(position).getSelected());
return view;
}
}
Вот скриншот финального приложения (оно не очень красивое, но работает):
И это все! Надеюсь, я ответил на ваш вопрос и помог любому, кто наткнулся на него, как я. Если вы хотите динамически изменять данные в списке, используйте методы DataAdapter add()
, remove()
, get()
и set()
. Чтобы изменить данные для каждого отдельного счетчика, вам нужно изменить класс DataHolder. Здесь создается SpinnerAdapter, поэтому вам просто нужно динамически генерировать адаптеры в зависимости от ответа базы данных.