首先看一下效果图:
首先使用RecyclerView需要添加依赖
compile 'com.android.support:recyclerview-v7:26.0.+'
布局很简单,在上面是一个RecyclerView。下面是一个水平的LinearLarout其中有两个控件,分别是EditText、Button。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="0dip"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dip"
android:orientation="horizontal">
<EditText
android:id="@+id/edt_msg"
android:layout_weight="1"
android:layout_width="0dip"
android:layout_height="wrap_content" />
<Button
android:id="@+id/btn_send"
android:padding="3dip"
android:layout_width="100dip"
android:layout_height="50dip"
android:text="发送"/>
</LinearLayout>
</LinearLayout>
关键布局是RecyclerView中每一个Item的布局,如下
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:padding="5dip"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!--用来显示接受到的信息-->
<LinearLayout
android:id="@+id/rev_layout"
android:orientation="horizontal"
android:gravity="left"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/rev_tv"
android:background="@drawable/left_msg"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<!--用来显示发送出去信息-->
<LinearLayout
android:id="@+id/send_layout"
android:orientation="horizontal"
android:gravity="right"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/send_tv"
android:background="@drawable/right_msg"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
可以看到分别用两个TextView显示发送和接收的消息,接受消息的TextView靠左显示android:gravity="left",发送消息的TextView靠右显示android:gravity="right"。注意两个TextView的背景图片是.9图,因为要保证随着消息内容的增多,背景图可以很自然的拉伸,保证不变型。
我们应该用一个实体类来表示消息如下:
public class MsgEntity {
//分别代表发送和接受消息的类型
public static final int SEND_MSG=1;
public static final int RCV_MSG=2;
//消息内容
private String content;
//消息类型
private int type;
public MsgEntity(int type, String content) {
this.type = type;
this.content = content;
}
public String getContent() {
return content;
}
public int getType() {
return type;
}
}
对于RecyclerView需要一个适配器,代码很简单。
public class MsgAdapter extends RecyclerView.Adapter<MsgAdapter.ViewHolder> {
private List<MsgEntity> mMsg;//消息的实体类集合
private Context mContext;
public MsgAdapter(Context context,List<MsgEntity> msg){
this.mMsg=msg;
this.mContext=context;
}
@Override
public MsgAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view= LayoutInflater.from(mContext).inflate(R.layout.msg_item,parent,false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(MsgAdapter.ViewHolder holder, int position) {
MsgEntity msg=mMsg.get(position);
if (msg.getType()==MsgEntity.RCV_MSG){
//接受消息:让发送消息有关的控件隐藏
holder.send_layout.setVisibility(View.GONE);
holder.rev_layout.setVisibility(View.VISIBLE);
holder.rev_tv.setText(msg.getContent());
}
else if (msg.getType()==MsgEntity.SEND_MSG){
//发送消息:让接收消息有关的控件隐藏
holder.rev_layout.setVisibility(View.GONE);
holder.send_layout.setVisibility(View.VISIBLE);
holder.send_tv.setText(msg.getContent());
}
}
@Override
public int getItemCount() {
return mMsg.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder{
LinearLayout rev_layout;
LinearLayout send_layout;
TextView rev_tv;
TextView send_tv;
public ViewHolder(View itemView) {
super(itemView);
rev_layout=itemView.findViewById(R.id.rev_layout);
send_layout=itemView.findViewById(R.id.send_layout);
rev_tv=itemView.findViewById(R.id.rev_tv);
send_tv=itemView.findViewById(R.id.send_tv);
}
}
}
可以看到关键的思想是在我们调用onBindViewHolder()方法绑定数据时,先取出消息,然后根据消息的类型来判断是接受到的消息还是发送出去的。如果是接收到的消息就显示左边的LinearLayout给左边TextView设置数据并隐藏右边的用来显示发送消息的那部分控件。发送时同理。
MainActivity.java
public class MainActivity extends AppCompatActivity{
private RecyclerView recyclerView;
private EditText edt_msg;
private Button btn_send;
private List<MsgEntity> list;//存放消息实体的集合
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();//初始化控件
initMsg();//模拟消息
final MsgAdapter msgAdapter=new MsgAdapter(this,list);
LinearLayoutManager layoutManager=new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(msgAdapter);
btn_send.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String send_content=edt_msg.getText().toString().trim();
if (!TextUtils.isEmpty(send_content)){
MsgEntity send_msg=new MsgEntity(MsgEntity.SEND_MSG,send_content);
list.add(send_msg);
//刷新RecyclerView显示
msgAdapter.notifyItemInserted(list.size()-1);
//模拟接受消息
MsgEntity rcv_msg=new MsgEntity(MsgEntity.RCV_MSG,"我也感觉"+send_content);
list.add(rcv_msg);
msgAdapter.notifyItemInserted(list.size()-1);
//将RecyclerView将显示的数据定位到最后一行
recyclerView.scrollToPosition(list.size()-1);
edt_msg.setText("");//清空消息输入框
}
}
});
}
private void initMsg() {
list=new ArrayList<MsgEntity>();
MsgEntity msg1=new MsgEntity(MsgEntity.RCV_MSG,"你好啊!我是张");
MsgEntity msg2=new MsgEntity(MsgEntity.SEND_MSG,"你也好啊!我是李");
list.add(msg1);
list.add(msg2);
}
//初始化控件
private void initView() {
recyclerView=(RecyclerView)findViewById(R.id.recyclerView);
edt_msg=(EditText)findViewById(R.id.edt_msg);
btn_send=(Button)findViewById(R.id.btn_send);
}
}