博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
RecyclerView你一定会用到的功能
阅读量:6624 次
发布时间:2019-06-25

本文共 17352 字,大约阅读时间需要 57 分钟。

RecyclerView不显示阴影的方法

安卓6.0以后不管是RecylerView或者Listview或者ViePpager以及Scrollviw滚动到底部和顶部都会出现阴影,有时你会感觉挺烦的,只需要在xml中添加两行代码就能去除掉阴影

android:fadingEdge="none"android:overScrollMode="never"复制代码

解决RecyclerView和Scrollviw的冲突

如何让Scrollviw里面显示显示RecyclerView

xml需要用一个view包含recylerview

复制代码

代码中需要添加如下属性

mRecyclerView.setLayoutManager(new FullyLinearLayoutManager(mContext));mRecyclerView.setNestedScrollingEnabled(false);复制代码

FullyLinearLayoutManager是线性布局的manager,recylerview还需要FullyGridLayoutManager,ExStaggeredGridLayoutManager根据需要选择不同的管理器

1.FullyLinearLayoutManager的代码如下

public class FullyLinearLayoutManager  extends LinearLayoutManager {    private static final String TAG = FullyLinearLayoutManager.class.getSimpleName();    public FullyLinearLayoutManager(Context context) {        super(context);    }    public FullyLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {        super(context, orientation, reverseLayout);    }    private int[] mMeasuredDimension = new int[2];    @Override    public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state,                          int widthSpec, int heightSpec) {        final int widthMode = View.MeasureSpec.getMode(widthSpec);        final int heightMode = View.MeasureSpec.getMode(heightSpec);        final int widthSize = View.MeasureSpec.getSize(widthSpec);        final int heightSize = View.MeasureSpec.getSize(heightSpec);        int width = 0;        int height = 0;        for (int i = 0; i < getItemCount(); i++) {            measureScrapChild(recycler, i,                    View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),                    View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),                    mMeasuredDimension);            if (getOrientation() == HORIZONTAL) {                width = width + mMeasuredDimension[0];                if (i == 0) {                    height = mMeasuredDimension[1];                }            } else {                height = height + mMeasuredDimension[1];                if (i == 0) {                    width = mMeasuredDimension[0];                }            }        }        switch (widthMode) {            case View.MeasureSpec.EXACTLY:                width = widthSize;            case View.MeasureSpec.AT_MOST:            case View.MeasureSpec.UNSPECIFIED:        }        switch (heightMode) {            case View.MeasureSpec.EXACTLY:                height = heightSize;            case View.MeasureSpec.AT_MOST:            case View.MeasureSpec.UNSPECIFIED:        }        setMeasuredDimension(width, height);    }    private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec,                                   int heightSpec, int[] measuredDimension) {        try {            View view = recycler.getViewForPosition(0);//fix 动态添加时报IndexOutOfBoundsException            if (view != null) {                RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams();                int childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec,                        getPaddingLeft() + getPaddingRight(), p.width);                int childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec,                        getPaddingTop() + getPaddingBottom(), p.height);                view.measure(childWidthSpec, childHeightSpec);                measuredDimension[0] = view.getMeasuredWidth() + p.leftMargin + p.rightMargin;                measuredDimension[1] = view.getMeasuredHeight() + p.bottomMargin + p.topMargin;                recycler.recycleView(view);            }        } catch (Exception e) {            e.printStackTrace();        } finally {        }    }}复制代码

2.FullyGridLayoutManager的代码如下

public class FullyGridLayoutManager extends GridLayoutManager {    public FullyGridLayoutManager(Context context, int spanCount) {        super(context, spanCount);    }    public FullyGridLayoutManager(Context context, int spanCount, int orientation, boolean reverseLayout) {        super(context, spanCount, orientation, reverseLayout);    }    private int[] mMeasuredDimension = new int[2];    @Override    public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state, int widthSpec, int heightSpec) {        final int widthMode = View.MeasureSpec.getMode(widthSpec);        final int heightMode = View.MeasureSpec.getMode(heightSpec);        final int widthSize = View.MeasureSpec.getSize(widthSpec);        final int heightSize = View.MeasureSpec.getSize(heightSpec);        int width = 0;        int height = 0;        int count = getItemCount();        int span = getSpanCount();        for (int i = 0; i < count; i++) {            measureScrapChild(recycler, i,                    View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),                    View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),                    mMeasuredDimension);            if (getOrientation() == HORIZONTAL) {                if (i % span == 0) {                    width = width + mMeasuredDimension[0];                }                if (i == 0) {                    height = mMeasuredDimension[1];                }            } else {                if (i % span == 0) {                    height = height + mMeasuredDimension[1];                }                if (i == 0) {                    width = mMeasuredDimension[0];                }            }        }        switch (widthMode) {            case View.MeasureSpec.EXACTLY:                width = widthSize;            case View.MeasureSpec.AT_MOST:            case View.MeasureSpec.UNSPECIFIED:        }        switch (heightMode) {            case View.MeasureSpec.EXACTLY:                height = heightSize;            case View.MeasureSpec.AT_MOST:            case View.MeasureSpec.UNSPECIFIED:        }        setMeasuredDimension(width, height);    }    private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec,                                   int heightSpec, int[] measuredDimension) {        if (position < getItemCount()) {            try {                View view = recycler.getViewForPosition(0);//fix 动态添加时报IndexOutOfBoundsException                if (view != null) {                    RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams();                    int childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec,                            getPaddingLeft() + getPaddingRight(), p.width);                    int childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec,                            getPaddingTop() + getPaddingBottom(), p.height);                    view.measure(childWidthSpec, childHeightSpec);                    measuredDimension[0] = view.getMeasuredWidth() + p.leftMargin + p.rightMargin;                    measuredDimension[1] = view.getMeasuredHeight() + p.bottomMargin + p.topMargin;                    recycler.recycleView(view);                }            } catch (Exception e) {                e.printStackTrace();            }        }    }}复制代码

3.ExStaggeredGridLayoutManager的代码如下

public class ExStaggeredGridLayoutManager extends StaggeredGridLayoutManager {    public ExStaggeredGridLayoutManager(int spanCount, int orientation) {        super(spanCount, orientation);    }    // 尺寸的数组,[0]是宽,[1]是高    private int[] measuredDimension = new int[2];    // 用来比较同行/列那个item罪宽/高    private int[] dimension;    @Override    public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state, int widthSpec, int heightSpec) {        // 宽的mode+size        final int widthMode = View.MeasureSpec.getMode(widthSpec);        final int widthSize = View.MeasureSpec.getSize(widthSpec);        // 高的mode + size        final int heightMode = View.MeasureSpec.getMode(heightSpec);        final int heightSize = View.MeasureSpec.getSize(heightSpec);        // 自身宽高的初始值        int width = 0;        int height = 0;        // item的数目        int count = getItemCount();        // item的列数        int span = getSpanCount();        // 根据行数或列数来创建数组        dimension = new int[span];        for (int i = 0; i < count; i++) {            measureScrapChild(recycler, i,                    View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),                    View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED), measuredDimension);            // 如果是竖直的列表,计算item的高,否则计算宽度            //Log.d("LISTENER", "position " + i + " height = " + measuredDimension[1]);            if (getOrientation() == VERTICAL) {                dimension[findMinIndex(dimension)] += measuredDimension[1];            } else {                dimension[findMinIndex(dimension)] += measuredDimension[0];            }        }        if (getOrientation() == VERTICAL) {            height = findMax(dimension);        } else {            width = findMax(dimension);        }        switch (widthMode) {            // 当控件宽是match_parent时,宽度就是父控件的宽度            case View.MeasureSpec.EXACTLY:                width = widthSize;                break;            case View.MeasureSpec.AT_MOST:                break;            case View.MeasureSpec.UNSPECIFIED:                break;        }        switch (heightMode) {            // 当控件高是match_parent时,高度就是父控件的高度            case View.MeasureSpec.EXACTLY:                height = heightSize;                break;            case View.MeasureSpec.AT_MOST:                break;            case View.MeasureSpec.UNSPECIFIED:                break;        }        // 设置测量尺寸        setMeasuredDimension(width, height);    }    private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec,                                   int heightSpec, int[] measuredDimension) {        // 挨个遍历所有item        if (position < getItemCount()) {            try {                View view = recycler.getViewForPosition(position);//fix 动态添加时报IndexOutOfBoundsException                if (view != null) {                    RecyclerView.LayoutParams lp = (RecyclerView.LayoutParams) view.getLayoutParams();                    int childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec, getPaddingLeft() + getPaddingRight(), lp.width);                    int childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec, getPaddingTop() + getPaddingBottom(), lp.height);                    // 子view进行测量,然后可以通过getMeasuredWidth()获得测量的宽,高类似                    view.measure(childWidthSpec, childHeightSpec);                    // 将item的宽高放入数组中                    measuredDimension[0] = view.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;                    measuredDimension[1] = view.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;                    recycler.recycleView(view);                }            } catch (Exception e) {                e.printStackTrace();            }        }    }    private int findMax(int[] array) {        int max = array[0];        for (int value : array) {            if (value > max) {                max = value;            }        }        return max;    }    /**     * 得到最数组中最小元素的下标     *     * @param array     * @return     */    private int findMinIndex(int[] array) {        int index = 0;        int min = array[0];        for (int i = 0; i < array.length; i++) {            if (array[i] < min) {                min = array[i];                index = i;            }        }        return index;    }}复制代码

RecylerView滚动到底部

好多开发只知道一下的方法

第一种方法:

mRecycleView.smoothScrollBy(distance,duration);复制代码

第二种方法:

mRecycleView.smoothScrollOffset(offset);复制代码

第三种方法:

mRecycleView.smoothToPosition(index);复制代码

第四种方法:

mRecycleView.scrollToPosition(index);复制代码

等等,以上是能达到效果的,但是如果item过长的话,用上面的方法就无法达到效果,我盟可以尝试一下的方法

//messageListView.computeVerticalScrollRange()整个控件的高度messageListView.scrollBy(0, messageListView.computeVerticalScrollRange());复制代码

判断是否滚动到底部的方法

1.第一种

RecyclerView.canScrollVertically(1)的值表示是否能向上滚动,false表示已经滚动到底部RecyclerView.canScrollVertically(-1)的值表示是否能向下滚动,false表示已经滚动到顶部复制代码

2.第二种

public static boolean isSlideToBottom(RecyclerView recyclerView) {       if (recyclerView == null) return false;    if (recyclerView.computeVerticalScrollExtent() + recyclerView.computeVerticalScrollOffset()         >= recyclerView.computeVerticalScrollRange())        return true;     return false;}复制代码

这样就很清晰明了,computeVerticalScrollExtent()是当前屏幕显示的区域高度,computeVerticalScrollOffset() 是当前屏幕之前滑过的距离,而computeVerticalScrollRange()是整个View控件的高度。

这些基础的属性好多人并不知道,使用好上面的这些属性,能让你对recylerview做许多的操作。

RecylerView添加头和尾

这里就直接上代码了

public class HeaderAndFooterWrapper extends RecyclerView.Adapter
{ private static final int BASE_ITEM_TYPE_HEADER = 0x10; private static final int BASE_ITEM_TYPE_FOOTER = 0x20; private SparseArrayCompat
mHeaderViews = new SparseArrayCompat<>(); private SparseArrayCompat
mFootViews = new SparseArrayCompat<>(); private RecyclerView.Adapter mInnerAdapter; public HeaderAndFooterWrapper(RecyclerView.Adapter adapter) { mInnerAdapter = adapter; } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { if (mHeaderViews.get(viewType) != null) { ViewHolder holder = ViewHolder.createViewHolder(parent.getContext(), mHeaderViews.get(viewType)); return holder; } else if (mFootViews.get(viewType) != null) { ViewHolder holder = ViewHolder.createViewHolder(parent.getContext(), mFootViews.get(viewType)); return holder; } return mInnerAdapter.onCreateViewHolder(parent, viewType); } @Override public int getItemViewType(int position) { if (isHeaderViewPos(position)) { return mHeaderViews.keyAt(position); } else if (isFooterViewPos(position)) { return mFootViews.keyAt(position - getHeadersCount() - getRealItemCount()); } return mInnerAdapter.getItemViewType(position - getHeadersCount()); } private int getRealItemCount() { return mInnerAdapter.getItemCount(); } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { if (isHeaderViewPos(position)) { return; } if (isFooterViewPos(position)) { return; } mInnerAdapter.onBindViewHolder(holder, position - getHeadersCount()); } @Override public int getItemCount() { return getHeadersCount() + getFootersCount() + getRealItemCount(); } @Override public void onAttachedToRecyclerView(RecyclerView recyclerView) { mInnerAdapter.onAttachedToRecyclerView(recyclerView); RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager(); if (layoutManager instanceof GridLayoutManager) { final GridLayoutManager gridLayoutManager = (GridLayoutManager) layoutManager; final GridLayoutManager.SpanSizeLookup spanSizeLookup = gridLayoutManager.getSpanSizeLookup(); gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { @Override public int getSpanSize(int position) { int viewType = getItemViewType(position); if (mHeaderViews.get(viewType) != null) { return gridLayoutManager.getSpanCount(); } else if (mFootViews.get(viewType) != null) { return gridLayoutManager.getSpanCount(); } if (spanSizeLookup != null) return spanSizeLookup.getSpanSize(position); return 1; } }); gridLayoutManager.setSpanCount(gridLayoutManager.getSpanCount()); } } @Override public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) { mInnerAdapter.onViewAttachedToWindow(holder); int position = holder.getLayoutPosition(); if (isHeaderViewPos(position) || isFooterViewPos(position)) { ViewGroup.LayoutParams lp = holder.itemView.getLayoutParams(); if (lp != null && lp instanceof StaggeredGridLayoutManager.LayoutParams) { StaggeredGridLayoutManager.LayoutParams p = (StaggeredGridLayoutManager.LayoutParams) lp; p.setFullSpan(true); } } } private boolean isHeaderViewPos(int position) { return position < getHeadersCount(); } private boolean isFooterViewPos(int position) { return position >= getHeadersCount() + getRealItemCount(); } public void addHeaderView(View view) { mHeaderViews.put(mHeaderViews.size() + BASE_ITEM_TYPE_HEADER, view); } public void addFootView(View view) { mFootViews.put(mFootViews.size() + BASE_ITEM_TYPE_FOOTER, view); } public int getHeadersCount() { return mHeaderViews.size(); } public int getFootersCount() { return mFootViews.size(); }}复制代码

使用方法

HeaderAndFooterWrapper footerWrapper = new HeaderAndFooterWrapper(你自己的dadapter);footerWrapper.addFootView(footview);footerWrapper.addHeaderView(Headerview);复制代码

要屏蔽notifyItemChanged方法产生的动画,可使用以下方法:

((SimpleItemAnimator)mUserListView.getItemAnimator()).setSupportsChangeAnimations(false);  复制代码

转载地址:http://hvjpo.baihongyu.com/

你可能感兴趣的文章
2013年度第一期测试沙龙 PPT下载
查看>>
我的Java后端书架 (2016年暮春3.0版)
查看>>
两行代码搞定UITableView无数据无网络显示-b
查看>>
Microsoft Speech SDK开发包 使用
查看>>
Android应用开发基础篇(2)-----Notification(状态栏通知)
查看>>
10 款非常棒的CSS代码格式化工具推荐
查看>>
SQL Server 临时表的删除
查看>>
程序8
查看>>
【原】WebRebuild深圳站的一点感悟
查看>>
QT Basic---Widgets<1>
查看>>
Android开发10.3:UI组件GridView网格视图
查看>>
Power BI的一些视频演示资源
查看>>
TBluetoothLEDevice.UpdateOnReconnect
查看>>
QtTableView 简介
查看>>
Linux系统上安装软件(ftp服务器)
查看>>
[iOS] App引导页的简单实现 (Swift 2)
查看>>
MHA 代码解析(online swtich+master is alive 模式)
查看>>
利用openssl进行RSA加密解密
查看>>
盒模型--边界
查看>>
14.使用通配符
查看>>