今天抽空看《第一行代码》关于 "编写精美聊天界面"的示例,想改进例子使用 RecyclerView 结合 viewBinding ,但是发现布局全部靠左

效果图是下面这样子:
RecyclerView 和 viewBinding 结合使用和布局靠左的问题解决_java

话不多说,先上代码:
接收和发送气泡的布局
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));

导致的