03UI开发-RecyclerView及简单聊天界面

基本用法

  1. 想要使用这个控件,首先在项目的build.gradle中添加相应的依赖库才行
    打开app/build.gradle文件,在dependencies闭包中添加
dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:26.1.0'
    // 添加的是这一句
    compile 'com.android.support:recyclerview-v7:26.1.0'
    implementation 'com.android.support.constraint:constraint-layout:1.0.2'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.1'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
}

  1. 添加完成后点击一下Sync Now来进行同步,然后修改activity_main.xml中的代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recycler_view_1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</LinearLayout>

添加一个控件,宽度和高度都是占满整部布局空间的

  1. 接下来定义一个自定义布局fruit_item.xml,这个时候注意layout_width="wrap_content"的设置,让它自适应大就可以了
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <ImageView
        android:id="@+id/img"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />

    <TextView
        android:id="@+id/text"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="center_vertical"
        android:layout_marginLeft="20dp"
        />

</LinearLayout>

4.定义一个实体类,作为RecyclerView适配器的适配类型,建立Fruit


public class Fruit {
    private String name;
    private int imageId;

    public Fruit(String name,int imageId){
        this.imageId = imageId;
        this.name = name;
    }
    public String getName() {
        return name;
    }

    public int getImageId() {
        return imageId;
    }
}

  1. 为RecyclerView准备一个适配器,新建FruitAdapter类,让这个适配器继承RecyclerView.Adapter,并将泛型指定为FruitAdapter.ViewHolder,其中ViewHolder是我们在FruitAdapter中定义的一个内部类

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

    private List<Fruit> mFruitList;

    static class ViewHolder extends RecyclerView.ViewHolder{
        ImageView fruitImage;
        TextView fruitName;

        public ViewHolder(View view){
            super(view);
            fruitImage=(ImageView)view.findViewById(R.id.img);
            fruitName = (TextView)view.findViewById(R.id.text);
        }
    }

    public FruitAdapter(List<Fruit> fruitList){
        mFruitList = fruitList;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.fruit_item,parent,false);
        ViewHolder holder = new ViewHolder(view);
        return holder;
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        Fruit fruit = mFruitList.get(position);
        holder.fruitImage.setImageResource(fruit.getImageId());
        holder.fruitName.setText(fruit.getName());
    }

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


}


  • 首先定义了一个内部类,ViewHolder要继承自RecyclerView.ViewHolder,然后在这个里面的构造函数中传入了一个View参数,这个参数通常就是RecyclerView子项的最外层布局,那么就可以通过这个findViewById()的方法获取到布局中的ImageVIew和TextView的实例了
  • FruitAdapter中也有一个构造函数,这个函数用于将把要展示的数据源传递进来,并赋值给一个全局变量mFruitList,后面操作的就是这个数据源了
  • 由于FruitAdapter继承自RecyclerView.Adapter,那么就必须重写 onCreateViewHolder(),onBindViewHolder(),getItemCount()这三个方法,
  • onCreateViewHolder()方法用于创建一个ViewHolder实例,并把加载出来的布局传入到构造函数中,最后将ViewHolder的实例返回
  • onBindViewHolder()方法用与对RecyclerView子项的数据进行赋值,会在每个子项滚动到屏幕内的时候执行,通过position参数可以获得当前项的Fruit实例,然后再将数据设置到ViewHolder的ImageView和TextVIew中
  • getItemCount()用于告诉RecyclerVIew一共有多少个子项,直接返回数据源的长度
  1. 接下来就可以使用RecyclerView,修改MainActivity中的代码

public class MainActivity extends AppCompatActivity {

    private List<Fruit> fruitList = new ArrayList<>();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 用于初始化水果
        initFruits();
        RecyclerView recyclerView = (RecyclerView)findViewById(R.id.recycler_view_1);
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(layoutManager);
        FruitAdapter adapter = new FruitAdapter(fruitList);
        recyclerView.setAdapter(adapter);
    }


    private void initFruits(){
        for (int i= 0;i<2;i++){
            Fruit apple = new Fruit("Apple",R.drawable.apple_pic);
            fruitList.add(apple);
            Fruit banana = new Fruit("Banana",R.drawable.banana_pic);
            fruitList.add(banana);
            Fruit orange = new Fruit("orange",R.drawable.orange_pic);
            fruitList.add(orange);
            Fruit watermelon = new Fruit("watermelon",R.drawable.watermelon_pic);
            fruitList.add(watermelon);
            Fruit pear = new Fruit("pear",R.drawable.pear_pic);
            fruitList.add(pear);
            Fruit grape = new Fruit("grape",R.drawable.grape_pic);
            fruitList.add(grape);
            Fruit pineapple = new Fruit("pineapple",R.drawable.pineapple_pic);
            fruitList.add(pineapple);
            Fruit strawberry = new Fruit("strawberry",R.drawable.strawberry_pic);
            fruitList.add(strawberry);
            Fruit cherry = new Fruit("cherry",R.drawable.cherry_pic);
            fruitList.add(cherry);
            Fruit mango = new Fruit("mango",R.drawable.mango_pic);
            fruitList.add(mango);
        }
    }

}

  • 使用了同样的initFruits()方法,用于初始化水果的数据,接着onCreate()方法获取到RecyclerView的实例,
  • 创建一个LayoutManager用于指定RecycleView的布局方式,这里使用的是LinearLayoutManager是线性布局的意思,可以实现和ListView类似的效果,
  • 接下来创建一个FruitAdapter的实例,将水果的数据传入到FruitAdapter的构造函数中
  • 最后调用RecyclerView的setAdapter()方法来完成适配器的设置,这样RecyclerVIew和数据之间的关联就建立完成了


    2018-03-11_16-06-47.png

实现横向滚动和瀑布流布局

  1. 首先要对fruit_item布局进行修改,实现横向滚动,得把这里面的元素改成垂直排列的方式
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="100dp"
    android:layout_height="wrap_content">

    <ImageView
        android:id="@+id/img"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        />

    <TextView
        android:id="@+id/text"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="20dp"
        />

</LinearLayout>

  • android:orientation="vertical"该成了垂直方向排列,而且宽度色设置为100dp,这样不会因为每种水果名字的长度不一而导致RecycleView的各个子项长短不一
  • android:layout_gravity="center_horizontal" 都设置为水平居中
  1. 修改MainActivity中的代码
package com.example.md.recyclerview;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {


    private List<Fruit> fruitList = new ArrayList<>();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 用于初始化水果
        initFruits();
        RecyclerView recyclerView = (RecyclerView)findViewById(R.id.recycler_view_1);
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        // 多添加这一句话
        layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
        recyclerView.setLayoutManager(layoutManager);
        FruitAdapter adapter = new FruitAdapter(fruitList);
        recyclerView.setAdapter(adapter);
    }
        
    ..............

}


  • 相比之下,只多了一行代码,调用了layoutManager的setOrientation()方法来设置布局的排列方法,默认是纵向的,传入LinearLayoutManager.HORIZONTAL表示让布局横向排列
    Snipaste_2018-03-11_16-20-07.png
  1. 除了LinearLayoutManager之外,RecyclerView还提供了GridLayoutManagerStaggeredGridLayoutManager这样中内置的布局排列方式,GridLayoutManager是用于网络布局,StaggeredGridLayoutManager用于瀑布布局
    修改fruit_item.xml中的代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="5dp">

    <ImageView
        android:id="@+id/img"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        />

    <TextView
        android:id="@+id/text"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="left"
        android:layout_marginTop="20dp"
        />

</LinearLayout>

只有几处调整,把宽度有100dp改成match_parent,因为瀑布的宽度是根据布局的列数自动匹配的,不是一个固定的值,还用margin属性,让子项之间留点间距,文字的对齐方式改成了左对齐

  1. 修改MainActivity中的代码

public class MainActivity extends AppCompatActivity {


    private List<Fruit> fruitList = new ArrayList<>();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 用于初始化水果
        initFruits();
        RecyclerView recyclerView = (RecyclerView)findViewById(R.id.recycler_view_1);
//        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        // 多添加这一句话
//        layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);

//      主要就是这一行代码,瀑布
        StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(
                3, StaggeredGridLayoutManager.VERTICAL
        );

        // 网络
        //GridLayoutManager layoutManager = new GridLayoutManager(this,4);

        recyclerView.setLayoutManager(layoutManager);
        FruitAdapter adapter = new FruitAdapter(fruitList);
        recyclerView.setAdapter(adapter);
    }

    private void initFruits(){
        for (int i= 0;i<2;i++){
            Fruit apple = new Fruit(getRandomLengthName("Apple"),R.drawable.apple_pic);
            fruitList.add(apple);
            Fruit banana = new Fruit(getRandomLengthName("Banana"),R.drawable.banana_pic);
            fruitList.add(banana);
            Fruit orange = new Fruit(getRandomLengthName("orange"),R.drawable.orange_pic);
            fruitList.add(orange);
            Fruit watermelon = new Fruit(getRandomLengthName("watermelon"),R.drawable.watermelon_pic);
            fruitList.add(watermelon);
            Fruit pear = new Fruit(getRandomLengthName("pear"),R.drawable.pear_pic);
            fruitList.add(pear);
            Fruit grape = new Fruit(getRandomLengthName("grape"),R.drawable.grape_pic);
            fruitList.add(grape);
            Fruit pineapple = new Fruit(getRandomLengthName("pineapple"),R.drawable.pineapple_pic);
            fruitList.add(pineapple);
            Fruit strawberry = new Fruit(getRandomLengthName("strawberry"),R.drawable.strawberry_pic);
            fruitList.add(strawberry);
            Fruit cherry = new Fruit(getRandomLengthName("cherry"),R.drawable.cherry_pic);
            fruitList.add(cherry);
            Fruit mango = new Fruit(getRandomLengthName("mango"),R.drawable.mango_pic);
            fruitList.add(mango);
        }
    }

// 不想实现也可以不用写
    private String getRandomLengthName(String name){
        Random random = new Random();
        int length = random.nextInt(20) + 1;
        StringBuilder builder = new StringBuilder();
        for(int i = 0;i<length;i++){
            builder.append(name);
        }
        return builder.toString();
    }

}

  • 首先在onCreate()方法中,创建了StaggeredGridLayoutManager的实例,它的构造函数接收了两个参数,第一个用于指定布局的列数,传入3表示会把布局分为3列,第二个参数用于指定布局的排列方向, StaggeredGridLayoutManager.VERTICAL表示是纵向排列,最后再把创建好的实例设置到RecyclerView中
  • 这里使用了一个小技巧,在这个getRandomLengthName()方法上,这个方法用了Random对象来创造一个1到20之间的随机数,然后将参数中传入的字符重复随即便,在initFruits()方法中,每个水果的名字都调用这个方法来生成,这样就保证水果的名字的长短差距大,子项的高度就不一样了


    2018-03-11_16-45-14.png
  • 若不写这个方法也是可以的,在传入的时候直接写入水果的名字也可以


    2018-03-17_11-13-27.png
  • 当然了,还可以写网络布局,只需要创建一个GridLayoutManager实例就可以了,它的构造函数接收两个参数,第一个是上下文对象,第二个参数是一行显示几列数据


    2018-03-17_11-19-17.png

RecyclerView的点击事件

这个的注册监听器方法是需要我们自己给子项具体的View去注册点击事件的

  1. 修改FruitAdapter中的代码

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

    private List<Fruit> mFruitList;

    static class ViewHolder extends RecyclerView.ViewHolder{
        // 这里定义一个View变量
        View fruitView;
        ImageView fruitImage;
        TextView fruitName;

        public ViewHolder(View view){
            super(view);
            // 保存最外层的布局实例
            fruitView  = view;
            fruitImage = view.findViewById(R.id.img);
            fruitName = view.findViewById(R.id.text);
        }
    }

    public FruitAdapter(List<Fruit> fruitList){
        mFruitList = fruitList;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.fruit_item,parent,false);
       // 
        final ViewHolder holder = new ViewHolder(view);

        //分别为最外层的布局和Image注册点击事件
        holder.fruitView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 获取到position,然后拿到Fruit实例
                int position = holder.getAdapterPosition();
                Fruit fruit = mFruitList.get(position);
                Toast.makeText(v.getContext(),"you click view"+fruit.getName(),Toast.LENGTH_SHORT).show();
            }
        });
        holder.fruitImage.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int position = holder.getAdapterPosition();
                Fruit fruit = mFruitList.get(position);
                Toast.makeText(v.getContext(),"you clcik image"+fruit.getImageId(),Toast.LENGTH_SHORT).show();
            }
        });
        return holder;
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        Fruit fruit = mFruitList.get(position);
        holder.fruitImage.setImageResource(fruit.getImageId());
        holder.fruitName.setText(fruit.getName());
    }

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

  • 先修改ViewHolder,在ViewHolder中添加fruitView变量来保存子项最外层布局的实例,然后在onCreateViewHolder()方法中注册点击事件
  • 分别为最外层的布局和Image都注册了事件,先获取到用户点击的position,然后通过position拿到响应的Fruit实例,然后通过Toast显示


    点击图片.png

    点击文字.png

了解Nine-Patch

  1. 现在项目中有一个气泡状的图片,将这个图片设置为背景图片
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/beijing"
    >
</LinearLayout>

2018-03-17_13-53-54.png

这个时候可以看到图片被均匀的拉伸了,效果极差,这个时候就可以使用Nine-Patch来处理了

  1. 右击要添加的图片,点击Create 9-Patch file


    2018-03-17_13-55-30.png
  2. 就进入到这个页面


    2018-03-17_13-57-25.png

    我们可以在四周绘制一个个小黑点,按住Shift键拖动就可以进行擦除,使用这个新的图片替换原来的,再运行程序就可以看到


    2018-03-17_14-00-18.png
  3. 这样,当图片需要拉伸的时候,就指定拉伸的区域,在外观上就好看了

编写聊天界面

  1. 首先使用到的是RecyclerView,所以首先进行在app/build.gradle中添加依赖库
dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:26.1.0'
    // 添加这行代码
    compile 'com.android.support:recyclerview-v7:26.1.0'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.1'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
}

  1. 编写主页面,修改activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#d8e0e8"
    >

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyc_1"
        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/edit_1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:hint="Type something here"
            android:textSize="25sp"
            android:maxLines="2"/>

        <Button
            android:id="@+id/send"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="25sp"
            android:text="Send"/>

    </LinearLayout>



</LinearLayout>

  • 在主页面中放一个RecycleView用于显示聊天的消息内容,又放置了一个输入框,和一个按钮
  1. 定义消息的实体类,新建一个Msg
public class Msg {
    // 接收到一条消息
    public static final int TYPE_RECEVED = 0;
    // 发出一条消息
    public static final int TYPE_SENT = 1;

    //消息内容
    private String content;
    // 消息类型
    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;
    }
}

  • Msg中只有两个字段,content表示消息的内容,type表示消息的类型,其中消息的类型有两个值可选,一个是TYPE_RECEVED表示接收到的数据,TYPE_SENT表示发送的数据
  1. 接下来编写RecyclerView的子项布局,新建msg_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <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: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"
            android:textSize="25sp"/>

    </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_msg"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_margin="10dp"
            android:textColor="#000000"
            android:textSize="25sp"/>

    </LinearLayout>


</LinearLayout>

  • 接收到的消息左对齐,发送的消息右对齐,这个时候问题来了,怎么让收到的消息和发出的消息在一个布局中呢在这一个布局中,必定有一个控件是空白的在学基本控件的时候学到了可见属性,稍后在代码中可以根据这个消息的类型来决定隐藏和显示那种消息
  1. 编写自定义的MagAdapter适配器,和在RecyclerView写的适配器代码基本一样

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

    private List<Msg> mMsgList;

    static class ViewHolder extends RecyclerView.ViewHolder{

        LinearLayout leftLayout;
        LinearLayout rightLayout;
        TextView lefMsg;
        TextView rightMsg;

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

    }

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

    @Override
    public MsgAdapter.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(MsgAdapter.ViewHolder holder, int position) {
        Msg msg = mMsgList.get(position);
        if (msg.getType() == Msg.TYPE_RECEVED){
            // 如果是接收到的消息,则显示左边的消息布局,将右边的隐藏
            holder.leftLayout.setVisibility(View.VISIBLE);
            holder.rightLayout.setVisibility(View.GONE);
            holder.lefMsg.setText(msg.getContent());
        }else if (msg.getType() == Msg.TYPE_SENT){
            // 如果是发送消息,那么显示右边的布局,把左边的布局隐藏
            holder.rightLayout.setVisibility(View.VISIBLE);
            holder.leftLayout.setVisibility(View.GONE);
            holder.rightMsg.setText(msg.getContent());
        }
    }

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


  1. 修改MainActivity中的代码

public class MainActivity extends AppCompatActivity {

    private List<Msg> msgList = new ArrayList<>();
    private EditText inputText;
    private Button send;
    private RecyclerView msgRecyclerView;
    private MsgAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_layout);
        // 初始化消息数据
        initMsag();
        inputText = (EditText)findViewById(R.id.edit_1);
        send = (Button)findViewById(R.id.send);
        // 获取到这个滚动控件
        msgRecyclerView = (RecyclerView)findViewById(R.id.recyc_1);
        // 指定这个控件的布局方式
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        //设置到这个滚动控件中
        msgRecyclerView.setLayoutManager(layoutManager);
        // 数据传入到自定义的适配器中
        adapter = new MsgAdapter(msgList);
        msgRecyclerView.setAdapter(adapter);
        //点击按钮的时候
        send.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // 获取到消息框中的内容
                String content = inputText.getText().toString();
                if (!"".equals(content)){
                    Msg msg = new Msg(content,Msg.TYPE_SENT);
                    msgList.add(msg);
                    // 当有新的消息的时候刷新ListView中的显示
                    adapter.notifyItemInserted(msgList.size()-1);
                    // 将ListView定位到最后一行
                    msgRecyclerView.scrollToPosition(msgList.size()-1);
                    // 清空输入框中的内容
                    inputText.setText("");
                }
            }
        });


    }

    public void initMsag(){
        Msg msg = new Msg("hello pony",Msg.TYPE_RECEVED);
        msgList.add(msg);
        Msg msg1 = new Msg("hello Tom",Msg.TYPE_SENT);
        msgList.add(msg1);
        Msg msg2 = new Msg("我们去哪里呀?",Msg.TYPE_RECEVED);
        msgList.add(msg2);
    }
}


  • 在initMsag()中初始化了几条数据,用于在RecyclerView中显示
  • 在点击按钮的时候,如果内容不为空,就创建了一个Msg对象,并且添加到了msgList中去
  • 然后调用适配器的notifyItemInserted()方法,用于通知列表中有新的数据插入,这样新增的一条消息才能够在RecyclerVIew中显示,
  • 接着调用RecyclerView的scrollToPosition()方法,将数据定位到最后一行,
  • 最后调用setTExt()方法将输入的内容清空


    2018-03-17_16-13-25.png

参考数据:第一行代码
若有错误请指出

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,284评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,115评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,614评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,671评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,699评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,562评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,309评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,223评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,668评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,859评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,981评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,705评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,310评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,904评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,023评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,146评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,933评论 2 355

推荐阅读更多精彩内容