0

I have a nested recycler view on which child item click I want the whole child recycler view to set visibility GONE.

I have tried some way to do it. But keeps on loosing the recycler view state and wrong data show's up. Help, please.

Here is ParentAdapter.java code

public class MessageListAdapter extends RecyclerView.Adapter {
    private Context mContext;
    private static final int VIEW_TYPE_MESSAGE_SENT = 1;
    private static final int VIEW_TYPE_MESSAGE_RECEIVED = 2;
    private List<Payload> chatMessageList;
    private RecyclerView.RecycledViewPool recycledViewPool;
    private OnItemClickListener onItemClickListener;

    MessageListAdapter(Context context, List<Payload> chatMessageList, OnItemClickListener onItemClickListener) {
        this.mContext = context;
        this.chatMessageList = chatMessageList;
        this.onItemClickListener = onItemClickListener;
        recycledViewPool = new RecyclerView.RecycledViewPool();
    }

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

    // Determines the appropriate ViewType according to the sender of the message.
    @Override
    public int getItemViewType(int position) {
        Payload message = chatMessageList.get(position);
        if (TextUtils.equals(message.getUserType(), "USER")) {
            // If the current user is the sender of the message
            return VIEW_TYPE_MESSAGE_SENT;
        } else {
            // If some other user sent the message
            return VIEW_TYPE_MESSAGE_RECEIVED;
        }
    }


    // Inflates the appropriate layout according to the ViewType.
    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view;
        if (viewType == VIEW_TYPE_MESSAGE_SENT) {
            view = LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.item_user_msg, parent, false);
            return new SentMessageHolder(view);
        } else {
            view = LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.item_bot_msg, parent, false);
            return new ReceivedMessageHolder(view);
        }
    }


    // Passes the message object to a ViewHolder so that the contents can be bound to UI.
    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        Payload chatMessage = chatMessageList.get(position);
        switch (holder.getItemViewType()) {
            case VIEW_TYPE_MESSAGE_SENT:
                ((SentMessageHolder) holder).bind(chatMessage.getMessage(), getFormattedTime());
                break;
            case VIEW_TYPE_MESSAGE_RECEIVED:
                ((ReceivedMessageHolder) holder).bind(chatMessage.getMessage(), getFormattedTime());
                ((ReceivedMessageHolder) holder).bindRv(chatMessage, mContext, recycledViewPool, onItemClickListener);
                break;
        }
    }

    private static class SentMessageHolder extends RecyclerView.ViewHolder {
        TextView txtViewChatMsgUser;
        TextView txtViewDateTimeUser;

        SentMessageHolder(View itemView) {
            super(itemView);
            txtViewChatMsgUser = itemView.findViewById(R.id.txtViewChatMsgUser);
            txtViewDateTimeUser = itemView.findViewById(R.id.txtViewDateTimeUser);
        }

        void bind(String message, String time) {
            txtViewChatMsgUser.setText(message);
            txtViewDateTimeUser.setText(time);
        }
    }

    private class ReceivedMessageHolder extends RecyclerView.ViewHolder {
        TextView txtViewChatMsgBot;
        RecyclerView rvDeepLink;
        TextView txtViewDateTimeBot;

        ReceivedMessageHolder(View itemView) {
            super(itemView);
            txtViewChatMsgBot = itemView.findViewById(R.id.txtViewChatMsgBot);
            rvDeepLink = itemView.findViewById(R.id.itemRvDeepLink);
            txtViewDateTimeBot = itemView.findViewById(R.id.txtViewDateTimeBot);
        }

        void bind(String message, String time) {
            txtViewChatMsgBot.setText(message);
            txtViewDateTimeBot.setText(time);
        }

        void bindRv(Payload chatMessage, Context context, RecyclerView.RecycledViewPool recycledViewPool, OnItemClickListener onItemClickListener) {
            if (chatMessage.getData() != null && !chatMessage.isOptionSelected()) {
                DeepLinkAdapter deepLinkAdapter = new DeepLinkAdapter(context, chatMessage.getData(), onItemClickListener, getAdapterPosition());
                LinearLayoutManager linearLayoutManager = new LinearLayoutManager(context);
                linearLayoutManager.setOrientation(RecyclerView.VERTICAL);
                rvDeepLink.setLayoutManager(linearLayoutManager);
                rvDeepLink.setAdapter(deepLinkAdapter);
                rvDeepLink.setRecycledViewPool(recycledViewPool);
                deepLinkAdapter.notifyDataSetChanged();
            } else {
                rvDeepLink.setVisibility(View.GONE);
            }
        }
    }

    private String getFormattedTime() {
        SimpleDateFormat dateFormat = new SimpleDateFormat("hh.mm aa", Locale.ENGLISH);
        return dateFormat.format(new Date());
    }


    public void clearData() {
        chatMessageList.clear();
        notifyDataSetChanged();
    }

    public void onSelected(int position) {
        chatMessageList.get(position).setOptionSelected(true);
        notifyItemChanged(position);
    }
}

Here is my ChildAdapter.java code:

public class DeepLinkAdapter extends RecyclerView.Adapter<DeepLinkAdapter.DeepLinkViewHolder> {

    private List<DataItem> dataItemList;
    private Context context;
    private OnItemClickListener onItemClickListener;
    private int parentPos;

    DeepLinkAdapter(Context context, List<DataItem> dataItemList, OnItemClickListener onItemClickListener, int parentPos) {
        this.context = context;
        this.dataItemList = dataItemList;
        this.onItemClickListener = onItemClickListener;
        this.parentPos = parentPos;
    }

    @NonNull
    @Override
    public DeepLinkViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        return new DeepLinkViewHolder(LayoutInflater.from(context).inflate(R.layout.inner_bot_msg, parent, false), onItemClickListener, parentPos);
    }

    @Override
    public void onBindViewHolder(@NonNull final DeepLinkViewHolder holder, final int position) {
        DataItem dataItem = dataItemList.get(position);
        if (TextUtils.isEmpty(dataItem.getDeeplink())) {
            holder.deepLinkText.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
        } else {
            holder.deepLinkText.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_right_arrow, 0);
        }
        if (!TextUtils.isEmpty(dataItem.getText())) {
            holder.deepLinkText.setVisibility(View.VISIBLE);
            holder.deepLinkText.setText(dataItem.getText());
        } else {
            holder.deepLinkText.setVisibility(View.GONE);
        }
    }

    @Override
    public int getItemCount() {
        if (dataItemList != null) {
            return dataItemList.size();
        } else {
            return 0;
        }
    }


    class DeepLinkViewHolder extends RecyclerView.ViewHolder {
        private TextView deepLinkText;

        DeepLinkViewHolder(View itemView, OnItemClickListener onItemClickListener, int parentPos) {
            super(itemView);
            deepLinkText = itemView.findViewById(R.id.innerDeepLinkMsgText);
            if (onItemClickListener != null) {
                deepLinkText.setOnClickListener(v -> {
                    onItemClickListener.onItemClick(getAdapterPosition(), parentPos);
                });
            }
        }
    }
}

Here is my Click Listener Code in the Activity:

@Override
    public void onItemClick(int childPos, int parentPos) {
        if (TextUtils.isEmpty(chatMessageList.get(parentPos).getData().get(childPos).getDeeplink())) {
            String message = chatMessageList.get(parentPos).getData().get(childPos).getText();
            if (!viewModel.sendMessage(message)) {
                setMessage(getString(R.string.error_something_went_wrong), ChatBotManager.UserType.BOT.toString());
            } else {
                messageListAdapter.onSelected(parentPos);
                setMessage(message, ChatBotManager.UserType.USER.toString());
            }
        } else {
            if (TextUtils.equals(chatMessageList.get(parentPos).getData().get(childPos).getDeeplink(), "restart")) {
                if (messageListAdapter != null) {
                    messageListAdapter.clearData();
                    viewModel.sendMessage("start");
                }
            } else {
                String uri = chatMessageList.get(parentPos).getData().get(childPos).getDeeplink();
                Intent newIntent = new Intent(ApplicationClass.getContext(), TalkLinkingActivity.class);
                newIntent.setData(Uri.parse(uri));
                newIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                startActivity(newIntent);
                finish();
            }
        }
    }

Please help what I am missing here, My goal is to have a click listener from the child adapter on Activity, and also after the click on the item, I want to remove the whole recycler view. Just like a chatbot in Swiggy.

Shubham Agrawal
  • 1,252
  • 12
  • 29
  • What do you mean "remove the whole recycler view"? Is your goal to click an item in the nested recyclerview and remove the parent item? Is your goal to click an item in the nested recyclerview and remove the nested item? – Hasan Bou Taam May 07 '20 at 15:37
  • @HasanBouTaam My goal is to click an item in the nested recyclerview and hide the whole list item, means whole child recycler view all the item in child recycler. – Shubham Agrawal May 07 '20 at 15:42
  • You mean removing the whole list item completely after clicking a nested item? – Hasan Bou Taam May 07 '20 at 15:51
  • @HasanBouTaam Yes, removing the whole list item. – Shubham Agrawal May 07 '20 at 18:11

1 Answers1

0

Have a method in DeepLinkAdapter that clears the whole list:

public class DeepLinkAdapter extends RecyclerView.Adapter<DeepLinkAdapter.DeepLinkViewHolder> {

.......

public void clearTheWholeList(){
dataItemList.clear();
notifyDataSetChanged();
}

}

Have a method in your MessageListAdapter that removes an item completely:

public class MessageListAdapter extends RecyclerView.Adapter {
......
......
private int positionToClear = -1;



public void removeItem(int position){

positionToClear = position;
notifyDataSetChanged();


}

//in onBindViewHolder

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
............
............
//pass the positionToClear here
((ReceivedMessageHolder) holder).bindRv(chatMessage, mContext, recycledViewPool, onItemClickListener , positionToClear);

}



.......

}

In ReceivedMessageHolder

private class ReceivedMessageHolder extends RecyclerView.ViewHolder {


//here add new param for removed position
void bindRv(Payload chatMessage, Context context, RecyclerView.RecycledViewPool recycledViewPool, OnItemClickListener onItemClickListener, int positionToClear) {

 if (chatMessage.getData() != null && !chatMessage.isOptionSelected()) {
 DeepLinkAdapter deepLinkAdapter = new DeepLinkAdapter(context, chatMessage.getData(), onItemClickListener, getAdapterPosition());

//do a check here
if(getAdapterPosition() == positionToClear){
deepLinkAdapter.clearTheWholeList();
}

.......
.......
.......

} else {
rvDeepLink.setVisibility(View.GONE);
}
}


}

Assuming the onItemClick interface is working:

@Override
public void onItemClick(int childPos, int parentPos) {

...........
...........

//somewhere where you want the item to be removed

messageListAdapter.removeItem(parentPos);

............
............

}
Hasan Bou Taam
  • 4,017
  • 2
  • 12
  • 22
  • But that will remove the whole list including the parent list values also, I just want to all the child item on click of any child item. – Shubham Agrawal May 07 '20 at 18:13
  • Look I edited the whole answer, check again the whole answer step by step. – Hasan Bou Taam May 07 '20 at 18:31
  • While scrolling from bottom-top-bottom, I am losing the last item's child data, I mean the nested recycler view data is not showing when scrolling. Can you help me here? – Shubham Agrawal May 08 '20 at 08:46