Android Java中如何设置RecyclerView聊天消息项左右对齐
解决方案
方案1:多布局类型实现(推荐)
这个方案性能更好,复用逻辑更清晰,实现步骤如下:
- 首先在Adapter内部定义两种布局类型常量:
private static final int VIEW_TYPE_SEND = 1; private static final int VIEW_TYPE_RECEIVE = 2;
- 重写Adapter的
getItemViewType方法,这个方法可以拿到对应位置的数据源,提前判断消息归属:
@Override public int getItemViewType(int position) { getMessage model = getItem(position); if (model.getUidSender().equals(fAuth.getCurrentUser().getUid())) { return VIEW_TYPE_SEND; } else { return VIEW_TYPE_RECEIVE; } }
- 提前准备两个布局文件:
R.layout.item_chat_send:自己发送的消息布局,默认右对齐,气泡用右侧样式R.layout.item_chat_receive:对方发送的消息布局,默认左对齐,气泡用左侧样式
两个布局里的控件id保持和原有R.layout.card_chat一致,不需要修改ViewHolder逻辑。
- 修改
onCreateViewHolder,根据viewType加载对应布局:
@NonNull @NotNull @Override public getASetMsg onCreateViewHolder(@NonNull @NotNull ViewGroup parent, int viewType) { View view; if (viewType == VIEW_TYPE_SEND) { view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_chat_send, parent, false); } else { view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_chat_receive, parent, false); } return new getASetMsg(view); }
这样就完成了不同身份消息加载不同布局的逻辑,不需要在onBindViewHolder里做额外的对齐处理。
方案2:单布局动态修改样式
如果不想写两个布局,可以直接在onBindViewHolder里判断身份后动态调整布局参数:
首先调整原有R.layout.card_chat的根布局,设置宽度为match_parent,内部消息容器(包含txtMsgText和dateATime的父布局)宽度为wrap_content,给消息容器设id,比如msg_container。
然后在ViewHolder里新增消息容器的引用:
public static class getASetMsg extends RecyclerView.ViewHolder { TextView txtMsgText, dateATime; LinearLayout msgContainer; // 按你实际用的布局类型修改,比如ConstraintLayout也可以 public getASetMsg(@NonNull View itemView) { super(itemView); txtMsgText = itemView.findViewById(R.id.txtMsgText); dateATime = itemView.findViewById(R.id.dateATime); msgContainer = itemView.findViewById(R.id.msg_container); } }
最后在onBindViewHolder里判断身份修改布局参数:
@Override protected void onBindViewHolder(@NonNull @NotNull getASetMsg holder, int position, @NonNull @NotNull getMessage model) { holder.txtMsgText.setText(model.getText()); holder.dateATime.setText(model.getDate()); LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) holder.msgContainer.getLayoutParams(); if(model.getUidSender().equals(fAuth.getCurrentUser().getUid())) { // 自己发的消息右对齐 params.gravity = Gravity.END; // 可额外调整边距、修改气泡背景 params.leftMargin = dp2px(holder.itemView.getContext(), 80); params.rightMargin = dp2px(holder.itemView.getContext(), 16); holder.msgContainer.setBackgroundResource(R.drawable.bg_chat_send); } else { // 对方发的消息左对齐 params.gravity = Gravity.START; params.leftMargin = dp2px(holder.itemView.getContext(), 16); params.rightMargin = dp2px(holder.itemView.getContext(), 80); holder.msgContainer.setBackgroundResource(R.drawable.bg_chat_receive); } holder.msgContainer.setLayoutParams(params); } // 附加dp转px的工具方法,避免不同设备密度适配问题 private int dp2px(Context context, float dpValue) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (dpValue * scale + 0.5f); }
内容的提问来源于stack exchange,提问作者Conta
相关产品推荐
相关产品推荐

