dissect tech
dissect tech

Reputation: 35

Issue with recycler view contextual action mode

I have implemented a contextual action bar in my recycler view on long press of the row. Here I am showing a checkbox for each row when in action mode. And hiding based on a flag to check if it is not action mode. The problem is in action mode only one row is showing with the checkbox on long press, remaining rows are hiding it. I am not sure what is wrong with it. I am attaching my Recycler adapter class and the corresponding row XML here. Please take a look and let me know if you could find where the issue lies.

Thanks in advance!

As some body suggested to show code here instead of pointing to the java file. Here is the code

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.RecyclerViewHolder> {

    Context context;
    List<RssFeed> feeds;
    Database database;
    FirebaseData db;
    String uid;
    private static final String TAG = Constants.TAG + " : " + RecyclerViewAdapter.class.getSimpleName();

    public RecyclerViewAdapter(Context context, List<RssFeed> feeds) {
        this.context = context;
        this.feeds = feeds;
        database = new Database(context);
        db = new FirebaseData(context);
        uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
    }

    @Override
    public RecyclerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(context).inflate(R.layout.edit_rss_feed_row, parent, false);
        final RecyclerViewHolder holder = new RecyclerViewHolder(view, (Activity) context, RecyclerViewAdapter.this);

        return holder;
    }

    @Override
    public void onBindViewHolder(final RecyclerViewHolder holder, int position) {
        holder.title.setText(feeds.get(position).getRssFeedTitle());
        holder.address.setText(feeds.get(position).getRssFeedAddress());

        if (!holder.action_mode)
            holder.checkBox.setVisibility(View.GONE);
        else {
            holder.checkBox.setVisibility(View.VISIBLE);
            holder.checkBox.setChecked(false);
        }


        holder.row.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                AlertDialog.Builder dialog = new AlertDialog.Builder(context);
                dialog.setTitle(context.getString(R.string.rss_delete_alert_title));
                dialog.setMessage(context.getString(R.string.rss_delete_alert_msg));
                final int position = holder.getAdapterPosition();
                dialog.setNegativeButton(context.getString(R.string.no), null);
                dialog.setPositiveButton(context.getString(R.string.yes), new AlertDialog.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        RssFeed feed = feeds.get(position);
                        deleteFeed(feed);
                        feeds = new Database(context).getRssFeeds(SharedPrefUtil.getUtil(context, uid).getUserInfo());
                        notifyDataSetChanged();
                    }
                });
                dialog.show();

            }
        });

    }

    private void deleteFeed(RssFeed feed){
        database.deleteRssFeed(feed);
        db.deleteRssFeed(feed);
    }

    @Override
    public int getItemCount() {
        return feeds.size();
    }

    public void removeFeeds(List<RssFeed> list) {
        for (RssFeed feed : list)
            feeds.remove(feed);
        notifyDataSetChanged();
    }

    class RecyclerViewHolder extends RecyclerView.ViewHolder {

        TextView title;
        TextView address;
        RelativeLayout row;
        CheckBox checkBox;
        boolean action_mode = false;
        ActionMode actionMode;
        Activity activity;
        RecyclerViewAdapter recyclerViewAdapter;
        final ArrayList<RssFeed> removedList = new ArrayList<>();


        public RecyclerViewHolder(View item, final Activity activity, RecyclerViewAdapter rView) {
            super(item);

            this.activity = activity;
            recyclerViewAdapter = rView;
            row = item.findViewById(R.id.row);
            title = item.findViewById(R.id.rssEditFeedTitle);
            address = item.findViewById(R.id.rssEditFeedAddress);
            checkBox = item.findViewById(R.id.checkBox);

            row.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View v) {

                    actionMode = ((AppCompatActivity)activity).startSupportActionMode(new ContextualCallBack(RecyclerViewHolder.this));

                    return true;
                }
            });
            checkBox.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (((CheckBox) v).isChecked())
                        removedList.add(feeds.get(getAdapterPosition()));
                    else removedList.remove(feeds.get(getAdapterPosition()));
                }
            });
        }

    }

    class ContextualCallBack implements ActionMode.Callback {

        RecyclerViewHolder holder;

        ContextualCallBack(RecyclerViewHolder holder) {
            this.holder = holder;
        }

        @Override
        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
            mode.getMenuInflater().inflate(R.menu.edit_rss_feed_action_mode_menu, menu);
            holder.action_mode = true;
            holder.recyclerViewAdapter.notifyDataSetChanged();
            return true;
        }

        @Override
        public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
            mode.setTitle(R.string.app_name);
            return false;
        }

        @Override
        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
            int id = item.getItemId();
            if (id == R.id.delete) {
                holder.recyclerViewAdapter.removeFeeds(holder.removedList);
                for(RssFeed feed:holder.removedList)
                    holder.recyclerViewAdapter.deleteFeed(feed);
                holder.recyclerViewAdapter.notifyDataSetChanged();
            }
            return false;
        }

        @Override
        public void onDestroyActionMode(ActionMode mode) {
            holder.action_mode = false;
            holder.recyclerViewAdapter.notifyDataSetChanged();
        }
    }
}

And here is the XML for each row

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/row"
    android:descendantFocusability="blocksDescendants"
    tools:context="com.rss.feedster.rss_feedster.EditRssFeedFragment">


    <EditText
        android:id="@+id/rssEditFeedTitle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:inputType="textPersonName"
        android:text="Title RSS Feed"
        android:textAppearance="@android:style/TextAppearance.DeviceDefault.Medium"
        android:textStyle="bold" />

    <EditText
        android:id="@+id/rssEditFeedAddress"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/rssEditFeedTitle"
        android:layout_alignLeft="@id/rssEditFeedTitle"
        android:text="Description Text View"
        android:textAppearance="@android:style/TextAppearance.Small" />

    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_alignParentEnd="true"
        android:layout_marginRight="15dp"
        android:text="Tab to remove" />

    <CheckBox
        android:id="@+id/checkBox"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignEnd="@+id/textView2"
        android:layout_below="@+id/rssEditFeedTitle"
        android:visibility="visible"/>


</RelativeLayout>

More Info: One thing I forgot to include is that the recycler view is being used in a fragment in navigation drawer layout.

Upvotes: 0

Views: 1153

Answers (1)

dissect tech
dissect tech

Reputation: 35

Finally, I got what was the mistake here. I put the flag (action_mode) for checking if it was action mode or not, inside the holder object itself which meant that the flag was only available for a single holder object(row) at a time. When I moved it to the adapter object then everything worked like a charm.

Upvotes: 0

Related Questions