概要:今天想运用一下已学的知识试着实现一下微信的聊天界面。主要实现的功能只是聊天内容的发送和显示。 这其实是《第一行代码》中的一个实战样例,主要想记录一下心得体会。
First 定义一个消息类Msg.class。主要属性有,消息的内容,消息的类型(接受的还是发送的),并定义两个方法用于get内容与类型。
Second 布局主界面。 界面主要是对话列表与底下的输入框及输入按钮组成。先定义一个RecyclerView列表布局,当然,需要现在build.gradle中先添加依赖。
1 2 implementation 'com.android.support:recyclerview-v7:24.2.1'
然后就可以愉快的使用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 2 3 4 5 6 @Override 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; }
这部分代码一般没有太多改动,其中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.java
1 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; @Override 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(){ @Override 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.java
1 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 import 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; } @Override 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; } @Override 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); } } @Override public int getItemCount () { return list.size(); } }
Msg.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 package 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.xml
1 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.xml
1 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>
v1.5.2