[Android]关于RecyclerView控件的使用

最近在研究android中瀑布流视图的实现方法,我第一次看到这种视图是在一款视频App上,名叫bilibili手机客户端,非常喜欢这款App,它的界面十分漂亮,与用户的交互性很高。以下就是这款App瀑布流视图的截图

 

 

查阅相关资料,我了解到了这种瀑布流效果可以借助一款新的android控件来实现,这款控件在android-support-v7包中,大名就叫做RecyclerView。可以说,RecyclerView的确是款挺强大的控件,它不仅可以取代ListView,完成数据列表形式的展示,还能做到像瀑布流或表格这样的布局风格,巧妙的是,这些布局风格的切换仅仅需要一行代码就能实现,方便快捷。

与传统的ListView相比,RecyclerView增加了ViewHolder特性,这对于列表视图优化的实现便捷了许多。传统ListView实现优化一般是采用自己编写ViewHolder的形式,通过可复用视图(convertView)的setTag()getTag()方法传递ViewHolder,当adapter每次创建item视图( getView() )的时候直接修改ViewHolder中已经定义好的控件的属性,避免了每次在创建item视图( getView() )时都调用findViewById(),从而达到优化的效果。而RecyclerView则自带了ViewHolder,设置起来也十分简单,所以在代码优化的方面比起ListView便捷了不少。

      话不多说,以下就展示这款强大控件的使用吧!

首先是引包,因为我使用的是Android Studio,所以导包的方式为:

File-->Project Structure打开项目结构面板,然后按照下方截图所示即可导入RecyclerView包:

       


 

 

导好包后下面就进行代码的编写,以下是数据和RecyclerView的初始化:

  private void initData() {
        this.mData = new ArrayList<>();
        mAdapter = new ContentViewAdapter(this.mData,getApplicationContext());
        for(int i = 'A';i<'z';i++)
        {
            Map<String,String> map = new HashMap<>();
            map.put("name",(char)i+"");
            map.put("intro",i+"");
            this.mData.add(map);
        }
    }

    private void initView(RecyclerView.LayoutManager manager) {
        this.contentView = (RecyclerView) this.findViewById(R.id.id_content_view);
        
        /*设置Adapter*/
        this.contentView.setAdapter(this.mAdapter);
        /*设置recyclerView中item增减的动画效果*/
        this.contentView.setItemAnimator(new DefaultItemAnimator());
        /*设置布局*/
        this.contentView.setLayoutManager(manager); 
         //manager = new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL)
    }


上方有涉及到RecyclerView中LayoutManager的设置问题,在这里可传三种 LayoutManager:



    其中,若使用第一个manager,则可以把此RecyclerView布局变成ListView的列表形式,若使用第二个,则是瀑布流布局,而第三个则是表格布局,每个布局都有方向可设置,水平或垂直。





下面就是创建RecyclerView的Adapter类。


/**
 * My View Adapter
 */
public class ContentViewAdapter extends RecyclerView.Adapter<ContentViewAdapter.ContentViewHolder> {


    private List<Map<String,String>> data;
    private LayoutInflater inflater;
    private ItemClickListener mListener;




    public ContentViewAdapter(List<Map<String,String>> data,Context context)
    {
        this.inflater = LayoutInflater.from(context);
        this.data = data;
    }

    public void setItemClickListener(ItemClickListener listener)
    {
        this.mListener = listener;
    }

    @Override
    public ContentViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
        return new ContentViewHolder(this.inflater.inflate(R.layout.layout_item,viewGroup,false));
    }

    @Override
    public int getItemCount() {
        return this.data.size();
    }
    
    /**
     * 方法中获取item位置我用的是 contentViewHolder.getLayoutPosition()
     * 为什么不用参数中提供的position?
     * 原因是当增加或删除一个item时,使用到
     * notifyItemRemoved()或notifyItemInserted()方法
     * position值不会随之改变,但是getLayoutPosition()返回的是真实的item位置
     * 
     * */
    @Override
    public void onBindViewHolder(final ContentViewHolder contentViewHolder, int position) {
        Map<String,String> sth = this.data.get(contentViewHolder.getAdapterPosition());
        contentViewHolder.setName(sth.get("name"));
        contentViewHolder.setIntro(sth.get("intro"));

        if(mListener!=null)
        {

            contentViewHolder.getItemView().setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    ContentViewAdapter.this.mListener.onItemClick(v, contentViewHolder.getLayoutPosition());
                }
            });
            contentViewHolder.getItemView().setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View v) {
                    ContentViewAdapter.this.mListener.onItemLongClick(v, contentViewHolder.getLayoutPosition());
                    return false;
                }
            });
        }

        /*随意设置item的高度,目的为了达到瀑布流的效果*/
        ViewGroup.LayoutParams params = contentViewHolder.getItemView().getLayoutParams();
        params.height = (int) (300 + Math.random()*(500-300+1));

    }

    public void insertItem()
    {
        Map<String,String> oneDate = new HashMap<>();
        oneDate.put("name","Tom");
        oneDate.put("intro", "I am tom!");
        this.data.add(0, oneDate);

        //记住是用这个方法而不是notifyDataSetChanged(),不然会没有动画效果
        this.notifyItemInserted(0);

    }

    public void deleteItem(int pos)
    {
        this.data.remove(pos);
        //规则同上
        this.notifyItemRemoved(pos);

    }



    /**
     * My View Holder
     */
    class ContentViewHolder extends RecyclerView.ViewHolder {

        private TextView name;
        private TextView intro;
        private View itemView;

        public ContentViewHolder(View itemView) {
            super(itemView);
            this.itemView = itemView;
            this.name = (TextView) itemView.findViewById(R.id.id_name);
            this.intro = (TextView) itemView.findViewById(R.id.id_intro);
        }

        public void setName(String name) {
            this.name.setText(name);
        }

        public void setIntro(String intro) {
            this.intro.setText(intro);
        }

        public View getItemView()
        {
            return this.itemView;
        }

    }

    /**
     * 监听item点击/长点击事件
     * 因为RecyclerView中没有帮我们定义item被点击后的事件监听
     * 所以这需要我们自己去定义
     */
    public interface ItemClickListener
    {
        void onItemClick(View view,int which);
        void onItemLongClick(View view,int which);
    }

以上就是实现RecyclerView的基本代码,下面是运行时的截图:





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值