概要:今天想运用一下已学的知识试着实现一下微信的聊天界面。主要实现的功能只是聊天内容的发送和显示。
这其实是《第一行代码》中的一个实战样例,主要想记录一下心得体会。
First
定义一个消息类Msg.class。主要属性有,消息的内容,消息的类型(接受的还是发送的),并定义两个方法用于get内容与类型。
Second
布局主界面。
界面主要是对话列表与底下的输入框及输入按钮组成。先定义一个RecyclerView列表布局,当然,需要现在build.gradle中先添加依赖。1
2implementation 'com.android.support:recyclerview-v7:24.2.1'
//官方已不支持使用compile
然后就可以愉快的使用RecyclerView啦。
对话列表布局
布局完主界面就要对列表子项进行布局,即设置我们的对话框。新建一个message.xml,注意父布局宽度应为wrap_content。因为对话框接收与发送的方向不同,所以需要设置两个子布局,然后使用时再在代码中对其中一个进行隐藏。
接着是设置对话框的气泡图片。在网上搜到合适的对话框图片然后添加到res/drawable文件夹中。建议图片的尺寸最好小一点,这样最后效果好看一点。
这里还要插入一个知识点:
Nine-Patch图片的使用
以前制作.9图片,需要使用Android sdk/tools/draw9patch.bat,但AndroidStudio开始,就将此功能集成到了IDE中。只要右键png图片选择Create 9-Patch file即可创建。
.9图片有什么用呢,它能更方便于做出更好的图片效果。
打开.9.png,拖动图片边框黑点,左上边框用于定义图片可被拉长的部分,右下边框用于定义图片被添加内容时的位置,这样即使的我们布局时候更加方便。
Third
定义列表的配适器,建立recyclerview与数据间的联系
一直认为自定义列表配适器特别麻烦,但是写多了,思路也就清晰了。
构造方法
首先定义一个成员变量用于接收数据内容,一般是一个list。然后在构造方法中进行数据的赋值。
然后这个Adapter需要继承自RecyclerView.Adapter<Adapter类名.HolderView>
定义一个子类ViewHolder类(继承自RecyclerView.Holder)
这个类用于缓存数据内容,无需重复获取控件的实例,提高list的运行效率。
首先定义成员变量,都是需要缓存的数据或控件。接着是构造方法,需传入一个RecyclerView子项的最外层布局的view,直接传给ViewHolder的父级构造方法,然后开始对view中的控件进行获取和赋值。
加载布局,在代码中获取并将布局返回
1 |
|
这部分代码一般没有太多改动,其中R.layout.message是要加载布局的定义。
将数据添加到布局中,子项滚动进入屏幕时执行
在这里进行消息类型的判断,用setVisibility()对布局进行显示或隐藏。
####
最后是一个每次必须重写的方法,获取子项个数。
自此Adapter就已经准备完毕,逐个理解并多加实践便不会觉得太复杂。
Forth
到此一切准备就绪,可以开始编写MainActivity。
首先定义数据列表,msg配适器,获取EditText,Button,RecyclerView实例,定义一个LinearLayoutManager,指定RecyclerView的布局方式
然后将数据列表传入配适器,指定RecyclerView的配适器。
最后设置Button的点击事件,先获取输入框内容新建一个Msg对象并添加到列表,
使用adapter.notifyItemInserted(list.size() - 1),实现有新消息时刷新RecyclerView的显示
然后recyclerview.scrollToPosition(list.size() - 1),实现将RecyclerView定位到最后一行,使每次增加对话后不会回到顶部。
到这里就大功告成了。
如果愿意的话,可以先初始化一部分Msg数据用于一开始的显示。
源码
下面贴出源代码
MainActivity.java1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
ArrayList<Msg> msgList = new ArrayList<Msg>();
private TextView textView;
private RecyclerView msgRecycleView;
private MsgAdapter adapter;
private LinearLayoutManager manager;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initMsg();
msgRecycleView = (RecyclerView) findViewById(R.id.list);
manager = new LinearLayoutManager(this);
msgRecycleView.setLayoutManager(manager);
adapter = new MsgAdapter(msgList);
msgRecycleView.setAdapter(adapter);
Button send = (Button) findViewById(R.id.send);
textView = findViewById(R.id.text);
textView.setText("");
send.setOnClickListener(new View.OnClickListener(){
public void onClick(View v) {
String content = textView.getText().toString();
Msg msg = new Msg(content ,1);
msgList.add(msg);
msgRecycleView.setLayoutManager(manager);
adapter = new MsgAdapter(msgList);
msgRecycleView.scrollToPosition(msgList.size() -1);
msgRecycleView.setAdapter(adapter);
textView.setText("");
}
});
}
public void initMsg(){
Msg msg_1 = new Msg("Hello, How are you?", 0);
msgList.add(msg_1);
Msg msg_2 = new Msg("I am fine! Thank you!", 1);
msgList.add(msg_2);
Msg msg_3 = new Msg("Oh yeah! I am from Guangzhou, are you?", 0);
msgList.add(msg_3);
}
}
MsgAdapter.java1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import java.util.List;
public class MsgAdapter extends RecyclerView.Adapter<MsgAdapter.ViewHolder> {
private List<Msg> list;
static class ViewHolder extends RecyclerView.ViewHolder{
protected TextView leftContent;
protected TextView rightContent;
protected LinearLayout leftLayout;
protected LinearLayout rightLayout;
public ViewHolder(View v){
super(v);
leftLayout = (LinearLayout) v.findViewById(R.id.left_layout);
rightLayout = (LinearLayout) v.findViewById(R.id.right_layout);
leftContent = (TextView) v.findViewById(R.id.left);
rightContent = (TextView) v.findViewById(R.id.right);
}
}
public MsgAdapter(List<Msg> list){
this.list = list;
}
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.message, parent, false);
ViewHolder holder = new ViewHolder(view);
return holder;
}
public void onBindViewHolder(ViewHolder holder, int position) {
Msg message = list.get(position);
if(message.getType() == 0){
holder.leftContent.setText(message.getContent());
holder.leftLayout.setVisibility(View.VISIBLE);
holder.rightLayout.setVisibility(View.GONE);
}
else if(message.getType() == 1){
holder.rightContent.setText(message.getContent());
holder.rightLayout.setVisibility(View.VISIBLE);
holder.leftLayout.setVisibility(View.GONE);
}
}
public int getItemCount() {
return list.size();
}
}
Msg.java1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20package com.example.minions.uibestpractice;
public class Msg {
private final static int type_recrived = 0;
private final static int type_send = 1;
private String content;
private int type;
public Msg(String content, int type){
this.content = content;
this.type = type;
}
public int getType() {
return type;
}
public String getContent() {
return content;
}
}
activity_main.xml1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32<?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:orientation="vertical">
<android.support.v7.widget.RecyclerView
android:id="@+id/list"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="0dp">
</android.support.v7.widget.RecyclerView>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="@+id/text"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent" />
<Button
android:id="@+id/send"
android:background="#9090"
android:textColor="#fff"
android:layout_margin="3dp"
android:text="Send"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
message.xml1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36<?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_gravity="left"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/message_left">
<TextView
android:textSize="25dp"
android:id="@+id/left"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
android:id="@+id/right_layout"
android:layout_gravity="right"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/message_right">
<TextView
android:id="@+id/right"
android:textSize="25dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>