Kamran Kamran - 4 months ago 17
Android Question

trying to change background of imageButton in List item

Objective

I want to play sound on click of List item with ImageButton (initially hidden, visible on click) showing play pause (2 images) resource.
ImageButton is only to show state of sound to user.

Problem

When I scroll the List, imageButton is again GONE.

Code

BaseAdapter

private class ListAdapter extends BaseAdapter {
private Context mContext;
private LayoutInflater mInflater;
ViewHolder holder;

ListAdapter(Context context) {
mContext = context;
this.mInflater = LayoutInflater.from(mContext);

}

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

@Override
public Object getItem(int position) {
return indexTitles.get(position);
}

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

@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
holder = new ViewHolder();
convertView = mInflater.inflate(R.layout.dua_row, null);
holder.mainBg = (RelativeLayout) convertView.findViewById(R.id.duaBG);
holder.title_text = (TextView) convertView.findViewById(R.id.title_text);
holder.buttonPlayPause = (ImageButton) convertView.findViewById(R.id.imageButton);
holder.buttonPlayPause.setFocusable(false);
holder.buttonPlayPause.setFocusableInTouchMode(false);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
String leftRemoved = indexTitles.get(position).trim();
holder.title_text.setText(leftRemoved);
// /player selection
if (playPos == position) {
holder.buttonPlayPause.setBackgroundResource(R.drawable.buttonpause);
holder.mainBg.setBackgroundColor(Color.parseColor("#000000"));
holder.title_text.setTextColor(Color.parseColor("#D59D52"));
} else {
holder.buttonPlayPause.setVisibility(View.GONE);
holder.title_text.setTextColor(Color.parseColor("#000000"));
holder.mainBg.setBackgroundColor(Color.parseColor("#D59D52"));
}
return convertView;
}


List Row

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/activity_horizontal_margin"
android:id="@+id/duaBG"
android:background="#D59D52">

<TextView
android:layout_width="match_parent"
android:layout_height="32dp"
android:text=""
android:textSize="18dp"
android:id="@+id/title_text"
android:ellipsize="end"
android:maxLines="1"

android:layout_alignParentTop="true"
android:layout_marginLeft="@dimen/activity_horizontal_margin"
android:layout_marginTop="@dimen/activity_horizontal_margin"
android:layout_marginBottom="@dimen/activity_horizontal_margin"
android:layout_toLeftOf="@+id/imageButton"
android:layout_toStartOf="@+id/imageButton" />

<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/imageButton"
android:focusable="false"
android:visibility="gone"
android:background="@drawable/buttonpause"
android:layout_centerVertical="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true" />

<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="5dp"
android:background="#000000"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"></LinearLayout>



OnItemClickListener

// indexTitles is ArrayList<String>
indexTitles = getIndexTitles();
final ListAdapter adapter = new ListAdapter(this);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new OnItemClickListener() {


@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
final View v = view.findViewById(R.id.imageButton);
v.setVisibility(View.VISIBLE);

if (mediaPlayer.isPlaying() && playPos == position) {
// pause mediaplayer
mediaPlayer.pause();
MEDIA_PAUSED = true;
v.setBackgroundResource(R.drawable.buttonplay);

} else if (MEDIA_PAUSED && !mediaPlayer.isPlaying() && playPos == position) {
MEDIA_PAUSED = false;
mediaPlayer.start();
v.setBackgroundResource(R.drawable.buttonpause);
} else if (!mediaPlayer.isPlaying() || mediaPlayer.isPlaying() && playPos != position) {
// release and start from this position
mediaPlayer.reset();
v.setVisibility(View.VISIBLE);
v.setBackgroundResource(R.drawable.buttonpause);
String s = String.format("%03d", position + 2);
String Path = SDCARD_PATH + "/DoaData/DD_" + s + ".mp3";
playPos = position;
adapter.notifyDataSetChanged();
File file = new File(Path);
Uri uri = Uri.fromFile(file);
try {
mediaPlayer.setDataSource(context, uri);
mediaPlayer.prepare();
mediaPlayer.start();
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
v.setBackgroundResource(R.drawable.buttonplay);
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
}
});


What Needed
I want to imageButton to keep its state about being played or paused.

Thanks

Answer

Simply set the visibility inside the IF statement like this:

               if (playPos == position) {           
                     holder.buttonPlayPause.setVisibility(View.VISIBLE);
                     // further implementation
                } else {
                    holder.buttonPlayPause.setVisibility(View.GONE);
                    // further implementation
                }

The problem occured, because the list adapter recycles the old views. When one view is not visible and the list is creating the new view using an old one, you have to set every different property again, else all properties from the previous view object are recycled/reused.

Comments