Я разрабатываю приложение для чата, есть разные типы сообщений: простой текст, изображение, файл и т. д. Также есть только сообщение (другое, слева от экрана) и мое сообщение (справа от экрана).
Теперь у меня разные макеты для каждого типа сообщения:
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.
Пожалуйста, помогите!
@DKV, поэтому должно быть 2 типа просмотра: MESSAGE, MY_MESSAGE? И 2 ViewHolder с макетами только «облака сообщений». И я должен раздувать макет «тела сообщения» внутри этого ViewHolder, верно?
не 2, ты можешь иметь столько, сколько хочешь
вы можете иметь свой логин для другого типа в getItemViewType ()
В моем случае у меня также есть тот же тип параметров сообщения и обрабатывается с помощью case switch в onBindViewHolder () с отображением и скрытием видимости. да, это сложно, когда вы добавляете новый тип сообщения, вам нужно добавить еще один случай в onBindViewHolder для его выполнения
В моем случае у меня также есть варианты сообщений того же типа, и мне нужно различать сообщения отправителя и полученные сообщения. Я добавил разные макеты для отправителя и получателя при создании самого держателя представления на основе типа сообщения.
Каждое сообщение имеет разные параметры сообщения (текст, изображение, видео, файл, аудио и т. д.), И я обрабатывал регистр переключателя в onBindViewHolder () с отображением и скрытием видимости.
У меня есть три разных viewHolder вместе.
ВЫ: сообщения, отправленные вами (всегда должно отображаться прямо на экране) В вашем случае МОЕ СООБЩЕНИЕ
Другое: сообщения, отправленные другими пользователями (всегда должно отображаться слева на экране). В вашем случае СООБЩЕНИЕ
СРОК ВРЕМЕНИ: сообщения на шкале времени, например, пользователь изменил имя чата, удалил, так что пользователь и т. д.
Так вот,
@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);
}
}
Вот логика, которую я написал для обработки различных типов сообщений Индивидуальные (текстовое изображение и т. д. Для вас и других).
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, чтобы добавить его.
Надеюсь, это поможет вам выполнить вашу задачу.
Спасибо за ответ и примеры! Это один из вариантов, который я предполагал. График отличный, думаю, он тоже будет реализован. Но я думаю, что это немного тяжелое решение, потому что мы не должны забывать показывать / скрывать представления, и, возможно, это замедлится. Что, если раздуть любой требуемый макет внутри метода шоу? MESSAGE / MY_MESSAGE будет родительским, а макет конкретного типа сообщения будет дочерним
OFFTOP: почему вы используете Glide, а не Picasso? :)
Да согласен. Скрытие и отображение - это немного сложная часть, но надувание ASAIK также имеет тот же тип сложности. Не пробовал таким образом
За Glide против Пикассо! прочтите это medium.com/@multidots/glide-vs-picasso-930eed42b81d
Спасибо! А пока ваш ответ самый подходящий
Если вы попробуете использовать подход Inflate, опубликуйте свои ответы здесь, чтобы я проверил оба и изменил свою логику. Но на данный момент в моем случае он работает нормально, как и ожидалось!
Да, я попробую накачать и если все будет нормально, я разместил здесь
эй, вы пробовали надувать макет, если да, пришлите решение !!!
Надувать разные макеты по мере необходимости.