前两篇文章总结了RecyclerView的一些使用:RecyclerView实现List View效果,RecyclerView实现GridView效果,RecyclerView设置Header等。今天,主要总结一下recyclerView其他的一些使用:监听RecyclerView滑动距离,为RecyclerView设置ItemDecoration,在RecyclerView中添加动画等。

一.监听RecyclerView的滑动

    如何监听RecyclerView的滑动,其实,RecyclerView本身就有监听滑动状态的支持,如下所示:

recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {

    @Override

    public void onScrollStateChanged(RecyclerView recyclerView, int newState) {

        super.onScrollStateChanged(recyclerView, newState);

    }



    @Override

    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {

        super.onScrolled(recyclerView, dx, dy);



    }

});

    我们可以在onScrolled中打印滑动的距离,看一下是否能够正确的监听滑动。因为我使用的是纵向滑动的RecyclerView,因此我监听dy的数值变化:

recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {

    @Override

    public void onScrollStateChanged(RecyclerView recyclerView, int newState) {

        super.onScrollStateChanged(recyclerView, newState);

    }



    @Override

    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {

        super.onScrolled(recyclerView, dx, dy);

        Log.d("TTTT", "y:" + dy);



    }

});

    我们上下滑动几下,看一下打印的log,不难发现,dy这个距离其实是每次滑动的距离,也就是从手指开始滑动到手指停止的一次距离,而不是累计的滑动距离,如下图所示:

Android TabLayout 滑动监听 recyclerview滑动监听_RecyclerView

    但是,在实际开发过程中,我们一般需要的是一个总的滑动距离。因此,我们可以修改一下代码,获取RecyclerView总的滑动距离,代码如下所示:

private int scrollY = 0;


recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {

    @Override

    public void onScrollStateChanged(RecyclerView recyclerView, int newState) {

        super.onScrollStateChanged(recyclerView, newState);

    }



    @Override

    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {

        super.onScrolled(recyclerView, dx, dy);

        scrollY += dy;

        Log.d("TTTT", "y:" + scrollY);



    }

});

    我们打印一下scroolY的数值,不难发现,我们现在得到的是一个累积的滑动距离,如下图所示:

Android TabLayout 滑动监听 recyclerview滑动监听_ide_02

二.为RecyclerView设置ItemDecoration

    有时候,为了RecyclerView的每个itemview的排列更加的美观,我们需要设置一些间隔。在RecyclerView中,我们可以通过使用ItemDecoration实现这样的需求,如下是我的一种实现方式,关键的地方已经在代码中注释:

package com.example.tuduzhao.myrecycleview;



import android.content.Context;

import android.graphics.Rect;

import android.support.v7.widget.RecyclerView;

import android.util.DisplayMetrics;

import android.view.View;

import android.view.WindowManager;



class MyDecoration extends RecyclerView.ItemDecoration {

    private int mSpan;

    private int mExtraSpace;

    private int mInnerSpace;

    private Context context;



    public MyDecoration(Context context, int spanCount, int itemWidth, int extraSpace) {

        this.context = context;



        WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);

        DisplayMetrics outMetrics = new DisplayMetrics();

        windowManager.getDefaultDisplay().getMetrics(outMetrics);

        int screenWidth = outMetrics.widthPixels;



        mInnerSpace = (screenWidth - itemWidth * spanCount - extraSpace * 2) / (spanCount * 2);

        this.mSpan = spanCount;

        this.mExtraSpace = extraSpace;

    }



    @Override

    public void getItemOffsets(Rect outRect, View view,

                               RecyclerView parent, RecyclerView.State state) {

        int position = parent.getChildAdapterPosition(view);

        int column = (position - 1) % mSpan;



        //header,左边间距与每行第一个一样,右边间距与每行最后一个一样

        if (position == 0) {

            outRect.left = mExtraSpace + mInnerSpace;

            outRect.right = mInnerSpace + mExtraSpace;

        }



        //每行第一个,左边额外设置间距

        if (column == 0) {



            outRect.left = mExtraSpace + mInnerSpace;

            outRect.right = mInnerSpace;

        }



        //每行第二个,不额外设置间距

        if (column == 1) {

            outRect.left = mInnerSpace;

            outRect.right = mInnerSpace;

        }



        //每行第三个,右边额外设置间距

        if (column == 2) {

            outRect.left = mInnerSpace;

            outRect.right = mInnerSpace + mExtraSpace;

        }

    }

    

}

    自定义好ItemDecoration了,那么我们如何使用它呢,只需要在Activity中调用addItemDecoration即可,如下所示:

recyclerView.addItemDecoration(new MyDecoration(this, 3, dp2px(this, 115), dp2px(this, 9)));

三.为RecyclerView的item添加动画

    有时候,出于某些需求,我们需要为RecyclerView的item增加动画。例如,我们想要给header增加动画,我们修改一下现有的代码:

header的布局文件:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:tools="http://schemas.android.com/tools"

    android:layout_width="match_parent"

    android:layout_height="wrap_content"

    android:orientation="vertical"

    tools:context=".MainActivity">



    <ImageView

        android:id="@+id/iv_header"

        android:layout_width="match_parent"

        android:layout_height="240dp"

        android:src="@mipmap/header" />

    <ImageView

        android:id="@+id/anim"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:layout_gravity="center"

        android:src="@drawable/fengshan" />

</LinearLayout>

viewholder:

package com.example.tuduzhao.myrecycleview;



import android.support.annotation.NonNull;

import android.support.v7.widget.RecyclerView;

import android.view.View;

import android.widget.ImageView;

import android.widget.TextView;



public class MyRecycleViewHolder extends RecyclerView.ViewHolder {

    public MyRecycleViewHolder(@NonNull View itemView) {

        super(itemView);

        iv = itemView.findViewById(R.id.iv);

        tv = itemView.findViewById(R.id.tv);

        btn = itemView.findViewById(R.id.btn);

        anim = itemView.findViewById(R.id.anim);

    }

    ImageView iv;

    TextView tv;

    TextView btn;

    ImageView anim;



}

adapter:

@Override

public void onBindViewHolder(@NonNull MyRecycleViewHolder myRecycleViewHolder, int i) {

    final MyRecycleViewHolder holder = myRecycleViewHolder;



    if (getItemViewType(i) == HEAD_VIEW) {



        holder.anim.startAnimation(getRotateAnimation());

    } else {



    }

}

private Animation getRotateAnimation() {

    RotateAnimation rotateAnimation = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);

    rotateAnimation.setRepeatCount(-1);

    rotateAnimation.setInterpolator(new LinearInterpolator());

    rotateAnimation.setDuration(3000);

    return rotateAnimation;

}

     按照上面的写法,可以实现在header上增加动画,但是,这样是有问题的,当我们滑动一段距离,header消失后,再次划上去时,动画自己停止了。这是自己在开发过程中遇到的一个问题,这个问题是recyclerView的item回收导致的。我们需要为itemview设置一个onAttachStateChangeListener监听器,在onViewAttachedToWindow方法中执行动画,在onViewDetachedFromWindow中清除动画(为了节省不必要的资源消耗),代码如下所示:

holder.itemView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {

    @Override

    public void onViewAttachedToWindow(View view) {

        holder.anim.startAnimation(getRotateAnimation());

        holder.anim.setOnClickListener(new View.OnClickListener() {

            @Override

            public void onClick(View v) {

                Toast.makeText(mContext, "点击了动画", Toast.LENGTH_SHORT).show();

            }

        });



    }



    @Override

    public void onViewDetachedFromWindow(View view) {

        if (holder.anim != null) {

            holder.anim.clearAnimation();

        }



    }

});

    最后,总结一下RecyclerView的使用。通过使用recyclerView,我们可以实现ListView,GridView等效果,可以自定义添加Header,可以监听滑动状态,可以自定义设置间隔,甚至可以在item中增加动画。RecyclerView的功能还是比较强大的,目前我对RecyclerView的使用也就这么多了。写博客的目的还是总结自己学习和工作中用到的一些东西,也希望为一些朋友带来一点帮助。