如何在Chat App上使用不同类型的消息来组织RecyclerView?

时间:2018-12-18 04:02:25

标签: android android-layout android-recyclerview chat recycler-adapter

我开发的聊天应用程序,有不同类型的消息:简单的文本,图像,文件等。 也只有消息(其他在屏幕左侧)和我的消息(在屏幕右侧)。

现在每种消息的布局都不同:

  • item_message_simple

  • item_my_message_simple

  • item_message_image

  • item_my_message_image

  • item_message_file

  • item_my_message_file

所有这些类型都在RecyclerView.Adapter中定义,并且getItemViewType()中有许多if-else条件

还可以答复和转发消息,消息的布局更为复杂。 如果我想添加新的消息类型,那将是灾难。

那么如何组织更好的方法呢? 也许应该全部采用一种布局,并选择两种类型:MESSAGE,MY_MESSAGE-和显示/隐藏布局的一部分。 或再次输入2种类型(MESSAGE,MY_MESSAGE),然后在ViewHolder中填充所需的子布局。

请帮忙!

1 个答案:

答案 0 :(得分:3)

就我而言,我也具有相同类型的消息选项,并且需要根据发件人消息和已接收消息进行区分。我根据消息类型自行创建了视图持有人,同时为发件人和接收人添加了不同的布局

每个味精具有不同的消息选项(文本,图像,视频,文件,音频等),我使用onBindViewHolder()中的开关大小写进行显示和隐藏。

我拥有三个不同的viewHolders。

YOU:您发送的邮件(应该始终在屏幕上显示) MY_MESSAGE

其他人:其他人发送的消息(该消息应始终显示在屏幕左侧),以您的情况消息

时间轴:时间轴消息,例如用户更改了聊天名称,已删除,因此用户等

所以在这里

@Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        MyViewHolder viewHolder = null;
        LayoutInflater inflater = LayoutInflater.from(parent.getContext());

        switch (viewType) {
            case YOU:
                View v1 = inflater.inflate(R.layout.chat_right_layout, parent, false);
                viewHolder = new MyViewHolder(v1, true);
                break;
            case OTHERS:
                View v2 = inflater.inflate(R.layout.chat_left_layout, parent, false);
                viewHolder = new MyViewHolder(v2, false);
                break;
            case TIMELINE:
                View v3 = inflater.inflate(R.layout.chat_timeline_layout, parent, false);
                viewHolder = new MyViewHolder(v3, false);
                break;
        }
        return viewHolder;
    }

在这里,我总共拥有3个不同的xml文件(您,其他和时间线消息) 每个You布局和其他xml布局都具有分别包含Text,Image和PDF的视图。

@Override
    public void onBindViewHolder(final MyViewHolder holder, int position) {
        ChatModel model = mDataList.get(position);

        if (model.getMessageType() == 10) // timeline message {
            holder.mTvTimeLine.setText(DecodeUtil.decodeBase64(model.getMessageText())+" on "+date);
        }else{
            showTextAndMediaData(holder, model);
        }
    }

这是我编写的用于处理不同消息类型“个人”(您和他人的“文本图像”等)的逻辑。

 private void showTextAndMediaData(MyViewHolder myViewHolder, ChatModel model) {

        switch (model.getMessageType()) {
            case 1:   // Image Type
                myViewHolder.mTxtMsg.setVisibility(View.GONE);
                myViewHolder.chatImageView.setVisibility(View.VISIBLE);
                myViewHolder.videoLayout.setVisibility(View.GONE);
                myViewHolder.documentImageView.setVisibility(View.GONE);

                    Uri mInitialUri = Uri.parse(model.getMessageText());
                    try {
                        myViewHolder.chatImageView.setImageURI(mInitialUri);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                break;
            case 3:  // video type
                myViewHolder.mTxtMsg.setVisibility(View.GONE);
                myViewHolder.chatImageView.setVisibility(View.GONE);
                myViewHolder.videoLayout.setVisibility(View.VISIBLE);
                myViewHolder.documentImageView.setVisibility(View.GONE);

                    Glide.with(mContext).load(Headers.getUrlWithHeaders(mContext, model.getThumbnailURL()))
                            .placeholder(R.drawable.novideo)
                            .thumbnail(0.5f)
                            .crossFade()
                            .diskCacheStrategy(DiskCacheStrategy.ALL)
                            .into(myViewHolder.vedioImageView);
                } 
                break;
            case 4: 
            case 5:
            case 6:
            case 7:
            case 8:
            case 9:   // file type
                myViewHolder.mTxtMsg.setVisibility(View.GONE);
                myViewHolder.chatImageView.setVisibility(View.GONE);
                myViewHolder.videoLayout.setVisibility(View.GONE);
                myViewHolder.documentImageView.setVisibility(View.VISIBLE);

                switch (model.getMediaType()) {
                    case "doc":
                        myViewHolder.documentImageView.setImageDrawable(ContextCompat.getDrawable(mContext, R.drawable.img_word_document));
                        break;
                    case "pdf":
                        myViewHolder.documentImageView.setImageDrawable(ContextCompat.getDrawable(mContext, R.drawable.img_pdf));
                        break;
                    case "excel":
                        myViewHolder.documentImageView.setImageDrawable(ContextCompat.getDrawable(mContext, R.drawable.img_excel));
                        break;
                    case "ppt":
                        myViewHolder.documentImageView.setImageDrawable(ContextCompat.getDrawable(mContext, R.drawable.img_ppt));
                        break;
                    case "txt":
                        myViewHolder.documentImageView.setImageDrawable(ContextCompat.getDrawable(mContext, R.drawable.img_txt));
                        break;
                    case "csv":
                        myViewHolder.documentImageView.setImageDrawable(ContextCompat.getDrawable(mContext, R.drawable.img_csv));
                        break;
                    default:
                        myViewHolder.documentImageView.setImageDrawable(ContextCompat.getDrawable(mContext, R.drawable.img_otherdoc));
                }
                break;
            default:  // text type
                myViewHolder.mTxtMsg.setVisibility(View.VISIBLE);
                myViewHolder.chatImageView.setVisibility(View.GONE);
                myViewHolder.videoLayout.setVisibility(View.GONE);
                myViewHolder.documentImageView.setVisibility(View.GONE);

                    try {
                        myViewHolder.mTxtMsg.setText(text);
                    } catch (Exception e) {
                        e.printStackTrace();
                        myViewHolder.mTxtMsg.setText(text);
                    }

        }
    }

删除了一些案例逻辑,因为它们都是不同的类型并以相同的方式处理。我还为发送方和接收方提供了更多逻辑,这些逻辑也在此块中删除。您可以根据需要添加

是的,当您添加新的消息类型时,您需要在onBindViewHolder中再添加一个案例来添加它是很困难的。

希望它能帮助您完成任务。