Updating views within a single row of a ListView when clicked

徘徊边缘 提交于 2019-12-25 09:21:26

问题


I was wondering how to update views/UI (say, making a TextView invisible) within a single row of a ListView when clicking on the row because every other rows' views would be affected as well. A good example would be playing a song in Google Play Music, and the equalizer animation would be displayed accordingly. Here are my snippets:

MainActivity's onCreate():

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main); // Renders only a ListView

    ListView songListView = (ListView) findViewById(R.id.list);
    List<Song> songList = new ArrayList<>();
    for (int i = 1; i <= 200; i++) songList.add(new Song("Song" + i, "Artist" + i));
    SongAdapter songAdapter = new SongAdapter(this, songList);
    songListView.setAdapter(songAdapter);
    songListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long l) {
            if (position == view.getId()) {
                TextView titleText = (TextView) view.findViewById(R.id.song_title);
                titleText.setVisibility(View.INVISIBLE);
            }
        }
    });
}

... and my ArrayAdapter's getView method and ViewHolder class:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolder holder;

    if (convertView == null) {
        convertView = LayoutInflater.from(getContext()).inflate(R.layout.list_item, parent,
                false);

        holder = new ViewHolder();
        holder.song = (TextView) convertView.findViewById(R.id.song_title);
        holder.artist = (TextView) convertView.findViewById(R.id.song_artist);

        convertView.setTag(holder);
    } else {
        holder = (ViewHolder) convertView.getTag();
    }

    convertView.setId(position);

    Song currentSong = getItem(position);

    if (currentSong != null) {
        holder.song.setText(currentSong.getTitle());
        holder.artist.setText(currentSong.getArtist());
    }

    return convertView;
}

private static class ViewHolder {
    TextView song;
    TextView artist;
}

回答1:


Add one more variable in your song model class to make visibility for each row, please try this below code :

class Song{
    private boolean isShowing =false;

    public boolean isShowing() {
        return isShowing;
    }

    public void setShowing(boolean showing) {
        isShowing = showing;
    }
}

SongsAdapter.class

class SongAdapter extends BaseAdapter {
           private Context mContext;
           private List<Song> mSongList;


           public SongAdapter(Context context, List<Song> songs) {
               mContext = context;
               mSongList = songs;
           }

           @Override
           public int getCount() {
               return mSongList.size();
           }

           @Override
           public Object getItem(int i) {
               return null;
           }

           @Override
           public long getItemId(int i) {
               return 0;
           }

           @Override
           public View getView(final int position, View convertView, ViewGroup parent) {
               ViewHolder holder;

               if (convertView == null) {
                   convertView = LayoutInflater.from(mContext).inflate(R.layout.list_item, parent,
                           false);
                   holder = new ViewHolder(convertView);

                   convertView.setTag(holder);
               } else {
                   holder = (ViewHolder) convertView.getTag();
               }

               final Song songModel = mSongList.get(position);
               holder.song.setText(songModel.getSongTitle());
               holder.artist.setText(songModel.getSongArtist());

               if(songModel.isShowing()){
                   holder.song.setVisibility(View.VISIBLE);
               }else{
                   holder.song.setVisibility(View.GONE);
               }
               convertView.setOnClickListener(new View.OnClickListener() {
                   @Override
                   public void onClick(View view) {
                       if(songModel.isShowing()){
                           songModel.setShowing(false);
                       }else{
                           songModel.setShowing(true);
                       }

                       notifyDataSetChanged();

                   }
               });
               return convertView;
           }

           public class ViewHolder{
               TextView song;
               TextView artist;

               public ViewHolder(View itemView) {
                   song = (TextView)itemView.findViewById(R.id.song_title);
                   artist = (TextView)itemView.findViewById(R.id.artist);

               }

           }
       }



回答2:


Hope this helps:

holder.song.setId(position);

Then your code looks like this:

mSongView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long l) {
    Log.d(LOG_TAG, "Song item clicked");
    TextView titleText = (TextView) view.findViewById(position);
    titleText.setVisibility(View.INVISIBLE);

}
});



回答3:


Add the below code in your adapter class

public interface OnItemClickListener {
void onClick(View view);}
private final OnItemClickListener listener;
public YourAdapter(Context mContext, OnItemClickListener listener) {
this.mContext = mContext;
this.listener = listener;}

Modify your viewholder class

class ViewHolder implements View.OnClickListener {

TextView song;
TextView artist;

ViewHolder(View itemView) {
    super(itemView);
    song = (TextView)itemView.findViewById(R.id.txt1);
    artist = (TextView)itemView.findViewById(R.id.txt2);
    itemView.setOnClickListener(this);

}

 @ Override
public void onClick(View v) {
    listener.onClick(v);
}

And lastly implement the interface in your Activity class

class MainActivity extends AppCompatActivity implements YourAdapter.OnItemClickListener{
 @Override
public void onClick(View view) {
   TextView titleText = (TextView) view.findViewById(R.id.song_title);
        titleText.setVisibility(View.INVISIBLE);
}

}




回答4:


I finally figured this out after getting help from my mentor. Initializing an int field in the adapter to keep record of previous positions in the list did the trick as follows:

MainActivity:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ListView songListView = (ListView) findViewById(R.id.list);
        List<Song> songList = new ArrayList<>();
        for (int i = 1; i <= 200; i++) songList.add(new Song("Song" + i, "Artist" + i));
        final SongAdapter songAdapter = new SongAdapter(this, songList);
        songListView.setAdapter(songAdapter);
        songListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long l) {
                songAdapter.setSongPosition(position);
                songAdapter.notifyDataSetChanged();
            }
        });
    }
}

Custom Song class:

public class Song {
    private String mSongTitle, mSongArtist;

    public Song(String songTitle, String songArtist) {
        mSongTitle = songTitle;
        mSongArtist = songArtist;
    }

    public String getSongTitle() {
        return mSongTitle;
    }

    public String getSongArtist() {
        return mSongArtist;
    }
}

Custom adapter:

public class SongAdapter extends ArrayAdapter<Song> {
    private int currentlyPlaying = -1;

    public SongAdapter(Context context, List<Song> songList) {
        super(context, 0, songList);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;

        if (convertView == null) {
            convertView = LayoutInflater.from(getContext()).inflate(R.layout.list_item, parent,
                    false);

            holder = new ViewHolder(convertView);

            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        Song song = getItem(position);
        holder.song.setText(song.getSongTitle());
        holder.artist.setText(song.getSongArtist());

        // Hides the row, so both TextViews. Otherwise, sets each row visible.
        if (position == currentlyPlaying) convertView.setVisibility(View.INVISIBLE);
        else convertView.setVisibility(View.VISIBLE);

        return convertView;
    }

    private class ViewHolder {
        private TextView song;
        private TextView artist;

        private ViewHolder(View itemView) {
            song = (TextView) itemView.findViewById(R.id.song_title);
            artist = (TextView) itemView.findViewById(R.id.artist);
        }
    }

    public void setSongPosition(int position) {
        currentlyPlaying = position;
    }
}


来源:https://stackoverflow.com/questions/43075352/updating-views-within-a-single-row-of-a-listview-when-clicked

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!