高级UIAndroid

RecycleView的使用

2019-12-30  本文已影响0人  瑟闻风倾

1. 概述

RecyclerView架构,提供了一种插拔式的体验。只管回收与复用View,其他可自己设置,所以高度的解耦,并具有充分的定制自由。因此通过这个RecyclerView可轻松实现ListView、GirdView和瀑布流等效果。

recyclerView = findView(R.id.test_recyclerview);
recyclerView .setLayoutManager(layout);//设置布局管理器
recyclerView .setAdapter(adapter)//设置adapter
recyclerView .setItemAnimator(new DefaultItemAnimator());//设置Item增删的动画
recyclerView .addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.HORIZONTAL));//添加分割线

2. 基本使用示例

2.1 实现线性布局ListView的效果

(1) RecycleviewTestActivity.java

package comi.example.liy.mytestdemo;

import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

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

/**
 * Created by liy on 2019-12-24 9:39
 */
public class RecycleviewTestActivity extends AppCompatActivity {

    private RecyclerView recyclerView;
    private List<String> names;
    private MyAdapter myAdapter;

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

        initData();
        recyclerView = findViewById(R.id.test_recycleview);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));//线性布局管理器,支持横向、纵向
        recyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));//使用系统分割线
        myAdapter = new MyAdapter();
        recyclerView.setAdapter(myAdapter);
    }

    private void initData(){
        names = new ArrayList<String>();
        names.add("李小倾");
        names.add("王小陌");
        names.add("赵思齐");
        names.add("钱卫聆");
        names.add("孙云溪");
        names.add("李龙飞");
        names.add("李子恒");
        names.add("颜绍");
        names.add("刘明蕴");
        names.add("郑星星");
        for (int i = 0; i < 10; i++){
            names.add("李" + (i+1));
        }
    }
    class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder>{

        @Override
        public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
        {
            MyViewHolder holder = new MyViewHolder(LayoutInflater.from(RecycleviewTestActivity.this).inflate(R.layout.item_recycleview, parent,false));
            return holder;
        }

        @Override
        public void onBindViewHolder(MyViewHolder holder, int position)
        {
            holder.tv.setText(names.get(position));
        }

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

        class MyViewHolder extends RecyclerView.ViewHolder {

            TextView tv;
            public MyViewHolder(@NonNull View itemView) {
                super(itemView);
                tv = (TextView) itemView.findViewById(R.id.name);
            }
        }
    }


}

(2) activity_recycleview.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

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

    </android.support.v7.widget.RecyclerView>

</android.support.constraint.ConstraintLayout>

(3) item_recycleview.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#06a7e2">

    <TextView
        android:id="@+id/name"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:gravity="center"
        android:text="1"/>
</FrameLayout>
ListView效果.png
分割线:在实际应用中我们也不需要去设计太过花哨的分割线,如果仅仅是希望item间有空隙,使用系统分割线或者设置item的margin即可实现。
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <TextView
        android:id="@+id/name"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:gravity="center"
        android:text="1"
        android:background="#06a7e2"
        android:layout_marginTop="1dp"
        android:layout_marginBottom="1dp"/>
</FrameLayout>
<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <item name="android:listDivider">@drawable/divider_bg</item>
    </style>

</resources>

divider_bg.xml:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle" >

    <gradient
        android:startColor="#ff0000"
        android:centerColor="#00ff00"
        android:endColor="#0000ff"
        android:type="linear" />
    <size android:height="4dp"/>

</shape>

自定义分割线效果:


自定义系统分割线效果.png

2.2 实现网格布局GridView的效果

(1) RecycleviewTestActivity.java中修改布局管理器:recyclerView.setLayoutManager(new GridLayoutManager(this,3))

 //recyclerView.setLayoutManager(new LinearLayoutManager(this));//线性布局管理器,支持横向、纵向
recyclerView.setLayoutManager(new GridLayoutManager(this,3));//网格布局管理器
recyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));//使用系统分割线
GridView效果.png

修改布局管理器为GridLayoutManager以后,由上图的显示效果来看,明显此时系统默认的分割线效果不满足我们的需求,如果仅仅是希望item间有空隙,此时设置item的margin显然是最简单的方式(同时注释掉系统分割线的调用)。

(2) 修改item_recycleview.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <TextView
        android:id="@+id/name"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:gravity="center"
        android:text="1"
        android:background="#06a7e2"
        android:layout_margin="1dp"/>
</FrameLayout>

(3) GridView效果展示


GridView效果.png

2.3 实现瀑布流布局效果

瀑布流的实现和网格布局效果并无多大区别,只需在网格布局效果的基础上修改布局管理器为recyclerView.setLayoutManager(new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL)),然后在适配器的onBindViewHolder方法中将item的固定高度设置为随机高度即可。

(1) 修改RecycleviewTestActivity.java

//recyclerView.setLayoutManager(new LinearLayoutManager(this));//线性布局管理器,支持横向、纵向
//recyclerView.setLayoutManager(new GridLayoutManager(this,3));//网格布局管理器
recyclerView.setLayoutManager(new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL));//瀑布布局管理器
//recyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));//使用系统分割线(适用于线性布局)
@Override
public void onBindViewHolder(MyViewHolder holder, int position){
      ViewGroup.LayoutParams lp = holder.tv.getLayoutParams();
      lp.height = (int) (100 + Math.random() * 300);//随机高度
      holder.tv.setLayoutParams(lp);

      holder.tv.setText(names.get(position));
}

(2) item_recycleview.xml和网格布局的一致即可
(3) 瀑布流效果展示


瀑布流效果.png

3. 自定义点击或长按效果

系统没有提供ClickListener和LongClickListener,需要我们自己去实现。
实现的方式比较多,既可以通过recyclerView.addOnItemTouchListener去监听然后去判断手势,也可以通过在adapter中定义回调接口,这里以后者为例实现自定义点击或长按效果。

(1) RecycleviewTestActivity.java

package comi.example.liy.mytestdemo;

import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;

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

/**
 * Created by liy on 2019-12-24 9:39
 */
public class RecycleviewTestActivity extends AppCompatActivity {

    private RecyclerView recyclerView;
    private List<String> names;
    private MyAdapter myAdapter;

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

        initData();
        recyclerView = findViewById(R.id.test_recycleview);
        //recyclerView.setLayoutManager(new LinearLayoutManager(this));//线性布局管理器,支持横向、纵向
        //recyclerView.setLayoutManager(new GridLayoutManager(this,3));//网格布局管理器
        recyclerView.setLayoutManager(new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL));//瀑布布局管理器
        //recyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));//使用系统分割线(适用于线性布局)
        //recyclerView.addItemDecoration(new MyDividerItemDecoration(this,MyDividerItemDecoration.VERTICAL));//自定义分割线(适用于线性布局)
        //recyclerView.addItemDecoration(new MyDividerGridItemDecoration(this));//自定义分割线(适用于网格布局)
        recyclerView.setItemAnimator(new DefaultItemAnimator());//设置item增删的动画(默认效果,可省略)
        myAdapter = new MyAdapter(this,names);
        recyclerView.setAdapter(myAdapter);

        initListener();//Activity中设置监听
    }

    private void initData(){
        names = new ArrayList<String>();
        names.add("李小倾");
        names.add("王小陌");
        names.add("赵思齐");
        names.add("钱卫聆");
        names.add("孙云溪");
        names.add("李龙飞");
        names.add("李子恒");
        names.add("颜绍");
        names.add("刘明蕴");
        names.add("郑星星");
        for (int i = 0; i < 10; i++){
            names.add("李" + (i+1));
        }
    }

    private void initListener(){
        myAdapter.setOnItemClickLitener(new MyAdapter.OnItemClickLitener()
        {
            @Override
            public void onItemClick(View view, int position) {
                Toast.makeText(RecycleviewTestActivity.this, position + " click",Toast.LENGTH_SHORT).show();
                addData(position);
            }

            @Override
            public void onItemLongClick(View view, int position) {
                Toast.makeText(RecycleviewTestActivity.this, position + " long click",Toast.LENGTH_SHORT).show();
                removeData(position);
            }
        });
    }

    public void addData(int position){
        names.add(position,"newName");//在当前位置添加
        //names.add("newName");//在末尾添加
        myAdapter.notifyItemInserted(position);//更新数据集刷新界面
    }

    public void removeData(int position){
        names.remove(position);
        myAdapter.notifyItemRemoved(position);//更新数据集刷新界面
    }

    static class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder>{
        private Context context;
        private List<String> names;

        public MyAdapter(Context context, List<String> names) {![waterfall.gif](https://img.haomeiwen.com/i1892430/e50ef69c88426aba.gif?imageMogr2/auto-orient/strip)

            this.context = context;
            this.names = names;
        }

        //定义一个回调接口
        public interface OnItemClickLitener{
            void onItemClick(View view, int position);
            void onItemLongClick(View view , int position);
        }
        private OnItemClickLitener mOnItemClickLitener;
        public void setOnItemClickLitener(OnItemClickLitener mOnItemClickLitener) {
            this.mOnItemClickLitener = mOnItemClickLitener;
        }

        @Override
        public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
        {
            MyViewHolder holder = new MyViewHolder(LayoutInflater.from(context).inflate(R.layout.item_recycleview, parent,false));
            return holder;
        }

        @Override
        public void onBindViewHolder(final MyViewHolder holder, int position)
        {
            ViewGroup.LayoutParams lp = holder.tv.getLayoutParams();
            lp.height = (int) (100 + Math.random() * 300);//随机高度
            holder.tv.setLayoutParams(lp);

            holder.tv.setText(names.get(position));

            // 如果设置了回调,则设置点击事件
            if (mOnItemClickLitener != null) {
                holder.tv.setOnClickListener(new View.OnClickListener()
                {
                    @Override
                    public void onClick(View v)
                    {
                        int pos = holder.getLayoutPosition();
                        mOnItemClickLitener.onItemClick(holder.itemView, pos);//回调我们设置的监听
                    }
                });

                holder.tv.setOnLongClickListener(new View.OnLongClickListener()
                {
                    @Override
                    public boolean onLongClick(View v)
                    {
                        int pos = holder.getLayoutPosition();
                        mOnItemClickLitener.onItemLongClick(holder.itemView, pos);
                        return true;//返回true自己消费掉,事件不会再向下传递触发点击事件
                    }
                });
            }

        }

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

        class MyViewHolder extends RecyclerView.ViewHolder {

            TextView tv;
            public MyViewHolder(@NonNull View itemView) {
                super(itemView);
                tv = (TextView) itemView.findViewById(R.id.name);
            }
        }

    }


}

(2) 自定义点击或长按效果


自定义点击或长按效果.gif
上一篇 下一篇

猜你喜欢

热点阅读