Andriod RecyclerView的应用 编写精美的聊天界面

完整项目代码
https://github.com/Phil-tom/Android-The-First-Line-of-Code/tree/main/Chapter3/UIBestPractice

在主界面中放置了RecyclerView用于显示聊天内容,EditText输入信息,Button用于发送信息。
activity_main.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="#d8e0e8"
    android:orientation="vertical">
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/msg_recycler_view"
        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/input_text"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:hint="Type something here"
            android:maxLines="2"
            />
        <Button
            android:id="@+id/send"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="send" />
    </LinearLayout>
</LinearLayout>

定义消息实体类Msg

public class Msg {

    public static final int TYPE_RECEIVED = 0;
    public static final int TYPE_SEND = 1;
    //表示消息内容
    private String content;
    //表示消息类型
    //其中type有两个值可选,TYPE_RECEIVED,TYPE_SEND
    private int type;

    public Msg(String content, int type) {
        this.content = content;
        this.type = type;
    }

    public String getContent() {
        return content;
    }

    public int getType() {
        return type;
    }
}

RecyclerView子项的布局,msg_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/left_layout"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="start"
        android:orientation="horizontal"
        android:background="@drawable/message_left">
        <TextView
            android:id="@+id/left_msg"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_margin="10dp"
            android:textColor="#fff"/>
    </LinearLayout>
    <LinearLayout
        android:id="@+id/right_layout"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="end"
        android:background="@drawable/message_right"
        android:orientation="horizontal">
        <TextView
            android:id="@+id/right_msg"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_margin="10dp"/>
    </LinearLayout>
</LinearLayout>

为了让收到的消息和发出的消息同放在同一个布局里,可以使用之前学过的可见属性。稍后在代码中,根据消息的类型来决定隐藏和显示哪种消息就可以了。

创建RecyclerView的适配器,新建类MsgAdapter,在onBindViewHolder()方法中增加了对消息类型的判断。

public class MsgAdapter extends RecyclerView.Adapter<MsgAdapter.ViewHolder> {

    private List<Msg> mMsgList;

    static class ViewHolder extends RecyclerView.ViewHolder{

        LinearLayout leftLayout;
        LinearLayout rightLayout;
        TextView leftMsg;
        TextView rightMsg;

        public ViewHolder(View itemView) {
            super(itemView);
            leftLayout = (LinearLayout)itemView.findViewById(R.id.left_layout);
            rightLayout = (LinearLayout)itemView.findViewById(R.id.right_layout);
            leftMsg = (TextView)itemView.findViewById(R.id.left_msg);
            rightMsg = (TextView)itemView.findViewById(R.id.right_msg);
        }

    }
    public MsgAdapter(List<Msg> mMsgList) {
        this.mMsgList = mMsgList;
    }

    //在该方法中将msg_item布局加载进来,然后创建一个ViewHolder实例,
    //并把加载出来的布局传入到构造函数中,最后将ViewHolder实例返回。
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.msg_item,parent,false);

        return new ViewHolder(view);
    }

    //该方法在每个子项滚动到屏幕内的时候执行
    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        Msg msg = mMsgList.get(position);
        if (msg.getType() == Msg.TYPE_RECEIVED){
            //如果是收到的消息,则显示左边的消息布局,将右边的消息布局隐藏
            holder.leftLayout.setVisibility(View.VISIBLE);
            holder.rightLayout.setVisibility(View.GONE);
            holder.leftMsg.setText(msg.getContent());
        }else if(msg.getType() == Msg.TYPE_SEND){
            //如果是发出的消息,则显示右边的消息布局,将左边的消息布局隐藏
            holder.rightLayout.setVisibility(View.VISIBLE);
            holder.leftLayout.setVisibility(View.GONE);
            holder.rightMsg.setText(msg.getContent());
        }
    }

    @Override
    public int getItemCount() {
        return mMsgList.size();
    }

}

最后是MainActivity.java,使用initMsgs()方法初始化了几条数据用于在RecyclerView中显示,如第一张图所示。点击SEND按钮获取EditText中的内容,如果内容不为空,则会创建一个新的Msg对象,并把它添加到msgList列表中去。之后调用了适配器的notifyItemInserted()方法,用于通知列表有新的数据插入,这样新增的一条消息才能在RecyclerView中显示。接着调用RecyclerView的scrollToPosition()方法将显示的数据定位到最后一行,以保证一定可以看到发出的最后一条消息。最后调用EditText的setText方法将输入的内容清空。

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    //初始化消息数据
    initMsgs();

    inputText = (EditText)findViewById(R.id.input_text);
    send = (Button)findViewById(R.id.send);
    msgRecyclerView = (RecyclerView)findViewById(R.id.msg_recycler_view);
    //LayoutManager用于执行RecyclerView的布局方式
    LinearLayoutManager layoutManager = new LinearLayoutManager(this);
    msgRecyclerView.setLayoutManager(layoutManager);
    msgAdapter = new MsgAdapter(msgList);
    msgRecyclerView.setAdapter(msgAdapter);

    send.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            String content = inputText.getText().toString();
            if(!"".equals(content)){
                Msg msg = new Msg(content, Msg.TYPE_SEND);
                msgList.add(msg);
                //当有新消息时,刷新RecyclerView中的显示
                msgAdapter.notifyItemInserted(msgList.size()-1);
                //将RecyclerView定位到最后一行
                msgRecyclerView.scrollToPosition(msgList.size()-1);
                //清空输入框中的内容
                inputText.setText("");
            }
        }
    });
}

结果图:
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值