MyAdapter:
public class voice_player_listview_adapter extends ArrayAdapter<String> {
public ArrayList<String> Duration=null;
public ArrayList<String> voice_id=null;
private Activity context;
public voice_player_listview_adapter(Activity context,ArrayList<String> voice_id,ArrayList<String> Duration) {
super(context, R.layout.voice_player_listview,sender);
// TODO Auto-generated constructor stub
this.context=context;
this.voice_id=voice_id;
this.Duration=Duration;
}
public View getView(final int position, final View convertView, ViewGroup parent) {
View rowView=convertView;
final viewHolder holder; //viewHolder already created in some where
if (rowView==null)
{
LayoutInflater inflater = context.getLayoutInflater();
rowView = inflater.inflate(R.layout.voice_player_listview, parent, false);
holder= new viewHolder();
holder.icon=(ImageView) rowView.findViewById(R.id.download_play_icon);
holder.voice_duration=(TextView) rowView.findViewById(R.id.voiceDuration);
holder.voice_player_seekbar=(SeekBar) rowView.findViewById(R.id.voice_player_seekbar);
rowView.setTag(holder);
}
else
{
holder= (viewHolder) convertView.getTag();
}
holder.voice_duration.setText("00:"+this.Duration.get(position));
holder.icon.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
new voicePlayer(voice_id.get(position),holder);
}
});
...
VoicePlayer:
class voicePlayer {
MediaPlayer mediaPlayer;
SeekBar seekbar;
TextView voice_duration;
ImageView icon;
viewHolder rowView;
final Handler handler = new Handler();
public void getViews()
{
this.seekbar=rowView.voice_player_seekbar;
this.voice_duration=rowView.voice_duration;
this.icon=rowView.icon;
}
public voicePlayer(String voice_id,WavesAPI.viewHolder holder) {
this.rowView=holder;
getViews();
try {
mediaPlayer=new MediaPlayer();
FileInputStream fis = new FileInputStream(Environment.getExternalStorageDirectory()...);
mediaPlayer.setDataSource(fis.getFD());
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.prepare();
mediaPlayer.start();
this.icon.setImageResource(R.drawable.pause);
this.updateSeekbar();
this.seekbar_listener();
} catch (IOException e) {
}
} catch (IOException e) {
}
}
}
private void updateSeekbar()
{
final Runnable runnable = new Runnable() {
public void run() {
int position= // calculating the position of the mediaPlayer for updating the seekbar
seekbar.setProgress(position);
handler.postDelayed(this, 50);
voice_duration.setText("00:"+((WavesAPI.player_data.mediaPlayer.getDuration()/1000)-(WavesAPI.player_data.mediaPlayer.getCurrentPosition()/1000)));
}
};
handler.post(runnable);
}
public void seekbar_listener()
{
seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (fromUser)
{
int player_position=// calc new postion of the mediaPlayer
mediaPlayer.seekTo(player_position);
}
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
}
}
The problem: when i click on play icon on the row of listview the music plays and the seekbar gets updated correctly as long as i don't scroll. But, Since the screen/listview fit only 3 items, when i scroll down, every 4 row, i see the new row seekbar is updating with the same progress of the old row i played and scrolled off. i think the convertView generates the same old instance view that once created and passed to the voicePlayer. once i didn't consider convertView and for every getView i create new rowView by inflater.inflate , the duplicating instance issue was resolved but when i scroll off a item and re-scroll back to the item, updating was stopped.
The problem solved. i used ScrollView instead of ListView
Related
I have a ListView of audios which have seek bar in it . When I click the play button of one of audios, it starts but when I scroll down I see that some other seekbars are also playing and when I scroll up again the first item that I clicked is no paused. I have searched a lot and it seems that there is a problem with position of item in list , the only solution I found was to use viewholder in adapter but it didn't work . does any one have a solution? thanks.
public class AudioAdapter extends ArrayAdapter<News> {
Context context;
boolean isPLaying = false;
public AudioAdapter(Context context, ArrayList<News> array) {
super(context, R.layout.list_item_news, array);
this.context = context;
}
public static class ViewHolder {
TextView txtTitle;
SeekBar seekBar;
TextView audioDuration;
ImageView btnPlayStop;
MediaPlayer mp;
Handler seekHandler;
int audioCurrentPosition;
}
public View getView(final int position, View convertView, ViewGroup parent) {
final News news = getItem(position);
final ViewHolder viewHolder;
if (convertView == null) {
viewHolder = new ViewHolder();
convertView = LayoutInflater.from(getContext())
.inflate(R.layout.list_item_audio, parent, false);
viewHolder.txtTitle = (TextView) convertView.findViewById(R.id.audioTitle);
viewHolder.seekBar = (SeekBar) convertView.findViewById(seek_bar);
viewHolder.audioDuration = (TextView) convertView.findViewById(R.id.txtDuration);
viewHolder.btnPlayStop = (ImageView) convertView.findViewById(R.id.btnPlayStop);
viewHolder.mp = new MediaPlayer();
viewHolder.seekHandler = new Handler();
convertView.setTag(viewHolder);
}
else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.txtTitle.setText(news.getTitle());
viewHolder.mp = MediaPlayer.create(context, R.raw.team);
viewHolder.audioCurrentPosition = news.getAudioPosition();
viewHolder.mp.seekTo(viewHolder.audioCurrentPosition * 1000);
viewHolder.audioDuration.setText(ms);
viewHolder.btnPlayStop.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if ( !isPLaying) {
viewHolder.mp.seekTo(viewHolder.audioCurrentPosition * 1000);
//play
isPLaying = true;
viewHolder.btnPlayStop.setImageResource(ic_media_pause);
viewHolder.mp.start();
viewHolder.seekBar.setMax( viewHolder.mp.getDuration() / 1000);
((Activity) context).runOnUiThread(new Runnable() {
#Override
public void run() {
if ( viewHolder.mp != null && viewHolder.mp.isPlaying()) {
int mCurrentPosition = viewHolder.mp.getCurrentPosition() / 1000;
viewHolder.seekBar.setProgress(mCurrentPosition);
viewHolder.seekHandler.postDelayed(this, 1000);
news.setAudioPosition( viewHolder.mp.getCurrentPosition() / 1000);
}
}
});
} else {
//pause
isPLaying = false;
viewHolder.btnPlayStop.setImageResource(ic_media_play);
viewHolder.audioCurrentPosition = viewHolder.mp.getCurrentPosition() / 1000;
viewHolder.mp.pause();
}
}
});
viewHolder.seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if ( viewHolder.mp != null && fromUser) {
//Change the seekbar with finger
viewHolder.mp.seekTo(progress * 1000);
viewHolder.audioCurrentPosition = progress * 1000;
}
}
});
viewHolder.mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
//When mediaplayer finishes
isPLaying = false;
viewHolder.btnPlayStop.setImageResource(ic_media_play);
viewHolder.audioCurrentPosition = 0;
}
});
return convertView;
}
}
Since you are using ViewHolder pattern, your views are being recycled and hence, your playing-indicator gets reused too...
Release your old MediaPlayer when you a new instance is started. For example:
protected void mediaplayerMethod(String filepath) {
Log.d(TAG, "mediaplayerMethod audio file path " + filepath);
if(mp != null){
mp.release();
}
mp = null;
mp = new MediaPlayer();
mp.setOnCompletionListener(AudioAdapter.this); // Important
seekBar.setOnSeekBarChangeListener(AudioAdapter.this);
utils = new Utilities();
playSong(filepath);
}
EDIT 1
You can try the below code
public class SoundTest extends Activity {
private ListView lv1;
private String lv_arr[]={"test 1","test 2","test 3","test 4","test 5"};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
lv1=(ListView)findViewById(R.id.ListView01);
lv1.setAdapter(new ArrayAdapter<String>(this,R.layout.list_item, lv_arr));
lv1.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,int position, long id) {
if (lv1.getItemAtPosition(position)=="test 1") {
MediaPlayer mp = MediaPlayer.create(getApplicationContext(),R.raw.sound1);
mp.start();
mp.setOnCompletionListener(new OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
mp.release();
}
});
}
if (lv1.getItemAtPosition(position)=="test 2") {
MediaPlayer mp = MediaPlayer.create(getApplicationContext(),R.raw.sound2);
mp.start();
mp.setOnCompletionListener(new OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
mp.release();
}
});
}
//And the rest of the audio 3,4,5.
}
});
}
}
The global variable MediaPlayer needs to be set private static. This has caught me several times.
I am new on Android. I have a listview, which have image, text and play/pause button. When I click on a play button in a row and then click on the play button in another row, the background of both buttons remain pause. So I want that when I click on play button in a row and then click on the play button in another row, the background of first button should change to play and background of second should remain pause. Thanks in advance.
public class MyListAdapter extends ArrayAdapter<String> {
private String[] gelenurl;
List<String> gelen_ad;
public static MediaPlayer mPlayer= new MediaPlayer();
private int layout;
public MyListAdapter(Context context, int resource, List<String> objects, String[] arr) {
super(context, resource, objects);
layout=resource;
gelenurl=arr;
gelen_ad=objects;
}
#NonNull
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder mainViewholder;
if(convertView==null) {
LayoutInflater inflater = LayoutInflater.from(getContext());
convertView=inflater.inflate(layout, parent, false);
mainViewholder= new ViewHolder();
convertView.setTag(mainViewholder);
}
else {
mainViewholder = (ViewHolder) convertView.getTag();
}
mainViewholder.img = (ImageView) convertView.findViewById(R.id.list_item_thumbnail);
mainViewholder.img.setImageResource(R.drawable.ic_radio);
mainViewholder.title = (TextView) convertView.findViewById(R.id.list_item_text);
mainViewholder.title.setText(getItem(position));
mainViewholder.button = (ImageButton) convertView.findViewById(R.id.list_item_btn);
mainViewholder.button.setImageResource(R.drawable.transparent_play);
mainViewholder.button.setBackgroundColor(Color.WHITE);
mainViewholder.button.setVisibility(View.VISIBLE);
mainViewholder.stop_button = (ImageButton) convertView.findViewById(R.id.list_item_stop_btn);
mainViewholder.stop_button.setImageResource(R.drawable.transparent_stop);
mainViewholder.stop_button.setBackgroundColor(Color.WHITE);
final ViewHolder vh = mainViewholder;
vh.stop_button.setVisibility(View.INVISIBLE);
mainViewholder.button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
vh.button.setVisibility(View.INVISIBLE);
vh.stop_button.setVisibility(View.VISIBLE);
try {
radioLinks(gelenurl[position]);
} catch (IOException e) {
e.printStackTrace();
}
}
public void radioLinks(String city) throws IOException {
if(mPlayer.isPlaying()) {
mPlayer.stop();
mPlayer.reset();
}
mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mPlayer.setDataSource(city);
mPlayer.prepareAsync();
mPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mPlayer.start();
}
});
}
});
mainViewholder.stop_button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
vh.button.setVisibility(View.VISIBLE);
vh.stop_button.setVisibility(View.INVISIBLE);
mPlayer.stop();
mPlayer.reset();
}
});
return convertView;
}
}
You will want to track the currently playing song with a member variable. Something like private String currentCity = null. Inside the onClick handler for play, you'll set that to the selected item, and call notifyDataSetChanged to tell the adapter to refresh everything. Inside the stop callback, you'll probably need to set currentCity = null after stopping and again call notifyDataSetChanged()
try {
currentCity = gelenurl[position];
radioLinks(currentCity);
notifyDataSetChanged();
} catch (IOException e) {
e.printStackTrace();
}
You want to use that information inside getView() to decide what to show.
mainViewholder.img = (ImageView) convertView.findViewById(R.id.list_item_thumbnail);
mainViewholder.img.setImageResource(R.drawable.ic_radio);
mainViewholder.title = (TextView) convertView.findViewById(R.id.list_item_text);
mainViewholder.title.setText(getItem(position));
mainViewholder.button = (ImageButton) convertView.findViewById(R.id.list_item_btn);
mainViewholder.button.setImageResource(R.drawable.transparent_play);
mainViewholder.button.setBackgroundColor(Color.WHITE);
...
if ( getItem(position) == currentCity ) {
// show stop button
} else {
/// show play button
}
I have a list in which each element on a player. When I click on "start" and a song starts playing strip seekbar starts moving. when click on the "stop" the song stops playing and the strip stops. But if while moving the strip I scroll list and it goes off the screen, it starts to move another strip that is on the same position in the visible area of the screen.
public class RecordAdapter extends BaseAdapter {
private MediaPlayer mediaPlayer;
private LayoutInflater inflater;
private ArrayList<RecordBean> recordBeans;
private final Handler handler = new Handler();
private Context ctx;
private int global_position;
...
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View view = convertView;
final ViewHolder holder;
if (convertView == null) {
view = inflater.inflate(R.layout.recorditem, parent, false);
holder = new ViewHolder();
holder.date = (TextView) view.findViewById(R.id.recordate);
holder.seekBar = (SeekBar) view.findViewById(R.id.seekBar);
holder.start = (Button) view.findViewById(R.id.btnStart);
holder.stop = (Button) view.findViewById(R.id.btnStop);
view.setTag(holder);
} else {
holder = (ViewHolder) view.getTag();
}
holder.date.setText(" " + recordBeans.get(position).getDate());
holder.start.setTag(position);
holder.stop.setTag(position);
holder.seekBar.setTag(position);
holder.seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(final SeekBar seekBar, final int i, boolean b) {
if (b && (Integer)seekBar.getTag()==global_position) {
mediaPlayer.seekTo(i);
}
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
holder.start.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
releaseMP();
try {
mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(recordBeans.get((Integer) v.getTag()).getFile());
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mediaPlayer) {
mediaPlayer.start();
global_position = position;
holder.start.setTextColor(Color.RED);
holder.seekBar.setMax(mediaPlayer.getDuration());
startPlayProgressUpdater(holder.seekBar,holder.start);
}
});
mediaPlayer.prepareAsync();
} catch (IOException e) {
e.printStackTrace();
}
if (mediaPlayer == null) {
return;
}
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mediaPlayer) {
Log.d("LOG_TAG", "onCompletion");
holder.start.setTextColor(Color.WHITE);
}
});
}
});
holder.stop.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mediaPlayer == null)
return;
if ((Integer) v.getTag() == global_position) {
mediaPlayer.stop();
}
}
});
return view;
}
private void releaseMP() {
if (mediaPlayer != null) {
try {
mediaPlayer.release();
mediaPlayer = null;
} catch (Exception e) {
e.printStackTrace();
}
}
}
private static class ViewHolder {
TextView date;
SeekBar seekBar;
Button start;
Button stop;
}
public void startPlayProgressUpdater(final SeekBar seek, final Button start) {
seek.setProgress(mediaPlayer.getCurrentPosition());
if (mediaPlayer.isPlaying()) {
Runnable notification = new Runnable() {
public void run() {
startPlayProgressUpdater(seek,start);
}
};
handler.postDelayed(notification, 1000);
} else {
mediaPlayer.pause();
seek.setProgress(0);
}
}
}
EDIT:
I added geter and seter in recordBean
public int getSeekPos() {
return SeekPos;
}
public void setSeekPos(int seekPos) {
SeekPos = seekPos;
}
and
holder.seekBar.setProgress(recordBeans.get(position).getSeekPos());
holder.date.setText(" " + recordBeans.get(position).getDate());
and
#Override
public void onProgressChanged(final SeekBar seekBar, final int i, boolean b) {
if (b && (Integer)seekBar.getTag()==global_position) {
// mediaPlayer.seekTo(i);
recordBeans.get(position).setSeekPos(i);
}
}
but I think it left something extra in my code
The list item is being recycled when it leaves the screen.
You could try to call this in getView:
holder.seekBar.clearFocus();
This is a tricky process, but you can do this in the following way, as I have seen that you have created a List of RecordBean class. So what you can do is you have to create a Getter Setter in RecordBean for storing the position of you SeekBar like:
public void setSeekPos(int pos) {
this.pos = pos;
}
public int getSeekPos() {
return pos;
}
In your adapter below the line
holder.date.setText(" " + recordBeans.get(position).getDate());
set the progress of seekBar like this: holder.seekBar.setProgress(recordBeans.get(position).getSeekPos());
and inside the onProgressChanged add the following line recordBeans.get(position).setSeekPos(i);
This will resolve your issue.
Please let me know if it's working or not.
Thanks
I have a Listview which displays videos in some rows so the user can watch the video via the listview using TextureView. So far the videos load and play correctly but they seem to show up in the wrong order at times while scrolling. I believe this is due to the adapter recycling views but I am not sure how to fix this.
here is my implementation
There is the getView which handles rendering the views and then there is an AsyncTask started by the getView to setup the MediaPlayer for each view.
#Override
public View getView(int position, View view, ViewGroup parent) {
final ViewHolder holder;
final VoucherItem vItem = items.get(position);
if (view == null) {
view = inflater.inflate(R.layout.voucher_row, parent, false);
holder = new ViewHolder();
holder.list_img = (ImageView) view.findViewById(R.id.list_img);
holder.vid_play = (ImageView) view.findViewById(R.id.vid_play);
holder.video = (TextureView) view.findViewById(R.id.texture_video);
view.setTag(holder);
} else {
holder = (ViewHolder) view.getTag();
}
if (!vItem.photo.equals(""))
Picasso.with(context).load(vItem.photo).fit().centerCrop()
.into(holder.list_img);
else
Picasso.with(context).load(R.drawable.default_spuare).fit()
.centerCrop().into(holder.list_img);
if (!vItem.photo.equals("")){
holder.vid_play.setVisibility(View.GONE);
holder.video.setVisibility(View.GONE);
holder.list_img.setVisibility(View.VISIBLE);
} else {
holder.video.setVisibility(View.VISIBLE);
holder.list_img.setVisibility(View.GONE);
holder.video.setSurfaceTextureListener(new SurfaceTextureListener() {
#Override
public void onSurfaceTextureUpdated(SurfaceTexture arg0) {
}
#Override
public void onSurfaceTextureSizeChanged(SurfaceTexture arg0, int arg1,
int arg2) {
}
#Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture arg0) {
return false;
}
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int arg1, int arg2) {
final MediaPlayer mediaPlayer = new MediaPlayer();
holder.vid_play.setTag(mediaPlayer);
new SetVideotask().execute(surface, vItem, mediaPlayer, holder.vid_play);
}
});
}
}
return view;
}
class SetVideotask extends AsyncTask<Object, Integer, String>{
#Override
protected String doInBackground(Object... o) {
// TODO Auto-generated method stub
final SurfaceTexture s = (SurfaceTexture) o[0];
final VoucherItem item = (VoucherItem) o[1];
final MediaPlayer mediaPlayer = (MediaPlayer) o[2];
final View v = (View) o[3];
mediaPlayer.setSurface(new Surface(s));
try {
mediaPlayer.setDataSource(item.video);
mediaPlayer.prepare();
mediaPlayer.start();
//I do this so there is a frame in the video to act as a preview
Thread.sleep(100);
mediaPlayer.pause();
mediaPlayer.setOnErrorListener(VoucherAdapter.this);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
static class ViewHolder {
ImageView list_img;
ImageView vid_play;
TextureView video;
}
#Override
public boolean onError(MediaPlayer arg0, int arg1, int arg2) {
return true;
}
This is because your AsyncTask instances created in onSurfaceTextureAvailable may not finish sequentially and when you are scrolling, the thread created for the new view may complete before the thread of the recycled view (so the old data is loaded).
I managed to solve this case by creating a single thread pool that I terminate while scrolling.
Also, this is the ultimate question for ListView loading.
I have a ListView with custom adapter with Image. I also have sound assigned to each item in ListView. I want when user for example click on 3rd item in ListView to change image of that item, and when user click on for example 15th item, to change item 3 image to old one, and change image of item 15 And so on. How can I do that?
This is my code:
Adapter:
#Override
public View getView(final int position, View convertView, ViewGroup parent){
View item=convertView;
HolderActivity holder=null;
if(item==null){
LayoutInflater inflater=(LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
item=inflater.inflate(R.layout.generator, parent,false);
holder=new HolderActivity(item);
item.setTag(holder);
}
else{
holder=(HolderActivity)item.getTag();
}
holder.transfer.setImageResource(transfer[position]);
holder.myImage.setImageResource(pictures[position]);
holder.ringName.setText(ringNames[position]);
holder.ringDesc.setText(descInfo[position]);
return item;
}
}
And then simple ItemClickListener in Main Activity
int[] songPos = { R.raw.position1, R.raw.position2, R.raw.position3,
R.raw.position4, R.raw.position4, R.raw.position5, R.raw.position6...etc etc
list.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View paramAnonymousView, int position, long id) {
CentralActivity.this.playSound(position);
}
});
private void playSound(int paramInt)
{
try
{
if ((CentralActivity.playing.booleanValue()) && (CentralActivity.position == paramInt))
{
Toast.makeText(CentralActivity.this, "It's Playing", Toast.LENGTH_SHORT).show();
}
else
{
CentralActivity.mp = MediaPlayer.create(CentralActivity.this, Integer.valueOf(this.songPos[paramInt]).intValue());
CentralActivity.mp.start();
CentralActivity.position = paramInt;
CentralActivity.playing = Boolean.valueOf(true);
CentralActivity.mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener()
{
public void onCompletion(MediaPlayer paramAnonymousMediaPlayer)
{
paramAnonymousMediaPlayer.release();
CentralActivity.playing = Boolean.valueOf(false);
}
});
}
}
catch (Exception localException) {}
}
Here are pieces for your code which should work:
Activity:
private ArrayAdapter mAdapter; // Make the mAdapter reachable by other methods
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
// If creating adapter from your activity, send it's context (this):
mAdapter = new ArrayAdapter(this,...);
...
}
private void playSound(int paramInt) {
try {
if ((CentralActivity.playing) && (CentralActivity.position == paramInt)) {
Toast.makeText(CentralActivity.this, "It's Playing", Toast.LENGTH_SHORT).show();
} else {
// Set activity variables
CentralActivity.position = paramInt;
CentralActivity.playing = true;
// Update ListView views
mAdapter.notifyDataSetChanged();
// Create MP and start playing
CentralActivity.mp = MediaPlayer.create(CentralActivity.this, Integer.valueOf(this.songPos[paramInt]).intValue());
CentralActivity.mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
public void onCompletion(MediaPlayer paramAnonymousMediaPlayer) {
paramAnonymousMediaPlayer.release();
CentralActivity.playing = false;
// Update ListView views
mAdapter.notifyDataSetChanged();
}
});
CentralActivity.mp.start();
}
} catch (Exception localException) {
localException.printStackTrace();
}
}
Adapter:
public class CustomAdapter extends ArrayAdapter {
// Considering CentralActivity is the name of your Activity's class
private CentralActivity mActivity;
// Custom adapter's constructor
public CustomAdapter(Context context, ...) {
mActivity = (CentralActivity) context;
...
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View item = convertView;
HolderActivity holder = null;
if (item == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
item = inflater.inflate(R.layout.generator, parent, false);
holder = new HolderActivity(item);
item.setTag(holder);
} else {
holder = (HolderActivity) item.getTag();
}
if (mActivity.playing && mActivity.position == position) {
holder.myImage.setImageResource(pauseImageResource);
} else {
holder.myImage.setImageResource(pictures[position]);
}
holder.transfer.setImageResource(transfer[position]);
holder.ringName.setText(ringNames[position]);
holder.ringDesc.setText(descInfo[position]);
return item;
}
...
}
Note that you will obviously need to replace ... and maybe CentralActivity too, to corresponding equivalents in your code.
The idea is to keep track of which index is playing.
Create setter in your adapter class:
public void setPlayingIndex(int index){
mPlayingIndex = index;
if(mPlayingIndex != ListView.INVALID_POSITION){
notifyDataSetChanged();
}
}
Make sure you call this method when you play the sound, like:
mListAdapter.setPlayingIndex(index);
In your getView() method, besides the ViewHolder pattern code have this:
if(mPlayingIndex == position){
//add the playing image
}else{
// load normal
holder.transfer.setImageResource(transfer[position]);
holder.myImage.setImageResource(pictures[position]);
holder.ringName.setText(ringNames[position]);
holder.ringDesc.setText(descInfo[position]);
}