Как организовать RecyclerView on Chat App с различными типами сообщений? - PullRequest
0 голосов
/ 18 декабря 2018

Я разрабатываю приложение чата, есть другой тип сообщения: простой текст, изображение, файл и т. Д. Также есть только сообщение (другое, слева на экране) и мое сообщение (справа на экране).

Теперь у меня есть разные макеты для каждого типа сообщений:

  • 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

Также можно отправлять и пересылать сообщения, которые имеют более сложные макеты.И если я хочу добавить новый тип сообщения, это будет катастрофа.

Так как организовать это лучше?Может быть, все должно быть в одном макете и 2 типа: MESSAGE, MY_MESSAGE - и показывать / скрывать части макета.Или снова введите 2 типа (MESSAGE, MY_MESSAGE) и накачайте требуемый суб-макет во ViewHolder.

Пожалуйста, помогите!

1 Ответ

0 голосов
/ 18 декабря 2018

В моем случае у меня также есть варианты сообщений того же типа, и я должен различать их в зависимости от сообщений отправителя и полученных сообщений.Я добавил разные макеты для Отправителя и Получателя при создании самого держателя вида в зависимости от типа сообщения

. Каждое сообщение имеет разные параметры сообщения (Текст, Изображение, Видео, Файл, Аудио и т. Д.), И я обработал егопереключить регистр в onBindViewHolder () с видимостью показать и скрыть.

У меня есть три разных виджета.

ВЫ: Сообщения, отправленные вами (оно должно отображаться всегда прямо на экране). В вашем случае MY_MESSAGE

Прочее: Сообщения, отправленные другими пользователями (должно отображаться всегда слева.на экране) В вашем случае СООБЩЕНИЕ

TIMELINE: сообщения временной шкалы, такие как пользователь, изменили имя чата, удалили его и т.д. пользователя

Так вот,

@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, Others и TimeLine). Каждый You и другие xml-макеты имеют представления для включения текста, изображения и 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);
        }
    }

Вот логика, которую я написал для обработки различных типов сообщений Individual (Text Image и т. Д. Для вас и других).

 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);
                    }

        }
    }

Удалены некоторые логики case, поскольку все они имеют разные типы и обрабатываются одинаково.У меня также есть немного логики для отправителя и получателя, которые также удалены в этом блоке.вы можете добавить в соответствии с вашими потребностями

да, это трудно, когда вы добавляете новый тип сообщения, вам нужно добавить еще один случай в onBindViewHolder, чтобы добавить его.

Надеюсь, это даст некоторые советы дочтобы выполнить свою задачу.

...