Android中利用RecyclerView实现瀑布流效果

    xiaoxiao2021-03-25  104

    RecyclerView相比于传统的ListView,功能更加强大,使用也比较方便,因此Android官方更加推荐使用RecycleView,未来也会有更多的程序逐渐从ListView转向RecycleView。为此,首先先来了解下RecycleView的用法。当然,最先看的是效果图:

    RecycleView属于新增的控件,为了让RecyclerView在所有的Android版本上都能使用,系统将RecyclerView定义在support库中,因此想要使用RecycleView这个控件,首先Android Studio要在项目的build.gradle中添加相应的依赖库才行。eclipse的话,项目中要有V7包。

    在项目的dependencies闭包中添加

    compile 'com.android.support:recyclerview-v7:24.2.1'

    添加完成后,在布局文件中添加控件时一定要写全包名。如下所示:

    <android.support.v7.widget.RecyclerView android:id="@+id/recycler_view" android:layout_width="match_parent" android:layout_height="match_parent"> </android.support.v7.widget.RecyclerView> 和ListView一样,复杂一点布局都需要我们自己写适配器,为RecyclerView准备适配器,让其继承自RecyclerView.Adapter,并将泛型指定为FruitAdapter.ViewHolder.其中ViewHolder是在FruitAdapter中定义的一个内部类,代码如下:

    package com.example.administrator.myapplication; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import java.util.List; public class FruitAdapterRecyclerView extends RecyclerView.Adapter<FruitAdapterRecyclerView.ViewHolder> { private List<Fruit> mFruitList; static class ViewHolder extends RecyclerView.ViewHolder{ View fruitItemView; ImageView imageView; TextView textView; public ViewHolder(View itemView) { super(itemView); fruitItemView=itemView; imageView= (ImageView) itemView.findViewById(R.id.img); textView= (TextView) itemView.findViewById(R.id.tv); } } public FruitAdapterRecyclerView(List<Fruit> mFruitList) { this.mFruitList = mFruitList; } @Override public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { View view= LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_item,viewGroup,false); final ViewHolder viewHolder=new ViewHolder(view); viewHolder.fruitItemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int position=viewHolder.getAdapterPosition(); Fruit fruit=mFruitList.get(position); Toast.makeText(v.getContext(),"点击的是itemview--"+fruit.getName(),Toast.LENGTH_SHORT).show(); } }); viewHolder.imageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int position=viewHolder.getAdapterPosition(); Fruit fruit=mFruitList.get(position); Toast.makeText(v.getContext(),"点击的是image--"+fruit.getName(),Toast.LENGTH_SHORT).show(); } }); return viewHolder; } @Override public void onBindViewHolder(ViewHolder viewHolder, int i) { Fruit fruit=mFruitList.get(i); viewHolder.imageView.setImageResource(fruit.getImgId()); viewHolder.textView.setText(fruit.getName()); } @Override public int getItemCount() { return mFruitList.size(); } }其中Fruit.java实体类代码如下: package com.example.administrator.myapplication; public class Fruit { private String name; private int imgId; public Fruit(String name,int imgId) { this.name = name; this.imgId = imgId; } public String getName() { return name; } public int getImgId() { return imgId; } }

    item的布局如下

    <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_margin="5dp" android:layout_height="wrap_content" android:orientation="vertical"> <ImageView android:id="@+id/img" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:id="@+id/tv" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:layout_gravity="left" /> </LinearLayout>

     刚开始的时候不容易理解,但是用的多了后,就发现比较好理解了,这里和ListView中的适配器类似首先定义了一个内部类ViewHolder,但是不同的是这里的ViewHolder要继承自RecyclerView.ViewHolder.然后在ViewHolder的构造函数中传入View参数,这个参数通常是RecyclerView的子项ItemView的布局,然后通过findViewById()方法来获取布局中的ImageView和TextView的实例。

           和ListView中的适配器一样,RecyclerView的适配器也有一个构造函数,通过这个方法将要展示的数据源传递进去并赋值给全局变量list,后续的操作都是基于此数据源进行操作的。

          由于FruitAdapter是继承自RecyclerView.Adaper的,那么就必须重写onCreatViewHolder()、onBindViewHolder()和getItemCount()这3个方法,onCreatViewHolder()方法是用于创建ViewHolder实例的,我们在这个方法中将list_item的布局加载进去。然后创建一个ViewHolder实例,并把加载出来的布局传入到构造函数中,最后将ViewHolder的实例返回;onBindViewHolder()方法是用于对RecyclerView子项的数据进行赋值的,会在每个子项被滚动到屏幕内的时候执行,这里我们通过position参数,利用数据源获取子项的数据,然后将数据设置到子项的控件中;而getItemCount()方法就和ListView中的一样了,它用于告诉RecyclerView一共有多少个子项。

         相比于ListView,RecyclerView在Activity的实现方面有个小的不同,就是多了个LayoutManager。代码如下:

    package com.example.administrator.myapplication; import android.app.Activity; import android.os.Bundle; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.StaggeredGridLayoutManager; import java.util.ArrayList; import java.util.List; import java.util.Random; public class RecycleViewActivity extends Activity{ List<Fruit> list=new ArrayList<>(); RecyclerView recyclerView; FruitAdapterRecyclerView fruitAdapterRecyclerView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_recycler); initFruits(); recyclerView= (RecyclerView) findViewById(R.id.recycler_view); LinearLayoutManager linearLayoutManager=new LinearLayoutManager(this); // linearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); // recyclerView.setLayoutManager(linearLayoutManager); StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL); recyclerView.setLayoutManager(layoutManager); fruitAdapterRecyclerView=new FruitAdapterRecyclerView(list); recyclerView.setAdapter(fruitAdapterRecyclerView); } private void initFruits() { for (int i=0;i<3;i++){ Fruit fruit=new Fruit(setRandomLength("apple"),R.mipmap.apple_pic); Fruit fruit2=new Fruit(setRandomLength("banana"),R.mipmap.banana_pic); Fruit fruit3=new Fruit(setRandomLength("cherry"),R.mipmap.cherry_pic); Fruit fruit4=new Fruit(setRandomLength("grape"),R.mipmap.grape_pic); Fruit fruit5=new Fruit(setRandomLength("mango"),R.mipmap.mango_pic); Fruit fruit6=new Fruit(setRandomLength("orange"),R.mipmap.orange_pic); Fruit fruit7=new Fruit(setRandomLength("pear"),R.mipmap.pear_pic); Fruit fruit8=new Fruit(setRandomLength("strawberry"),R.mipmap.strawberry_pic); list.add(fruit); list.add(fruit2); list.add(fruit3); list.add(fruit4); list.add(fruit5); list.add(fruit6); list.add(fruit7); list.add(fruit8); } } public String setRandomLength(String str){ StringBuilder sb=new StringBuilder(); Random random=new Random(); int num=random.nextInt(19)+1; for (int i = 0; i <num; i++) { sb.append(str).append(" "); } return sb.toString(); } } 这里我们创建了一个LinearLayoutManager对象,并将它设置到RecyclerView当中,LayoutManager用于指定RecyclerView的布局方式,这里如果使用LinearLayoutManager是线性布局的意思,可以实现和ListView中类似的效果。接下来就和ListView一样了,创建FruitAdapter实例,然后将数据传入到构造函数中,最后调用RecyclerView的setAdapter()方法来完成适配器的设置。

            当然,这里我们要实现的是瀑布流效果,所以选用的是StaggeredGridLayoutManager来实现的,它接受两个参数,第一个参数用于指定布局的列数,第二个参数指定布局的排列方向,最后还是将创建的实例设置到RecyclerView当中就行了。实现的效果如下:   

    RecyclerView的点击事件

    和ListView一样,控件要有点击事件才可以,不同于ListView的是,RecyclerView并没有提供类似于setOnItemClickListener()方法,采用的是点击事件都是交给具体的View去注册处理,相比于ListView中item中控件的点击事件的实现的话,要方便的多,这也就是RecyclerView的强大之处,可以轻松实现子项中任意控件或布局的点击事件。

           其中上面Adapter的第35行,注册的是整体item的点击事件,而第43行设置的是item中控件的点击事件。

    源码 点我下载

    转载请注明原文地址: https://ju.6miu.com/read-23195.html

    最新回复(0)