Search code examples
androidlistviewadapterlistadapter

A row is clicked in an adapter, how do I update the Views of neighbouring rows?


I have tried two ways. What I want to do is award the highest scoring player a trophy, and then take it away when another player scores higher. Both attempts have been adapter based, rather than outside it. I beleive this may not be possible because the adapter is designed to be a provider of views not a editor.

The first way I tried, kept track of the high score, and the row's trophy ImageView with globals in the adapter. So when a new highscore came along I made the old high score invisible and updated the globals. This worked but it didn't update the data set, so when it scrolled off screen, it forgot the leading row's trophy image.

So instead of making a copy of the Trophy winning ImageView, I tried to edit the data set, by accessing the Trophy ImageView by casting the adapters parent to (ListView) then getting its child.

NotifyDataChange() seemed to block this. With this commented out it caused anomalies where row's copied the trophy winners score.

From reading I believe that after a onClick event, I should possibly be hiding the former score leader's trophy ImageView from the class where I set the adapter on the ListView. But I don't know how to do this.

This is the wonky code at present:

    public void updateTrophyView(ScoreHolder holder, int newScore, int position, ViewGroup parent) {
    ListView parentListView = (ListView) parent;
    Log.wtf(TAG, "updating Trophy View?");
    if (highestScore != 0) {
        Log.wtf(TAG, "hidden old view?");
        //highestScorerTrophyView.setVisibility(View.INVISIBLE);

        //View retiredWinner = parentListView.getChildAt(oldPosition - parentListView.getFirstVisiblePosition());
        //retiredWinner.findViewById(R.id.trophyView).setVisibility(View.INVISIBLE)
    }
    Log.i(TAG, "toggling visibility?");
    highestScore = newScore;
    ((ImageView) parentListView.getChildAt(position - parentListView.getFirstVisiblePosition())
            .findViewById(R.id.trophyView)).setImageResource(R.drawable.ic_trophy);//.setVisibility(View.VISIBLE);
    //newLeader.setImageResource(R.drawable.ic_trophy);
    //newLeader.setVisibility(View.VISIBLE);
    //TODO need to find a reference to entire list

    /* THIS IS NOT CHANGING THE UNDERLYING DATA SET, JUST THE VIEWS,
    *  so when goes of screen adapter erases views, forgets changes.
    highestScore = newScore;
    holder.trophyImageView.setVisibility(View.VISIBLE);
    highestScorerTrophyView = holder.trophyImageView; */
    // need to make sure the listView the adapter is connected to is updated.
    notifyDataSetChanged();
}

Here's a picture, I want this sans bugs, please help! :) enter image description here


Solution

  • What I would do is put the trophy as a field in the object that populates the list (For example boolean isHighScore = true;), and loop on all the objects in the list and make them all false except the one with the highest score. That way, when the view in the list gets destroyed and re-created, the trophy's ImageView will appear only if isHighScore==true, else hide it.