RecyclerView详解

来源:互联网 发布:手机淘宝的首页装修 编辑:程序博客网 时间:2024/06/05 17:25
大家都知道,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
原创粉丝点击