Alan Nelson
Alan Nelson

Reputation: 1229

How to pass data from custom Android ListView ArrayAdapter (when it has multiple onClickEventListeners) back to its fragment/activity

I need to PASS THE DATA (videoId) from inside this custom ArrayAdapter back to the fragment that holds it when the user clicks on the favorite button.

I also need to PASS THE DATA of the song's position back to the fragment if the user clicks the layout of the song. (Both onclicks defined below.)

Previously, the position of the song was passed to the containing fragment SelectSongFragment via this method:

mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l)  {
//pass data to main activity
//TODO THIS NO LONGER RUNS
String songUrl = urlCleaner.parseIntoUrl(mSongs.getSong(i).getVideoId(), false);
passData(songUrl);
}
});

After I added the onclick Listeners to the arrayAdapter, mListView.setOnItemClickListener stopped working, and now I have no way to pass any data back! Check my custom ArrayAdapter below, and look for "HELP NEEDED HERE" Thanks very much!

public class SelectSongArrayAdapter extends ArrayAdapter<Song> implements AppInfo {

private ArrayList<Song> songs;
private ArrayList<String> mFavoriteSongs;
private boolean isFavorite = false;
private Song song;

/**
 * Override the constructor for ArrayAdapter
 * The only variable we care about now ArrayList<PlatformVersion> objects
 * it is the list of the objects we want to display
 *
 * @param context
 * @param resource
 * @param objects
 */
public SelectSongArrayAdapter(Context context, int resource, ArrayList<Song> objects, ArrayList<String> favoriteSongVideoIds) {
    super(context, resource, objects);
    this.songs = objects;
    this.mFavoriteSongs = favoriteSongVideoIds;

}

/**
 * Primary functionality to create a list in the view of songs and song detail lines.
 *
 * @param position
 * @param convertView
 * @param parent
 * @return
 */
public View getView(int position, View convertView, ViewGroup parent) {
    // assign the view we are converting to a local variable
    View view = convertView;

    /*
      Check to see if view null.  If so, we have to inflate the view
      "inflate" basically mean to render or show the view
     */
    if (view == null) {
        LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        view = inflater.inflate(R.layout.detail_line_song, null);
    }

    song = songs.get(position);

    // obtain a reference to the widgets in the defined layout "wire up the widgets from detail_line"
    TextView songTitle = (TextView) view.findViewById(R.id.songTitle);
    TextView songDescription = (TextView) view.findViewById(R.id.songDescription);
    View viewSongLayout = view.findViewById(R.id.songLayout);  //For when user clicks left side of view

    final ImageButton favoriteStarButton = (ImageButton) view.findViewById(R.id.favorite);

    //Find out if song is favorite or not:
    isFavorite = false;
    for (String songId : mFavoriteSongs) {

        if (song.getVideoId().equals(songId)) {
            //Is not a favorite song. Do nothing

        } else {
            //Is a favorite song
            isFavorite = true;
            break;
        }
    }

    //TODO Testing with multiple favorite songs.
    songTitle.setText(song.getDisplayName());
    songDescription.setText(song.getDescription());
    favoriteStarButton.setPressed(isFavorite); //Changes star color


    //Add Listeners
    favoriteStarButton.setOnClickListener(new View.OnClickListener() { //Star button click
        @Override
        public void onClick(View v) {

            isFavorite = !isFavorite;
            if (isFavorite) {
                //Add to favoriteVideoIds
                /************************************************
                 HELP NEEDED HERE:
                 NEED TO PASS DATA (song.getVideoId()) BACK TO THE FRAGMENT SOMEHOW TO
                 REMOVE SONG FROM FAVORITES LIST OF SONGS STORED IN THE ACTIVITY
                 NOT HERE IN THE ARRAYADAPTER)
                 ********************************************************************/
            } else {
                //remove from favoriteVideoIds
                /************************************************
                 HELP NEEDED HERE:
                 NEED TO PASS DATA (song.getVideoId()) BACK TO THE FRAGMENT SOMEHOW TO
                 ADD SONG TO FAVORITES LIST OF SONGS STORED IN THE ACTIVITY
                 NOT HERE IN THE ARRAYADAPTER)
                 ********************************************************************/
            }
            v.setPressed(isFavorite); //Changes star color
            //redraw view
            v.invalidate();
        }
    });

    //Listener for when song is clicked (left side of listview)
    viewSongLayout.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            /******************************************************************
             SAME PROBLEM HERE. NEED TO PASS DATA (POSITION) OF THE SONG THAT WAS CLICKED BACK TO THE FRAGMENT.
********************************/

    return view;
}
}

Upvotes: 1

Views: 466

Answers (1)

Nika Kurdadze
Nika Kurdadze

Reputation: 2512

You can create an interface for your click events :

interface ClickEvents {
    void onFavoriteStarButtonClick(boolean isFavorite, int position);
    void onViewSongLayoutClick(int position);
}

Specify an instance of ClickEvents as an argument inside your ArrayAdapter constructor :

private ClickEvents clickEvents;

public SelectSongArrayAdapter(Context context, int resource, ArrayList<Song> objects, ArrayList<String> favoriteSongVideoIds, ClickEvents clickEvents) {
    super(context, resource, objects);
    this.songs = objects;
    this.mFavoriteSongs = favoriteSongVideoIds;
    this.clickEvents = clickEvents;
}    

Call the appropriate methods of ClickEvents inside your onClick methods :

favoriteStarButton.setOnClickListener(new View.OnClickListener() { //Star button click
    @Override
    public void onClick(View v) {
        isFavorite = !isFavorite;
        clickEvents.onFavoriteStarButtonClick(isFavorite, position);
    }
});

viewSongLayout.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        clickEvents.onViewSongLayoutClick(position);
    }
}

Finally pass an implementation of ClickEvents to your adapter as a parameter :

final ClickEvents clickEvents = new ClickEvents() {
        @Override
        public void onFavoriteStarButtonClick(boolean isFavorite, int position) {
            // FavoriteStarButton clicked
        }

        @Override
        public void onViewSongLayoutClick(int position) {
            // ViewSongLayout clicked
        }
    };

final SelectSongArrayAdapter selectSongArrayAdapter = new SelectSongArrayAdapter(getContext(), resource, objects, favoriteSongVideoIds, clickEvents);

Upvotes: 2

Related Questions