MateralDesign-RecyclerView

MateralDesign-RecyclerView


ListView功能十分强大,同时在Android开发中可以说贡献卓越,直到今天仍然还有很多不计其数的程序再继续使用着ListView.不过ListView并不是完全没有缺点,比如说如果我们不使用一些技巧来提升它的运行效率,那么ListView的性能很差。还有,ListView的扩展性也不够很好,它只能实现数据纵向滚动的效果,如果想让实现横向滚动的话,ListView很难实现。

为此,Android提供了一个强大的滚动控件----RecycleView。它是增强版的ListView,不仅可以轻松实现和ListView同样的效果,还优化了ListView中存在的不足之处,目前Android官方推荐使用RecycleView,之后的开发中更多地程序逐渐从ListView转变到RecycleView.

下来我简单的创建一个RecycleViewTest项目,简述一下RecycleView的简单用法。

首先我们需要打开app/build.gradle文件,在dependencies闭包中添加如下的内容:

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:25.1.0'
    compile 'com.android.support:recyclerview-v7:24.2.1'
    testCompile 'junit:junit:4.12'
}

添加完之后Sync Now 进行同步

布局很简单

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

使用RecycleView和ListView步骤基本一致,还需要创建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/iv_fruit_image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@mipmap/banana_pic"
        android:layout_gravity="center_horizontal"
        />
    <TextView
        android:id="@+id/tv_fruit_info"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="left"
        android:text="水果信息"
        />

</LinearLayout>

Ok,到此基本上布局就搞定了。接下来我们创建一个Adapter,新建一个FruitAdapter类,让这个适配器继承自RecycleView.Adapter,并且泛型指定为FruitAdapter.ViewHolder,其中ViewHolder是我们在FruitAdapter中定义的一个的同步类,代码如下所示:

/**
 * Description:
 * Copyright  : Copyright (c) 2016
 * Author     : yangfang
 */

public class FruitAdapter extends RecyclerView.Adapter<FruitAdapter.ViewHolder> {
    private List<Fruit> mFruitList;

    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.fruitInfo.setText(fruit.getName());
    }

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

    static class ViewHolder extends RecyclerView.ViewHolder {

        private ImageView fruitImage;
        private TextView  fruitInfo;

        public ViewHolder(View itemView) {
            super(itemView);
            fruitImage = (ImageView) itemView.findViewById(R.id.iv_fruit_image);
            fruitInfo = (TextView) itemView.findViewById(R.id.tv_fruit_info);
        }

    }

}

简单解释一下先定义一个内部类ViewHolder,ViewHolder要继承自RecycleView.ViewHolder,,然后ViewHolder的构造函数中要传入View参数,此View是RecyleView子项目的最外层布局,然后通过findViewById()方法来获取到布局中的ImagesView和TextView。

FruitAdapter中有一个构造函数,这个方法用于把展示的数据源传进来,变成一个全局变量mFruitAdapter.

FruitAdapter继承自RecycleView.Adapter必须重写onCreateViewHolder(),onBindViewHolder()和getItemCount().

onCreateViewHolder()用于创建ViewHolder实例,将对象item布局加载进来,并且把加载出俩的布局传入到构造函数中,最后ViewHolder的实例返回。

onBindViewHolder()用于对RecycleView子项的数据进行赋值,会在每个子项滚动到屏幕内的时候执行,通过position参数得到当前项Fruit实例,然后再将数据设置到ViewHolder的ImageView和TextView当中。

getItemCount()告诉recycleView一共加载多少项。

适配器创建好之后,接下来需要在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);
        initFruit();
        RecyclerView recycleView = (RecyclerView) findViewById(R.id.recycle_view);
        StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL);
        recycleView.setLayoutManager(layoutManager);
        FruitAdapter adapter = new FruitAdapter(fruitList);
        recycleView.setAdapter(adapter);
    }

    private void initFruit() {
        for (int i = 0; i < 5 ; i++) {
            Fruit apple = new Fruit("Apple", R.drawable.pineapple_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 pear = new Fruit("pear", R.drawable.pear_pic);
            fruitList.add(pear);

            Fruit cherry = new Fruit("cherry", R.drawable.cherry_pic);
            fruitList.add(cherry);

            Fruit grape = new Fruit("grape", R.drawable.grape_pic);
            fruitList.add(grape);

            Fruit mango = new Fruit("mango", R.drawable.mango_pic);
            fruitList.add(mango);

            Fruit strawberry = new Fruit("strawberry", R.drawable.strawberry_pic);
            fruitList.add(strawberry);

        }

    }

}

到这里使用RecycleView实现ListView样式基本实现。

在此处需要关注关于Adapter相关的一些问题:Adapter的作用是数据和界面的桥梁,通过适配器至ListView(如调用了ListView的setAdapter(adapter))列表的每一项显示至页面,其实当列表中的每一项显示到页面中都会调用Adapter的getView返回一个View。

CurorAdapter提供了两个抽象方法

newView(context,cursor,viewGroup)

bindView(view,context,cursor)

newView()和bindView()细化了getView()中的功能实现,均可由getview()实现。


接下我们试着用RecycleView实现一个横向滚动和瀑布流

ListView扩展性能不好,它只能实现纵向滚动的效果,如果想实现横向的滚动,那么就需要使用RecycleView去实现。         

RecyclerView recycleView = (RecyclerView)findViewById(R.id.recycler_view);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
recycleView.setLayoutManager(layoutManager);
FruitAdapter adapter = new FruitAdapter(fruitList);
recycleView.setAdapter(adapter);

为什么ListView很难或者根本无法实现效果在RecyclerView上这么轻松实现呢?

因为ListView的布局排列是由自身去管理的,而RecyclerView则将这个工作交给LayoutManager,LayoutManager中制定了一套可扩展的布局排列接口,子类只要按照接口的规范来实现,就能定制出各类不同排列方式的布局了。


LinearLayoutManager之外,RecyclerView还给我们提供了GridLayoutManager和StaggeredGridLayoutManager这两种内置的布局排列方式。GridLayoutManager可以用于实现网格布局,StaggerGridLayoutManager可以用于实现瀑布流布局。

接下来简单的实现一下瀑布流

简单的布局布局如下

<?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/fruit_image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal" />

    <TextView
        android:id="@+id/fruit_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="left"
        android:layout_marginTop="10dp" />

</LinearLayout>


接下来修改MainActivity中的代码,如下所示

public class MainActivity extends AppCompatActivity {

    private List<Fruit> fruitList = new ArrayList<Fruit>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initFruits();
        RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
        StaggeredGridLayoutManager layoutManager = new
                StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL);
        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();
    }

}


RecyclerView点击事件

和ListView一样,RecyclerView也必须要能相应点击事件才可以,下面我们介绍一下如何在RecyclerView中注册点击事件,修改FruitAdapter中的代码

    @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);
        holder.fruitView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int position = holder.getAdapterPosition();
                Fruit fruit = mFruitList.get(position);
                Toast.makeText(v.getContext(), "you clicked 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 clicked image " + fruit.getName(), Toast.LENGTH_SHORT).show();
            }
        });
        return holder;
    }








  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值