精通RecyclerView:打造ListView、GridView、瀑布流;学会添加分割线、 添加删除动画 、Item点击事件

转载请注明出处:http://blog.csdn.net/linglongxin24/article/details/53126706

本文出自【DylanAndroid的博客】


精通RecyclerView:打造ListView、GridView、瀑布流;学会添加分割线、 添加删除动画 、Item点击事件

在上一篇Android用RecyclerView练手仿美团分类界面写了RecyclerView的基本用法,

今天想想,在这里重新学习一下RecyclerView的完整用法。包括如何打造一个普通的ListView和横向的ListView、普通的GridView和横向的GridView、如何添加分割线、

还有就是添加和删除的动画、以及如何设置Item的OnClick事件监听。这里包含了各种用法,也算是一个入门的用法,已经掌握的高手请略过。

先看总体效果图

一.RecyclerView介绍

RecyclerView 是Android 5.0版本中新出现的东西,用来替代ListView和GridView的。

二.RecyclerView架构

RecyclerView使用布局管理器LayoutManager和适配器Adapter的适配器模式去实现架构,不关心数据的来源。耦合性非常的底,用户可以根据自己的用户界面去实现相应的效果

三.RecyclerView的优点

  • 1.RecyclerView内部已经强制使用VIewHolder,优化了对Item中View的复用。
  • 2.提供了一个较为灵活的布局管理类,LayoutManager,用来控制RecyclerView是线性展示还是垂直展示,以及可以设置成瀑布流。并且提供了ItemDecoration这个类,来灵活的让用户来设置分割线。
  • 3.用ItemAnimator可以对item进行布局的删减动画效果。

四.RecyclerView实现三部曲

  • 第一步:设置布局管理器

    用来确定每一个item如何进行排列摆放:

    • LinearLayoutManager 相当于ListView的效果
    • GridLayoutManager相当于GridView的效果
    • StaggeredGridLayoutManager 瀑布流
  • 第二步:添加分割线

    我们用到了网上流传的万能分割线DividerItemDecoration和DividerGridItemDecoration,首先在style.xml里面定义分割线图片:

    1.先在drawable中新建divider.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle" >
    <solid android:color="@color/colorAccent"/>
    <size android:height="1dp"
        android:width="1dp"/>
</shape>
    2.然后在style.xml中设置android:listDivider
        <item name="android:listDivider">@drawable/divider</item>
  • 第三步:设置适配器
package cn.bluemobi.dylan.recyclerviewdemo2;

import android.content.Context;
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 java.util.ArrayList;
import java.util.List;

/**
 * RecyclerView的适配器
 * Created by yuandl on 2016-11-01.
 */

public class RvAdapter extends RecyclerView.Adapter<RvAdapter.MyViewHolder> {
    private Context context;
    private List<Integer> datas;

    /**
     * item的点击事件的长按事件接口
     */
    private OnItemClickListener onItemClickListener;
    /**
     * 瀑布流时的item随机高度
     */
    private List<Integer> heights = new ArrayList<>();

    /**
     * 不同的类型设置item不同的高度
     *
     * @param type
     */

    private int type = 0;

    public RvAdapter(Context context, List<Integer> datas) {
        this.context = context;
        this.datas = datas;
        for (int i : datas) {
            int height = (int) (Math.random() * 100 + 300);
            heights.add(height);
        }
    }

    public void setType(int type) {
        this.type = type;
    }

    /**
     * 设置点击事件
     *
     * @param onItemClickListener
     */
    public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
        this.onItemClickListener = onItemClickListener;
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View contentView = LayoutInflater.from(context).inflate(R.layout.item, parent, false);
        MyViewHolder viewHolder = new MyViewHolder(contentView);
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(MyViewHolder holder, final int position) {
        RecyclerView.LayoutParams layoutParams;
        if (type == 0) {
            layoutParams = new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        } else if (type == 1) {
            layoutParams = new RecyclerView.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        } else {
            layoutParams = new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, heights.get(position));
            layoutParams.setMargins(2, 2, 2, 2);
        }
        holder.itemView.setLayoutParams(layoutParams);
        holder.imageView.setImageResource(datas.get(position));
        holder.tv.setText("分类" + position);
        /**设置item点击监听**/
        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (onItemClickListener != null) {
                    onItemClickListener.onItemClickListener(position, datas.get(position));
                }
            }
        });

    }

    @Override
    public int getItemCount() {
        return datas == null ? 0 : datas.size();
    }

    /**
     * 用于缓存的ViewHolder
     */
    public class MyViewHolder extends RecyclerView.ViewHolder {
        private ImageView imageView;
        public TextView tv;

        public MyViewHolder(View itemView) {
            super(itemView);
            imageView = (ImageView) itemView.findViewById(R.id.iv);
            tv = (TextView) itemView.findViewById(R.id.tv);
        }
    }

    /**
     * 设置item监听的接口
     */
    public interface OnItemClickListener {
        void onItemClickListener(int position, Integer data);

    }
}

五.打造各种效果

  • 1.竖向的ListView
    rv.setBackgroundColor(Color.TRANSPARENT);
    rv.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
    rvAdapter.setType(0);
    rv.removeItemDecoration(itemDecoration);
    rv.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT));
    itemDecoration = new DividerItemDecoration(this, DividerItemDecoration.VERTICAL_LIST);
    rv.addItemDecoration(itemDecoration);

  • 2.横向的ListView
   rvAdapter.setType(1);
   rv.removeItemDecoration(itemDecoration);
   rv.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT));
   rv.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false));
   itemDecoration = new DividerItemDecoration(this, DividerItemDecoration.HORIZONTAL_LIST);
   rv.addItemDecoration(itemDecoration);

  • 3.竖向的GridView
   rvAdapter.setType(1);
   rv.setBackgroundColor(Color.TRANSPARENT);
   rv.removeItemDecoration(itemDecoration);
   rv.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT));
   rv.setLayoutManager(new GridLayoutManager(this, 5));
   itemDecoration = new DividerGridItemDecoration(this);
   rv.addItemDecoration(itemDecoration);

  • 4.横向的GridView
    rvAdapter.setType(1);
    rv.setBackgroundColor(Color.TRANSPARENT);
    rv.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT));
    rv.removeItemDecoration(itemDecoration);
    rv.setLayoutManager(new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.HORIZONTAL));
    itemDecoration = new DividerGridItemDecoration(this);
    rv.addItemDecoration(itemDecoration);

  • 5.竖向的瀑布流
     rvAdapter.setType(3);
     rv.setBackgroundColor(getResources().getColor(R.color.colorAccent));
     rv.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT));
     rv.removeItemDecoration(itemDecoration);
     rv.setLayoutManager(new StaggeredGridLayoutManager(5, StaggeredGridLayoutManager.VERTICAL));

  • 6.添加和删除动画
       /**添加一个数据**/
       rvAdapter.notifyItemInserted(1);
       /**删除一个数据**/
       rvAdapter.notifyItemRemoved(1);

六.GiHub

时间: 2024-08-27 14:50:57

精通RecyclerView:打造ListView、GridView、瀑布流;学会添加分割线、 添加删除动画 、Item点击事件的相关文章

从源码角度入手实现RecyclerView的Item点击事件

转载请注明出处:http://www.cnblogs.com/cnwutianhao/p/6758373.html RecyclerView 作为 ListView 和 GridView 的替代产物,相信在Android界已广为流传. RecyclerView 本是不会有类似 ListView 的那种点击事件,但是知道和会用又是两种情况,跟随我一起从源码角度分析,RecyclerView 点击事件. 首先看一下 Google 对 ListView 家族谱的介绍: 可以看出 ListView 归根

从头开始学 RecyclerView(二) 添加item点击事件

不管了,先来张图 偶吐了个槽 item点击事件必须手动添加,默认并没有一个显式的API接口可供调用. 为了节约学习时间,网上找了篇很不错的文章.这里基本就复制了. 添加点击事件 RecyclerView#addOnItemTouchListener 分析 查看RecyclerView源码可以看到,RecyclerView预留了一个Item的触摸事件方法: public void addOnItemTouchListener(OnItemTouchListener listener) { mOnI

Android 高级UI设计笔记20:RecyclerView 的详解之RecyclerView添加Item点击事件

1. 引言: RecyclerView侧重的是布局的灵活性,虽说可以替代ListView但是连基本的点击事件都没有,这篇文章就来详细讲解如何为RecyclerView的item添加点击事件,顺便复习一下观察者模式. 2. 最终目的 模拟ListView的setOnItemClickListener()方法,调用者只须调用类似于setOnItemClickListener的东西就能获得被点击item的相关数据.   3. 原理 为RecyclerView的每个子item设置setOnClickLi

Android学习之解决ListView中item点击事件和item中Button点击事件冲突问题

在ListView中添加Button后,如果只是单纯的加入而不加限制的话,ListView的onClick点击事件没有响应,因为Button获取了item的焦点,想要两者都可点击,需要加上如下限制: 在ListView的适配器中的布局文件中添加: (1)在布局文件的根元素上中添加属性android:descendantFocusability="blocksDescendants" (2)在Button中添加属性android:focusable="false"和a

自定义adapter的基础上Listview优化方案以及几个小错误(checkbox吃掉点击事件以及对象重复问题)

每次adapter运行都有一个getcount,有多少条就调用多少次getview,就会解析多少次xml文件(创建view,条数多了很消耗时间),13年谷歌提出了一个机制,每次只缓存一屏幕多几个,把划出屏幕外的listview回收(用的convertView),只要修改里面的值就可以重新用不用再创建一个view 修改的是自定义adapter中的getview方法 @Overridepublic View getView(int position, View convertView, ViewGr

Android listview的item点击事件失效Bug的解决

原因:listview布局中出现了button  .imaageButton.checkBox等可以点击的控件 第一种解决方法:在布局中添加android:descendantFocusability="blocksDescendants" 第二种解决方法:使用其他控件代替,在activity中用setOnClickListener监听点击事件

解决ListView中Item的子控件与Item点击事件冲突

经常会碰到在ListView中点击其中一个Item,会一并触发其子控件的点击事件,例如Item中的Button.ImageButton等,导致了点击Item中Button以外区域也会触发Button点击事件.在网上找了相关方法,这里记录下,亲测可行.. 1.在Item的xml文件根元素中添加属性:android:descendantFocusability="blocksDescendants" 2.在冲突的子控件中添加属性:android:focusable="false&

ListView的Item点击事件(消息传递)

转载请保留原文出处“http://my.oschina.net/gluoyer/blog”,谢谢! 您可以到博客的“友情链接”中,“程序猿媛(最新下载)*.*”下载最新版本,持续更新!当前版本,也可直接点击“当前1.5版本”下载.     引子:自定义ListView的Adapter,给Item中的子控件(按钮.图标.文字等)添加点击事件,来进行点击后的不同处理,是经常要做的事情.但有些需要在处理事件中,对Activity中其他控件进行更新的话,通常把Adapter在Activity中实现,处理

android捕获ListView中每个item点击事件

package com.wps.android; import java.util.ArrayList; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListe