Search code examples
androidlistviewimagebuttononitemclick

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


Solution

  • 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.