0

I have implementing a tutorial and I have a problem to adapt to my way.

The main.xml with de 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>

The rowview.xml

<?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>

The strings.xml file.

<?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>

The ListViewActivity class:

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);
    }
}

The DataHolder class:

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;
    }

}

All the DataHolder class :

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;
    }
}

To see the result of this code, see -> Android Listview with spinner and a checkbox

This code works, I have a listView with a spinner for each item, but how I can fill spinners with my own Strings? I tryed to fill them in the DataHolder class but it fails. (I have a list of Strings).

Thank's in advance.

Community
  • 1
  • 1
Pierre
  • 450
  • 6
  • 18
  • To me it looks like portions of your code are correct but you are populating the `listview` with your spinner objects: `` instead of populating a listview with strings and then attaching your "choices" to those. – Ryan Sayles Jun 12 '13 at 12:45
  • yes I know, but I don't know how I can populate the spinner with my own strings – Pierre Jun 12 '13 at 13:53

1 Answers1

0

All the work is done in the ADAPTER here your DataAdapter.

The cells are constructed in the method GetView, each cells is recycled : if convertView is null you create a new cell to use or else you use convertView.

i assume you must change some code in your DataHolder

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);
}

For now you must understand that the array of choices is provided statically :

R.array.choices

One solution would be to pass your data when constructing the viewHolders here :

 viewHolder.data = new DataHolder(myContext);

should looks like something like this :

 viewHolder.data = new DataHolder(myContext, myDataArray);

and then in your class change the instanciation of the adapter with something more like that..

public DataHolder(Context parent, ArrayList<String> dataArray) {
    adapter = new ArrayAdapter<String>(myContext, yourTextViewId, dataArray);
    adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
}

hopes it help good luck

An-droid
  • 6,433
  • 9
  • 48
  • 93
  • Ok I understand but I have somme problem for the implementation. In ListViewTestActivity I instantiate an ArrayList (I fill it) and I pass in arguments of the DataHolder constructor. Also, I have modified the DataHolder class. The ArrayAdapter becomes an ArrayAdapter. Ok but, in the DataAdapter class, with the line "viewHolder.data = new DataHolder(myContext);" I don't know what I can do... – Pierre Jun 12 '13 at 13:02
  • Just for you to know using String is much more casual than CharSequence and more user friendly. But it gives the same result for basic use. You can add an 'ArrayList' to your 'DataAdapter' to manage the data you want to pass to viewHolder.data it depends where those data can be retreived from ? – An-droid Jun 12 '13 at 21:19
  • So, I add the private variable ArrayList myList to the DataAdapter class and I add this list in the constructor of this class, ok. But then? I have to keep the ArrayAdapter present int the DataHolder class? And I don't know how a can manage the Strings in the DataAdapter class. Thank's – Pierre Jun 13 '13 at 07:23