RecyclerView详解

大家都知道,ListView具有强大的统治力,在Android过去的开发中可以说是贡献卓越。直到现在,很多App还是一直在使用Listview。但是listView也有不少缺点,比如说:

优化步骤麻烦:①复用convertView ②新建一个Viewholder来保存UI组件 

可是说是面向View编程的,它的扩展性也不好,只能实现纵向滚动的效果,如果我们想在ListView中实现横向滚动是做不到的;

因此谷歌提供了一个功能更强大的组件——RecyclerView。它可以说是一个增强版的listView,不仅可以实现和ListView中相同的效果,还优化了listView中存在的各种不足。目前谷歌官方推荐使用RecyclerView。那么本篇文章就来详细讲解一下RecyclerView。

由于RecyclerView是新增的控件,为了能让它在所有的版本中都能使用,谷歌还是把RecyclerView放到了support库中,要想使用RecyclerView,首先需要在build.gradle中添加相应的依赖库才能使用:

    compile 'com.android.support:recyclerview-v7:24.1.0'
添加完成要Sync Now进行同步。

然后在布局文件上添加如下代码:

    <android.support.v7.widget.RecyclerView
        android:layout_width="match_parent"
        android:id="@+id/recycle_rv"
        android:layout_height="match_parent">
    </android.support.v7.widget.RecyclerView>
由于RecyclerView不是内置在SDK中的,所以需要把完整的包的路径写出来;

接下来写适配器:

package com.example.forget.recyle;

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.ListView;
import android.widget.TextView;

import java.util.List;
import java.util.Map;

/**
 * Created by Forget on 2017/1/7.
 */

public class MyRecycleViewAdapter extends RecyclerView.Adapter<MyRecycleViewAdapter.ViewHolder> {
    private List<Map<String, Object>> list;

    public MyRecycleViewAdapter(List<Map<String, Object>> list) {
        this.list = list;
    }

    /**
     * @param parent   此参数是外类中通过setlayoutmanager传递进来的布局
     * @param viewType 代表view的类型
     * @return 返回一个ViewHolder容器
     */
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycle_item
                , parent, false);
//        将加载的布局通过ViewHoder的构造方法传递进来
        ViewHolder viewHolder = new ViewHolder(view);
        return viewHolder;
    }

    /**
     * @param holder   此处的ViewHolder就是recyclerView的每一项
     * @param position 代表recyclerView的每一个位置
     */
    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        holder.hero_iamge.setImageResource((Integer) list.get(position).get("image"));
        holder.hero_desc.setText((CharSequence) list.get(position).get("desc"));
    }

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

    public class ViewHolder extends RecyclerView.ViewHolder {
        ImageView hero_iamge;
        TextView hero_desc;

        public ViewHolder(View itemView) {
            super(itemView);
            hero_iamge = (ImageView) itemView.findViewById(R.id.hero_iv);
            hero_desc = (TextView) itemView.findViewById(R.id.hero_desc);
        }
    }
}
RecyclerView是面向viewHolder编程的,上面的代码首先定义了一个内部类ViewHolder,ViewHolder需要继承RecyclerView.ViewHolder,我们定义的ViewHolder的构造函数需要传入一个View参数,这个参数就是每一个条目的最外边的布局容器,我们可以通过findviewByid获取布局中的UI组件;

自定义的adapter的构造函数用于初始化数据源,自定义的adapter需要实现onCreateViewHolder(),onBindViewHolder()和getItemcount()三个方法。

onCreateViewHolder()方法用于创建ViewHolder实例,将布局文件加载出来,通过ViewHolder的构造函数传入此View,完成ViewHolder的的构建,并返回此ViewHolder

onBindViewHolder()该方法是对于recyclerView的子项进行赋值

getItemcount()表示RecyclerView一共有多少项

适配器的工作完成了,接下来修改Activity中的代码:

package com.example.forget.recyle;

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

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class MainActivity extends AppCompatActivity {
    private RecyclerView recyclerView;
    private List<Map<String, Object>> list;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        initData();
        LinearLayoutManager llm = new LinearLayoutManager(this);

        recyclerView.setLayoutManager(llm);
        MyRecycleViewAdapter adapter = new MyRecycleViewAdapter(list);
        recyclerView.setAdapter(adapter);
    }

    private void initData() {
        list = new ArrayList<>();
        String [] desc=new String[]{"你看到我的小熊了吗?","想和我玩儿么?可别怪我的尾巴无情哟",
        "规则,就是用来打破的","我可没有刮胡子的闲工夫",
        "断剑重铸之日,骑士归来之时","我要吃掉他们!"};
        int [] iamges=new int[]{R.mipmap.anni,R.mipmap.huli,R.mipmap.jinkesi,R.mipmap.nanqiang,R.mipmap.ruiwen,
                R.mipmap.xiaoyu};
        for (int i = 0; i <desc.length ; i++) {
            Map<String,Object> map=new HashMap<>();
            map.put("image",iamges[i]);
            map.put("desc",desc[i]);
            list.add(map);
        }
     }

    private void initView() {
        recyclerView = (RecyclerView) findViewById(R.id.recycle_rv);
    }
}
这里比较重要的方法是 recyclerView.setLayoutManager(llm),这里表示指定recyclerView布局方式,可以实现和listView类似的效果:


实现横向滚动:

ListView的扩展性不好,若想实现横向滚动就不可能了。而recyclerView做起来特别简单,只需要修改一点代码即可:
        LinearLayoutManager llm = new LinearLayoutManager(this);
        llm.setOrientation(LinearLayoutManager.HORIZONTAL);
给布局管理器指定排列方式即可,效果如下:

(是不是很简单?)

RecyclerView的事件处理:

RecyclerView没有提供和listView类似的setOnItemClicklistener()方法,这样注册监听需要我们给子项具体的View进行设置事件,实现起来比较复杂一点,其实listView设置的点击事件并不是很人性化,setOnItemClicklistener()设置的是整个子菜单项的点击事件,可是若我需要点击子项中某个具体的组件呢?虽然也是可以实现,但是很麻烦,RecyclerView就直接放弃了对子项设置点击事件,所有的点击事件都由具体的View去实现:
在ViewHolder中封装一个View对象,并且在构造方法中进行实例化:
    public class ViewHolder extends RecyclerView.ViewHolder {
        ImageView hero_iamge;
        TextView hero_desc;
        View hero;
        public ViewHolder(View itemView) {
            super(itemView);
            hero=itemView;
            hero_iamge = (ImageView) itemView.findViewById(R.id.hero_iv);
            hero_desc = (TextView) itemView.findViewById(R.id.hero_desc);
        }
    }
 在onCreateViewHolder中可以对整个子项设置事件,也可以对单个UI设置事件:
   public ViewHolder onCreateViewHolder(final ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycle_item
                , parent, false);
//        将加载的布局通过ViewHoder的构造方法传递进来
        final ViewHolder viewHolder = new ViewHolder(view);
        viewHolder.hero.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int postion=viewHolder.getAdapterPosition();
                Toast.makeText(parent.getContext(), ""+list.get(postion).get("desc").toString(), Toast.LENGTH_SHORT).show();
            }
        });
        return viewHolder;
    }
效果如下:


好啦,今天就简单介绍这些吧,日后再说更加炫酷的功能。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值