今天抽空看《第一行代码》关于 "编写精美聊天界面"的示例,想改进例子使用 RecyclerView 结合 viewBinding ,但是发现布局全部靠左
效果图是下面这样子:
话不多说,先上代码:
接收和发送气泡的布局
layer_message_bubble_receive.xml
<?xml version="1.0" encoding="utf-8"?>
<shape android:shape="rectangle"
xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#ffffff"/>
<corners android:radius="10dp"/>
</shape>
layer_message_bubble_sent.xml
<?xml version="1.0" encoding="utf-8"?>
<shape android:shape="rectangle"
xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#11b6bb"/>
<corners android:radius="10dp"/>
</shape>
message_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="10dp">
<LinearLayout
android:id="@+id/llLeft"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:background="@drawable/layer_message_bubble_receive"
android:visibility="gone">
<TextView
android:id="@+id/tvLeft"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="10dp"
android:textColor="#252835" />
</LinearLayout>
<LinearLayout
android:id="@+id/llRight"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:background="@drawable/layer_message_bubble_sent"
android:visibility="gone">
<TextView
android:id="@+id/tvRight"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="10dp"
android:textColor="@color/white" />
</LinearLayout>
</LinearLayout>
聊天界面主布局
activity_dialog_box.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#f5f5f5"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvContent"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="@+id/etInput"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="请输入 ..." />
<Button
android:id="@+id/bSend"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="发送" />
</LinearLayout>
</LinearLayout>
Message类
/**
* @author Tomas
* 消息
*/
public class Message {
public static final int TYPE_RECEIVED = 0;
public static final int TYPE_SENT = 1;
public String content;
public int type;
public Message(String content, int type) {
this.content = content;
this.type = type;
}
}
聊天界面Activity
/**
* 对话框的 demo
*/
public class DialogBoxActivity extends AppCompatActivity {
private ActivityDialogBoxBinding binding;
private ArrayList<Message> messageList;
private MessageAdapter messageAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityDialogBoxBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
buildView();
}
private void buildView() {
initMessageList();
// 布局
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
binding.rvContent.setLayoutManager(layoutManager);
// 设置适配器
messageAdapter = new MessageAdapter(this, messageList);
binding.rvContent.setAdapter(messageAdapter);
// 发送
binding.bSend.setOnClickListener(v -> {
String content = binding.etInput.getText().toString();
if (!TextUtils.isEmpty(content)) {
// 更新数据
Message sentMessage = new Message(content, Message.TYPE_SENT);
messageAdapter.updateOne(sentMessage);
// 定位到最后一行
binding.rvContent.scrollToPosition(messageList.size() - 1);
// 清空输入框
binding.etInput.setText("");
}
});
}
// 初始化消息数据
private void initMessageList() {
messageList = new ArrayList<>();
messageList.add(new Message("各位10点半有时间吗,快速对一下昨晚临门一脚的问题。", Message.TYPE_RECEIVED));
messageList.add(new Message("有时间", Message.TYPE_SENT));
}
}
MessageAdapter
/**
* @author Tomas
*/
public class MessageAdapter extends RecyclerView.Adapter<MessageAdapter.VH> {
private final Context context;
private final ArrayList<Message> msgList;
public MessageAdapter(Context context, ArrayList<Message> msgList) {
this.context = context;
this.msgList = msgList;
}
public void updateOne(Message message) {
msgList.add(message);
notifyItemChanged(msgList.size() - 1);
}
@NonNull
@Override
public VH onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
// return new VH(MessageItemBinding.inflate(LayoutInflater.from(parent.getContext())));
return new VH(MessageItemBinding.inflate(LayoutInflater.from(context), parent, false));
}
@Override
public void onBindViewHolder(@NonNull VH holder, int position) {
Message message = msgList.get(position);
if (message.type == Message.TYPE_RECEIVED) {
holder.itemBinding.llLeft.setVisibility(View.VISIBLE);
holder.itemBinding.tvLeft.setText(message.content);
} else if (message.type == Message.TYPE_SENT) {
holder.itemBinding.llRight.setVisibility(View.VISIBLE);
holder.itemBinding.tvRight.setText(message.content);
}
}
@Override
public int getItemCount() {
return msgList.size();
}
static class VH extends RecyclerView.ViewHolder {
MessageItemBinding itemBinding;
public VH(MessageItemBinding itemBinding) {
super(itemBinding.getRoot());
this.itemBinding = itemBinding;
}
}
}
布局靠左的问题是由于onCreateViewHolder中使用
return new VH(MessageItemBinding.inflate(LayoutInflater.from(parent.getContext())));
而不是使用
return new VH(MessageItemBinding.inflate(LayoutInflater.from(context), parent, false));
导致的