如何将数据从自定义 Android ListView ArrayAdapter(当它有多个 onClickEventListeners 时)传回其 fragment/activity
How to pass data from custom Android ListView ArrayAdapter (when it has multiple onClickEventListeners) back to its fragment/activity
我需要将数据 (videoId) 从这个自定义 ArrayAdapter 内部传递回当用户单击收藏夹按钮时保存它的片段。
如果用户点击歌曲的布局,我还需要将歌曲位置的数据传递回片段。 (下面定义了两个点击。)
以前,歌曲的位置是通过此方法传递给包含片段 SelectSongFragment 的:
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);
}
});
我给arrayAdapter添加了onclick Listeners后,mListView.setOnItemClickListener就停止工作了,现在我没有办法传回任何数据了!检查下面我的自定义 ArrayAdapter,并寻找 "HELP NEEDED HERE" 非常感谢!
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;
}
}
您可以为您的点击事件创建一个界面:
interface ClickEvents {
void onFavoriteStarButtonClick(boolean isFavorite, int position);
void onViewSongLayoutClick(int position);
}
将 ClickEvents
的实例指定为 ArrayAdapter
构造函数中的参数:
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;
}
在您的 onClick
方法中调用 ClickEvents
的适当方法:
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);
}
}
最后将 ClickEvents
的实现作为参数传递给您的适配器:
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);
我需要将数据 (videoId) 从这个自定义 ArrayAdapter 内部传递回当用户单击收藏夹按钮时保存它的片段。
如果用户点击歌曲的布局,我还需要将歌曲位置的数据传递回片段。 (下面定义了两个点击。)
以前,歌曲的位置是通过此方法传递给包含片段 SelectSongFragment 的:
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);
}
});
我给arrayAdapter添加了onclick Listeners后,mListView.setOnItemClickListener就停止工作了,现在我没有办法传回任何数据了!检查下面我的自定义 ArrayAdapter,并寻找 "HELP NEEDED HERE" 非常感谢!
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;
}
}
您可以为您的点击事件创建一个界面:
interface ClickEvents {
void onFavoriteStarButtonClick(boolean isFavorite, int position);
void onViewSongLayoutClick(int position);
}
将 ClickEvents
的实例指定为 ArrayAdapter
构造函数中的参数:
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;
}
在您的 onClick
方法中调用 ClickEvents
的适当方法:
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);
}
}
最后将 ClickEvents
的实现作为参数传递给您的适配器:
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);