0

so I have this huge problem with applying a strikethrough on a ListView item while populating it from the List of my objects.

    private void setListItems() {
        DatabaseHandler db = new DatabaseHandler(this);
        List<ToDoTask> taskList = db.getAllTasks();

        for (ToDoTask tt : taskList) {
            this.listAdapter.add(tt.getName());
        }

        this.listAdapter.notifyDataSetChanged();
    }

This part of the code populates my ListView. Now i want to add a strikethrough to item if

    tt.getActive() == 0

I don't know how can i get a TextView item from my ListView. I tried in my for loop to:

    TextView textView = (TextView) this.listView.getChildAt(this.listView.getCount() -1);

but the app crashes. The only solution that didn't crash my app was:

    TextView textView = this.listAdapter.getView(this.listView.getCount() -1, null, null)

but it didn't actually change anything in the ListView. I think it's not referencing the object itself. Here's some code that instantiates my variables:

    this.listView = (ListView) findViewById(R.id.listViewItem);
    this.listItems = new ArrayList<String>();
    this.listAdapter = new ArrayAdapter<String>(this, 
            android.R.layout.simple_list_item_1, this.listItems);
    this.listView.setAdapter(this.listAdapter);

1 Answers1

2

The list view is not in charge of instantiating or modifying the underlying state of the views it contains. That's the job of the adapter. When you scroll a ListView, it calls the adapter method getView() and the adapter will hand it a row (possibly a recycled view from the rows that scrolled off-screen).

Inside the getView() method, the adapter should consult the underlying data set and modify the row as needed - that would include crossing out text, or setting any visual properties of the row content.

Collin Flynn
  • 741
  • 6
  • 8
  • @user3170934: And, with respect to the strikethrough part, you would need to monkey around with `StrikethroughSpan`. – CommonsWare Jan 07 '14 at 22:48
  • @Collin FLynn: If I understand you correctly, I need to get TextView element by typing `TextView tv = this.listAdapter.getView(this.listView.getCount() - 1, null, this.listView)`. Yes, that gives me a TextView object, but when i set flags on this guy, it doens't affect the listView and the listAdapter. Should i tell listAdapter to somehow update the view at given position? – user3170934 Jan 09 '14 at 19:01
  • @user3170934 Yes, you should tell the adapter to update the view. One way is to use the `ViewHolder` pattern to your advantage. Have the adapter store the position int inside each `ViewHolder` for each row. Write a method in your adapter that takes a row (whatever your row is - some view) as a parameter. From the row, grab the view holder and inspect the position int to see which item it is in the data set. You should hold that state as part of the data set inside the adapter, and inside the `getView` method, check the state of the view your being asked to deliver, then construct it. – Collin Flynn Jan 09 '14 at 22:26
  • I should also mention - if you make a change to the data set, call `notifyDataSetChanged()` and the `ListView` will be prompted to ask for all the rows from the adapter once again. The adapter can then construct those rows with the modified data set. – Collin Flynn Jan 09 '14 at 22:28