还在用ListView?

Posted cym492224103

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了还在用ListView?相关的知识,希望对你有一定的参考价值。

还在用Lisview?RecyclerView都已经出来一年多了!

想必大家多或多或少的接触过或者了解过RecyclerView,为什么没有用起来,原因大概如下?

  • ListView我用的挺好的,为什么要换RecyclerView?
  • ListView稳定,熟悉,还知道很多开源库,特别的好用!
  • RecyclerView不能添加头部,ListView能!

RecyclerView

RecyclerView最大的优势就是灵活,RecyclerView只需改变一行代码就可以变化多种不同的布局显示排版,这一点对于开发者是非常方便的!

还有RecyclerView.Adapter,比BaseAdapter做了更好的封装,把BaseAdapter的getView方法拆分成onCreateViewHolder方法和onBindViewHolder方法,强制需要创建ViewHolder,这样的好处就是避免了初学者写性能不佳的代码

在Andorid 5.0出来不久,我就已经写过RecyclerView的简单介绍以及基本使用,不了解的可以看看ListView升级版RecyclerView,了解过的同学可以忽略,并往下看。

在实战中我们会遇到什么问题?

get到下面的技能就能够在使用RcyclerView的大路上畅通无阻了!

  • 添加分割线
  • 添加点按效果
  • 列表动画
  • 改变某个数据保持当前位置
  • 添加头部尾部
  • 列表分组
  • 各种效果集成Demo
  • 更灵活的RecyclerView

添加分割线

//通过以下方法添加分割线
mRecyclerView.addItemDecoration(new DividerItemDecoration(this,
DividerItemDecoration.VERTICAL_LIST));

需要RecyclerView.ItemDecoration这个抽象类实现一些方法
(后续有更偷懒的方法)

/**
 * This class is from the v7 samples of the android SDK. It's not by me!
 * <p/>
 * See the license above for details.
 */
public class DividerItemDecoration extends RecyclerView.ItemDecoration 

    private static final int[] ATTRS = new int[]
            android.R.attr.listDivider
    ;

    public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;

    public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;

    private Drawable mDivider;

    private int mOrientation;

    public DividerItemDecoration(Context context, int orientation) 
        final TypedArray a = context.obtainStyledAttributes(ATTRS);
        mDivider = a.getDrawable(0);
        a.recycle();
        setOrientation(orientation);
    

    public void setOrientation(int orientation) 
        if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) 
            throw new IllegalArgumentException("invalid orientation");
        
        mOrientation = orientation;
    

    @Override
    public void onDraw(Canvas c, RecyclerView parent) 
        Log.v("recyclerview - itemdecoration", "onDraw()");

        if (mOrientation == VERTICAL_LIST) 
            drawVertical(c, parent);
         else 
            drawHorizontal(c, parent);
        

    


    public void drawVertical(Canvas c, RecyclerView parent) 
        final int left = parent.getPaddingLeft();
        final int right = parent.getWidth() - parent.getPaddingRight();

        final int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++) 
            final View child = parent.getChildAt(i);
            android.support.v7.widget.RecyclerView v = new android.support.v7.widget.RecyclerView(parent.getContext());
            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
                    .getLayoutParams();
            final int top = child.getBottom() + params.bottomMargin;
            final int bottom = top + mDivider.getIntrinsicHeight();
            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        
    

    public void drawHorizontal(Canvas c, RecyclerView parent) 
        final int top = parent.getPaddingTop();
        final int bottom = parent.getHeight() - parent.getPaddingBottom();

        final int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++) 
            final View child = parent.getChildAt(i);
            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
                    .getLayoutParams();
            final int left = child.getRight() + params.rightMargin;
            final int right = left + mDivider.getIntrinsicHeight();
            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        
    

    @Override
    public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) 
        if (mOrientation == VERTICAL_LIST) 
            outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
         else 
            outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
        
    

看到这里应该有同学吐槽了,就添加一根线至于吗?还需要重写方法,ListView可是只需要简单配置一下就好了。

   android:divider="@color/grey"
   android:dividerHeight="5dp"

为此我也感觉太麻烦,于是我想了一个办法:
直接在item_view里面底部自己添加一根线布局,这样就无需重写了,并且这样还有个好处就是,如果细心的同学会发现,添加分割线,最后一个item下面不会有分割线,显然当数据量不足一个屏幕的时候显得很突兀,但是在item_view下面添加一个线的布局则不会出现这种情况

添加点按效果

RecyclerView直接在item_view里面配置即可

动画

一个好的用户体验就是要有操作动画的过渡,而不是生硬的刷新列表。

推荐一个RecyclerView的动画库(recyclerview-animators

RecyclerView自带添加、删除动画,而ListView则需添加额外的代码才能实现。

  • 删除调用RecyclerView的adapter的notifyItemRemoved
  • 添加调用RecyclerView的adapter的notifyItemInserted

说到adapter我们就来说说RecyclerView.Adapter和BaseAdapter相比,额外提供了一下这些方法:

// 数据发生了改变,那调用这个方法,传入改变对象的位置。
public final void notifyItemChanged(int position);

// 可以刷新从positionStart开始itemCount数量的item了
public final void notifyItemRangeChanged(int positionStart, int itemCount);

// 添加,传入对象的位置。
public final void notifyItemInserted(int position);

// 删除,传入对象的位置。
public final void notifyItemRemoved(int position);

// 对象从fromPosition移动到toPosition
 public final void notifyItemMoved(int fromPosition, int toPosition); 

//批量添加 
public final void notifyItemRangeInserted(int positionStart, int itemCount);

//批量删除
public final void notifyItemRangeRemoved(int positionStart, int itemCount);

改变列表某个布局状态且保持当前位置

这种需求是普遍存在的,就是改变列表某一个item数据,然后刷新列表,如果是ListView刷新后则会回到最顶部,而RecyclerView同样的操作但是原来滑动的位置不变。

各种解决方案的RecyclerView的Adapter

BaseRecyclerViewAdapterHelper

更灵活的RecyclerView

twoway-view
封装了RecyclerView常用方法,如click等等,以及支持了更多不同的布局,使得RecyclerView使用起来更简单!

造起来!小伙伴们!

以上是关于还在用ListView?的主要内容,如果未能解决你的问题,请参考以下文章

RecyclerView.Adapter优化了吗?

可拖拽listview基本使用技巧(DragSortListView)

可拖拽listview基本使用技巧(DragSortListView)

Android listview 错误:您的内容必须有一个 ID 属性为“android.R.id.list”的 ListView,但我有两个 listview [重复]

请教ListView中列表项用的android.R.layout.simple

Android ListView 更新颜色