• Metail Design之RecyclerView


    1.RecyclerView简单设置:

     1 private void initRecyclerView() {
     2         mList = new ArrayList<>();
     3         for (int i = 0; i < 60; i++) {
     4             mList.add(String.format(getString(R.string.lesson),(1+i)+""));
     5         }
     6         setLayoutManget(switchId);
     7         mAdapter = new MainRecyclerAdapter(mList);
     8         mRy.setAdapter(mAdapter);
     9         mRy.setItemAnimator(new DefaultItemAnimator());
    10         mAdapter.setItemClickListener(new MainRecyclerAdapter.ItemClickListener() {
    11             @Override
    12             public void click(View view, int position, String text) {
    13                 Toast.makeText(MainActivity.this, "点击--" + text, Toast.LENGTH_SHORT).show();
    14                 goActivity(position);
    15             }
    16         });
    17     }

     

    rv是高度解耦,可以为他设置LayoutManger,ItemAnimotor,Adaper,Deliver分割线等.

     

    2.设置条目添加,移除时可以局部刷新,尽可能优化性能:

     

     3.要使用StaggeredGridLayoutManager

     1).这里模拟给每个Item动态分配高度,记得使用

    View view =LayoutInflater.from(parent.getContext()).inflate(android.R.layout.simple_list_item_1,parent,false);
    这种方式经过看源码发现没有人为的添加到父类的ViewGroup,而是交给RecyclerView自己处理

     

    1 @Override
    2     public MainViewHold onCreateViewHolder(ViewGroup parent, int viewType) {
    3 //        View view = View.inflate(parent.getContext(), android.R.layout.simple_list_item_1, null);//没有添加进parent
    4 //        View view = View.inflate(parent.getContext(), android.R.layout.simple_list_item_1, parent);//双重parent
    5         View view =LayoutInflater.from(parent.getContext()).inflate(android.R.layout.simple_list_item_1,parent,false);
    6         return new MainViewHold(view);
    7     }

     

     

     2).上面注释两种方式有问题,第一种getLayoutParams参数为空,第二种resoure(android.R.layout.simple_list_item_1)有两个parent,因为查看源码发现root.add(view,params)添加了一次,recyclerview自己又会把item添加进入它之中.

     

     

      3).上面两种方法最终调用的是这个方法,对应的还是第三种方法

     

     4).上一张瀑布流的图:

     

     

     3.RecyclerView设置条目点击事件:

     方式一:采用holder.getAdaperPosition()来获得当前条目的位置信息,这种可以实时获取position信息,包括addItem和remove条目,最好应用于数据集变化的情况.

     
     
     方式二:采用自定义OnClickListener,构造方法时把position传进去,这样position在单独开辟的堆栈里,可以长久存储,最好应用于数据集不发生改变的情况(经过测试,addItem和removeItem后,postion不会实时变化)

     

     监听器: 

     

     

      应用于RecyclerView:

     

     

     4.RecycleView分割线:

     1).初识RecyclerView.ItemDecoration中的 getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) 

    它是先于onDraw()方法执行的,调用此方法首先会获得条目之间的间隔宽度,Rect的矩形区域.获得条目的偏移量,所有条目都会调用一次该方法.
    2)onDraw方法是真正绘制Divider时的方法
     
    这里我们先来个简单的,绘制LinearLayoutManager的分割线
    首先,可以拿系统的Divider(方便),构造方法传入布局方向

     

     我们可以给divider一个set方法,来动态设置

     

     设置所有item的偏移:

     

     divider绘制的位置:(根据上面)

    onDraw()真正的绘制: 

    计算边距:

     

     这里以绘制垂直方法为例,也就是长形矩形为例讲解:

     

    这里有一点非常需要注意:

     

    就是parent.getChildCount()方法是获得当前屏幕一屏的ChildView 数量:

    (1).这里绘制的时候child的param要用RecyclerView.LayoutParam的,因为它继承与MaragLayout可以拿到Margin边距

    (2).child如果有平移动画这里还要添加动画的距离:Math.round(ViewCompat.getTranslationY(child));
    (3).这里记得开始和结束用c.save()和c.restore()来保存画板
    (4).这里以child.getBottom)---item5为例说说,获得的值在屏幕上指的是哪里:

     

    drawHorazotion()也是同样的原理,再讲讲我们自定义的ItemDecoration怎么应用于recyclerview:

     

    这里说说绘制GridView布局分割线:
    1).关于偏移量这里就要考虑最后一行和最后一列:

     

     2).这里说说如何判断最后一行最后一列:

     

     3).判断最后一列:

     

     5.RecyclerView像ListView那样添加头和尾布局:

     1).通过看ListView添加头尾的源码,它其中采用了代理模式,添加头尾的时候重新new了一个WrapHeaderListViewAdapter,里面分别用两个List<View> 来存放添加进来的头和尾,getView,getCount等方法还是使用原来adapter,或者加以修饰还是交给子类去实现,所以我们也来模仿这样:

    先自己定义一个wrapHeadRecyclerAdapter:

     

     2).模仿着listview重写几个重要的方法:
    这里获得数量是把头和尾的也添加进去了

     

    3).通过getItemViewType来区分当前条目是什么类型(头,尾,正常条目)

     

     记得这里的mAdapter.getItemViewType(adjPosition)返回的是原来的正常Item,位置也是从0开始的
    4).onCreateViewHolder()方法里的头尾位置new出来的hold只要是配合框架使用,其实并没什么用,viewhold的目的主要是目的是复用,而头尾直接是addView就添加进来了,不存在大量复用情况

     

    5).onBindViewHolder

     

     6).使用还是跟平常rv一样使用,wrapheadrecyclerview使我们偷偷做的

     

     效果图:

     

     6.RecyclerView添加拖拽和侧滑:

     1).添加拖拽和侧滑需要用到一个ItemTouchHelper,以及ItemTouchHelper.Callback:

    1 getMovementFlags()方法

     

     onMove()方法

    onSwiped()方法

     isLongPressDragEnabled()方法:

    onSelectedChanged()方法:

     clearView()方法:

    onChildDraw()方法:

     2).两个不同的类之间通信,采用Interface接口做桥梁,很好的降低耦合:

     

    public QQAdapter(List<QQMessage> list, StartDragListener startDragListener) {
            this.list = list;
            mStartDragListener =startDragListener;
        }
    
    holder.iv_logo.setOnTouchListener(new View.OnTouchListener() {
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    if (event.getAction()==MotionEvent.ACTION_DOWN){
                        mStartDragListener.onStartDrag(holder);
                    }
                    return false;
                }
            });

    例如:这里QQAdapter相与外界通信,通过StartDragListener 接口,把图标iv_logo按下移动时,让ItemTouchHelper调用startDrag()方法

    /**
     * 监听Viewhold.icon按下上下拖拽的监听
     */
    public interface StartDragListener {
        void onStartDrag(RecyclerView.ViewHolder viewHolder);
    }

     在Activity中这样实现:

     

     3).ItemTouchHelper.CallBack需要把他的拖拽和侧滑回调给QQAdapter,来改变数据集的变化和视图的变化,这里通信就只有CallBack与QQAdapter,所以可以通过ItemTouchMoveListener接口来回调出去,QQAdapter来实现接口,分别进行数据的更新和试图的变化:
    MyCallBack中:

     

     QQAdaper中:

     

     都是调用的notify方法

     

    效果图如下:

     

     

     注意:

     如图:

     

  • 相关阅读:
    Kaka's Matrix Travels
    Cable TV Network
    LightOJ 1137
    SPOJ AMR11E Distinct Primes 基础数论
    HDU 5533Dancing Stars on Me 基础几何
    POJ 1014 / HDU 1059 Dividing 多重背包+二进制分解
    vijos 1180 选课 树形DP
    vijos 1313 金明的预算方案 树形DP
    LightOJ 1062
    vijos 1464 积木游戏 DP
  • 原文地址:https://www.cnblogs.com/jeffery336699/p/9295360.html
Copyright © 2020-2023  润新知