0

I am working on an Android app where I need to display a listview of Latin vocabulary words. I have looked over many tutorials and guides and have written custom ArrayAdapters and models but only one item in the list view is populated with the values I am passing it. Here are the pieces of code I feel are relevant.

My ArrayAdapter that uses the ViewHolder Pattern

public class MyArrayAdapter extends ArrayAdapter<Vocab> {
    private int layout;
    public MyArrayAdapter(Context context, int resource, ArrayList<Vocab> objects) {
        super(context, resource, objects);
        layout = resource;
    }

    private static class ViewHolder {

        TextView dict_entry;
        TextView definition;
        Button add;
    }

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        ViewHolder mainViewHolder = null;
        Vocab word = getItem(position);
        if(convertView == null){
            LayoutInflater inflater = LayoutInflater.from(getContext());
            convertView = inflater.inflate(layout, parent, false);
            ViewHolder viewHolder = new ViewHolder();
            viewHolder.dict_entry = (TextView)convertView.findViewById(R.id.TVdict_entry);
            viewHolder.definition = (TextView)convertView.findViewById(R.id.TVdefinition);
            viewHolder.add = (Button)convertView.findViewById(R.id.Badd);
            viewHolder.add.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Toast.makeText(getContext(), "Button was clicked for list item " + position, Toast.LENGTH_SHORT).show();
                }
            });
            convertView.setTag(viewHolder);
        } else {
            mainViewHolder = (ViewHolder)convertView.getTag();
            mainViewHolder.dict_entry.setText(word.dict_entry);
            mainViewHolder.definition.setText(word.definition);
        }

        return convertView;
    }
}

My Vocab Model

public class Vocab {
    public String dict_entry;
    public String definition;
    public String id;
    public Button add;

    public Vocab(JSONObject object){
        try {
            this.dict_entry = object.getString("dict_entry");
            this.definition = object.getString("definition");
            this.id = object.getString("id");
        } catch ( JSONException e){
            e.printStackTrace();
        }
    }

    public static ArrayList<Vocab> fromJSON(JSONArray jsonObjects){
        ArrayList<Vocab> words = new ArrayList<Vocab>();
        for(int i = 0; i < jsonObjects.length(); i++){
            try{
                words.add(new Vocab(jsonObjects.getJSONObject(i)));
            }catch (JSONException e){
                e.printStackTrace();
            }
        }
        return words;
    }
}

The code where I get a JSONArray and pass it to the Vocab construtor and then try to populate my LiveView

vocab_json = response;
            status.setText(response);

            try {
                JSONObject json = new JSONObject(response);
                JSONArray jsonArray = json.getJSONArray("all_words");
                ArrayList<Vocab> word_list = Vocab.fromJSON(jsonArray);

                ArrayList<Vocab> arrayOfVocab = new ArrayList<Vocab>();
                MyArrayAdapter adapter = new MyArrayAdapter(getBaseContext(), R.layout.vocab_list_item, arrayOfVocab);
                adapter.addAll(word_list);

                ListView listView = (ListView) findViewById(R.id.LVvocabwords);
                listView.setAdapter(adapter);
            }catch(JSONException e){
                e.printStackTrace();
            }

The Layout in case it matters

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:descendantFocusability="beforeDescendants">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="Dict_Entry"
        android:id="@+id/TVdict_entry"
        android:layout_alignBottom="@+id/Badd"
        android:layout_alignParentTop="true" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="Definition"
        android:id="@+id/TVdefinition"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_alignBottom="@+id/Badd" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Add"
        android:id="@+id/Badd"
        android:layout_alignParentTop="true"
        android:layout_alignParentEnd="true" />
</RelativeLayout>

Only the first element has the default text for the textviews changed. Any help would be much appreciated, I am sure it is something simple I am overlooking.

4
  • Wat's word_list .count() ?? Commented Aug 14, 2015 at 8:06
  • Button will take focus from the ListView item Commented Aug 14, 2015 at 8:08
  • Try to log the values, and see where exactly are you missing the data. Commented Aug 14, 2015 at 8:11
  • 1
    Outside if else statement: viewHolder.add.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(getContext(), "Button was clicked for list item " + position, Toast.LENGTH_SHORT).show(); } }); mainViewHolder.dict_entry.setText(word.dict_entry); mainViewHolder.definition.setText(word.definition); Commented Aug 14, 2015 at 8:11

1 Answer 1

3

Change your adapter class like this.

public class MyArrayAdapter extends ArrayAdapter<Vocab> {
    private int layout;
    public MyArrayAdapter(Context context, int resource, ArrayList<Vocab> objects) {
        super(context, resource, objects);
        layout = resource;
    }

    private static class ViewHolder {

        TextView dict_entry;
        TextView definition;
        Button add;
    }

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        ViewHolder viewHolder = null;
        Vocab word = getItem(position);
        if(convertView == null){
            LayoutInflater inflater = LayoutInflater.from(getContext());
            convertView = inflater.inflate(layout, parent, false);
            viewHolder = new ViewHolder();
            viewHolder.dict_entry = (TextView)convertView.findViewById(R.id.TVdict_entry);
            viewHolder.definition = (TextView)convertView.findViewById(R.id.TVdefinition);
            viewHolder.add = (Button)convertView.findViewById(R.id.Badd);
            convertView.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder)convertView.getTag();
        }
         viewHolder.dict_entry.setText(word.dict_entry);
         viewHolder.definition.setText(word.definition);    

            viewHolder.add.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Toast.makeText(getContext(), "Button was clicked for list item " + position, Toast.LENGTH_SHORT).show();
                }
            });

        return convertView;
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

This code does not work viewHolder -> mainViewHolder 2 times convertedView.getTag()
Have you complied the code or just saying it doesn't work?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.