RecyclerView从入门到深入

作者: minminaya | 来源:发表于2017-03-10 00:46 被阅读4256次

    Android学习整理 - 系列


    目录:

    • 一 RecyclerView简介
    • 二 RecyclerView为什么会出现
    • 三 基本使用方法
    • 四 高级用法
      1. Scrollbars

      2. Item间分割线

      3. Item显示方式

      4. 自定义LayoutManager

      5. RecyclerView的点击事件

      6. 高级效果 波纹点击

      7. 添加 删除时动画

      8. 与某些View结合使用

      9. 滑动监听addOnScrollListener 可实现下拉刷新等

      10. ItemTouchHelper实现item删除,互相拉动

    • 五 RecyclerView多种布局显示
    • 六 注意(未全)
    • 七 开源库XRecyclerView

    一 RecyclerView简介

    • 官方对RecycleView的描述是在有限的窗口中大量显示数据集
      灵活view,类似ListView,GridView

    • RecyclerView在support.V7包里,个人觉得Google是为了用它来替代ListView

    • 可以实现
      1.ListView的功能(包括横向)
      2.GridView的功能
      3.横向ScrollView
      4.瀑布流
      5.方便添加animation(item的add remove时)


    二 RecyclerView为什么会出现

    优点

    • 高度解耦,随意定制。它提供的LayoutManager,ItemDecoration,ItemAnimator可以让开发者自定义奇特的效果

    • RecyclerView封装了ViewHolder

    • 通过设置LayoutManager可以设计Item的显示的方式,横,竖甚至瀑布流

    • 通过ItemDecoration可以控制Item间的间隔条,还有自定义间隔条

    • 通过ItemAnimator可以控制Item增删的动画

    缺点

    • 短按长按点击事件需要自己来实现(WTF)

    虽然有缺点,但是几乎忽略不计,RecyclerView的随意定制,其自带的ViewHolder不再像ListView中ViewHolder作为View出现,其“Recycle”的强大,一行代码切换布局样式的优点使其势必取代ListView

    三 基本使用方法

    当前IDE:Android Studio 2.2正式版
    jdk1.8.102
    compileSdkVersion 25
    buildToolsVersion "25.0.2"

    gradle导包

    compile 'com.android.support:recyclerview-v7:25.2.0'
    

    然后layout布局文件中加入

     <android.support.v7.widget.RecyclerView
            android:id="@+id/activity_main_recycle_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
    

    code中需要

    //设置布局管理器,必须
    mRecyclerView.setLayoutManager(layout);
    //设置RecycleView的Adapter,必须
    mRecyclerView.setAdapter(adapter)
    //设置分割线,非必须
    mRecyclerView.addItemDecoration(ItemDecoration);
    //设置item的增删动画,非必须
    mRecyclerView.setItemAnimator(animator);
    

    现在先最简单创建一个列表

    新建Item的布局recycleview_item,以TextView为根节点

    <TextView xmlns:android="http://schemas.android.com/apk/res/android"
              android:id="@+id/recycle_textview"
              android:layout_width="match_parent"
              android:layout_height="50dp"
              android:gravity="center"
              android:textSize="20sp"/>
    

    新建一个RecyclerView.Adapter适配器TestRecycleViewAdapter

    public class TestRecycleViewAdapter extends RecyclerView.Adapter<TestRecycleViewAdapter.ViewHolderA> {
        private Context mContext;
        private List<String> mList;
    
        public TestRecycleViewAdapter(Context context, List<String> list) {
            mContext = context;
            mList = list;
        }
    
        @Override
        public ViewHolderA onCreateViewHolder(ViewGroup parent, int viewType) {
            //此处动态加载ViewHolder的布局文件并返回holder
            View view = LayoutInflater.from(mContext).inflate(R.layout.recycleview_item, parent, false);
            ViewHolderA holderA = new ViewHolderA(view);
            return holderA;
        }
    
        @Override
        public void onBindViewHolder(ViewHolderA holder, int position) {
            //此处设置Item中view的数据
            holder.mTextView.setText(mList.get(position));
        }
    
        @Override
        public int getItemCount() {
            //生成的item的数量
            return mList.size();
        }
    
        //Item的ViewHolder以及item内部布局控件的id绑定
        class ViewHolderA extends RecyclerView.ViewHolder{
    
            TextView mTextView;
            public ViewHolderA(View itemView) {
                super(itemView);
                mTextView = (TextView) itemView.findViewById(R.id.recycle_textview);
            }
        }
    }
    

    用Android Studio生成Adapter结构技巧

    1. 先新建一个类TestRecycleViewAdapter
    2. 继承自RecyclerView.Adapter<这里填ViewHolder名字的>,现在出现红线,先不管它
    3. 然后在TestRecycleViewAdapter 内部写内部类ViewHolderA 继承自 RecyclerView.ViewHolder,这个时候会自动生成构造函数
    4. 接着将ViewHolder的名字ViewHolderA填入第2步粗体处,注意这里是内部类所以正确填入是TestRecycleViewAdapter.ViewHolderA
    5. 接着点红线,然后IDE会自己生成所需的3个方法

    Activity中代码是这样

    public class MainActivity extends AppCompatActivity {
        private List<String> list;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            RecyclerView mRecyclerView = (RecyclerView) findViewById(R.id.activity_main_recycle_view);
            mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
            initData();
            //实例化并传输数据给adapter
            TestRecycleViewAdapter adapter = new TestRecycleViewAdapter(getApplicationContext(), list);
            mRecyclerView.setAdapter(adapter);
        }
    
        /**
         *  添加数据
         * */
        private void initData() {
            list = new ArrayList<>();
            for (int i = 0; i < 50; i++) {
                list.add("item" + i);
            }
        }
    }
    

    这样子一个最基本的RecyclerView就写好了,效果图

    最基本的RecycleView

    可以看到默认没有Scrollbars,没有item之间的间隔线,没有item点击效果,实际上这些我们需要自定义(虽然有点麻烦)


    四 高级用法

    1 Scrollbars

    • 只需要在RecycleView根节点加上
      android:scrollbars="vertical"
      默认为none,还有横向horizontal样式的

    2 Item间分割线

    • 可以给item设置margin,不过感觉好丑
      只要在item的layout里加上
              android:layout_marginTop="3dp"//只需要这一行
              android:background="#cf1616"//显示成红色比较明显
    
    android:layout_marginTop="3dp
    • 另外就是高大上的ItemDecoration了,直接在code中加上
     mRecyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));
    
    这里的context要注意用Activity的Context,假如用了Application的Context会显示默认的样式,谢谢@且听风吟9527的提醒 context使用场景图

    数字1:启动Activity在这些类中是可以的,但是需要创建一个新的task,一般情况不推荐;
    数字2:在这些类中去layout inflate是合法的,但是会使用系统默认的主题样式,如果你自定义了某些样式可能不会被使用;
    数字3:在Receiver为null时允许,在4.2或以上的版本中,用于获取黏性广播的当前值。(可以无视);
    ContentProvider、BroadcastReceiver之所以在上述表格中,是因为在其内部方法中都有一个context用于使用。

    2.png

    但是我们不能仅限于此,
    默认实现类DividerItemDecoration类中源代码部分如下

    
    public class DividerItemDecoration extends RecyclerView.ItemDecoration {
        public static final int HORIZONTAL = LinearLayout.HORIZONTAL;
        public static final int VERTICAL = LinearLayout.VERTICAL;
        //关键在这里,看到有个属性定义成了listDivider 
        private static final int[] ATTRS = new int[]{ android.R.attr.listDivider };
    
        .......
    
    
    public DividerItemDecoration(Context context, int orientation) {
            //这里调用了属性值listDivider
            final TypedArray a = context.obtainStyledAttributes(ATTRS);
            mDivider = a.getDrawable(0);
            a.recycle();
            setOrientation(orientation);
        }
    
        ........
    

    所以,自定义间隔线步骤如下:

    在Style文件里加上name="android:listDivider"的item
    <item name="android:listDivider">@drawable/divider_backgroud</item>
    

    书写divider_bg.xml文件,shape文件为渐变xml

    <shape xmlns:android="http://schemas.android.com/apk/res/android"
        android:shape="rectangle">
        <gradient
            android:centerColor="#b3b35f"
            android:endColor="#515187"
            android:startColor="#b34747"
            android:type="linear" />
        <size android:height="5dp"/>
    </shape>
    

    这样一个自定义间隔线样式就好了

    自定义间隔线

    网络与瀑布流的间隔线个人水平暂时弄不好.......(搁置中、、、、QAQ)


    3 Item显示方式

    GridLayout

    只需要将

    mRecyclerView.setLayoutManager(layoutManager);
    

    layoutManager设为

    mRecyclerView.setLayoutManager(new GridLayoutManager(this, 5));
    

    就可以实现5列的网格布局

    11.png

    我们看到网格样式看起来像流式的List,那是因为没有左右间隔线的问题(其实是水平不行),
    左右间隔线弄不出来QAQ,现在只能在recycleview_item.xml里面增加属性做一个假的间隔线QAQ

    android:layout_marginStart="1dp"
    
    2.png

    瀑布流

    同上

    mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL));
    
    3.png

    感觉上和网格布局没啥差别,因为这上面的item我们使用了固定的高度,我们可以在适配器的onBindViewHolder方法中随机设置item高度

    • 先在adapter的里声明
    private List<Integer> mHeight;
    
    • 在构造方法里随机生成高度值
    mHeight = new ArrayList<Integer>();
            for (int i = 0; i < mList.size(); i++) {
                mHeight.add((int) (80 + Math.random() * 300));
            }
    
    • 接着在onBindViewHolder方法里
    ViewGroup.LayoutParams lp = holder.mTextView.getLayoutParams();
     lp.height = mHeight.get(position);
    
    瀑布流

    类似的,不止有竖屏的效果,横屏的只要修改
    mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.HORIZONTAL));
    就可以快速实现类似的效果


    4 自定义LayoutManager

    请参考
    RecyclerView自定义LayoutManager,打造不规则布局

    另外
    对LayoutManager的分析,创建一个 RecyclerView LayoutManager


    5 RecycleView的点击事件

    RecycleView并没有提供类似setOnItemClickListener()这样的注册监听器方法,而是需要我们自己给子项view注册响应事件

    我们只需要在Adapter的onBindViewHolder方法里添加

    public void onBindViewHolder(ViewHolderA holder, final int position) {
            .....
             .....
            holder.mTextView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Toast.makeText(mContext, "item"+position,Toast.LENGTH_SHORT).show();
                }
            });
    
           .....
        }
    

    这样就轻松实现了TextView的点击事件,同理,长按的类似如此

    点击事件

    RecycleView的强大之处也在这里,就算是ViewHolder里的View多层嵌套了几个view都可以轻松的实现点击事件


    6 高级效果 波纹点击

    实现方法,在item布局文件根节点加上

    android:foreground="?android:attr/selectableItemBackground"
    
    波纹点击效果

    7 添加 删除时动画

    在adapter里新添加方法

    public void addData(int position){
            mList.add(position, "新增" + position);
          //通知适配器item内容插入
            notifyItemInserted(position);
        }
    public void RemoveData(int position){
            mList.remove(position);
           //通知适配器item内容删除
            notifyItemRemoved(position);
        }
    

    然后在Activity里添加action栏菜单

    @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            getMenuInflater().inflate(R.menu.main, menu);
            return super.onCreateOptionsMenu(menu);
        }
    
        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            switch (item.getItemId()){
                case R.id.menu_add:
                adapter.addData(1);
                break;
                case R.id.menu_remove:
                    adapter.RemoveData(1);
                break;
            }
            return true;
        }
    

    menu文件

    <menu xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:app="http://schemas.android.com/apk/res-auto">
    
        <item
            android:id="@+id/menu_remove"
            android:icon="@android:drawable/alert_light_frame"
            android:title="remove"
            app:showAsAction="ifRoom"/>
        <item
            android:id="@+id/menu_add"
            android:icon="@android:drawable/ic_input_add"
            android:orderInCategory="100"
            android:title="add"
            app:showAsAction="ifRoom"/>
    </menu>
    

    然后,这个是默认的动画,现在有很多开源库,具体可以Google

    mRecyclerView.setItemAnimator(new DefaultItemAnimator());
    
    add remove animator

    8 与某些View结合使用

    • 可以被SwipeRefreshLayout实现Android原生下拉刷新,也可以实现第三方下拉刷新
    • item可以使用CardView,恩,超漂亮

    9 滑动监听addOnScrollListener 可实现下拉刷新等

    实现这个借口的俩个方法

    • onScrollStateChanged
    • onScrolled
    mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
                //标记当前是否向最后一项滑动
                boolean isSlidingToLast = false;
    
                @Override
                public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                    super.onScrollStateChanged(recyclerView, newState);
                    //获取当前的LayoutManager
                    LinearLayoutManager manager = (LinearLayoutManager) recyclerView.getLayoutManager();
                    //当不滚动的时候
                    if (newState == RecyclerView.SCROLL_STATE_IDLE) {
                        //得到最后一个完全显示的item的position
                        int lastViusalItem = manager.findLastCompletelyVisibleItemPosition();
                        //总的ITemPosition
                        int totalItemCount = manager.getItemCount();
                        //当前是否向下滑,是否滚动到LastItem
                        if (lastViusalItem == (totalItemCount - 1) && isSlidingToLast) {
                            // 这里就是下拉加载更多功能的逻辑
                            //往item的List里添加数据,并通知适配器更新
                            adapter.addListData(lastViusalItem);
    
                        }
                    }
                }
    
                @Override
                public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                    super.onScrolled(recyclerView, dx, dy);
                    //如果dy>0则当前向下滑state
                    if (dy > 0) {
                        isSlidingToLast = true;
                    } else if (dy < 0) {
                        isSlidingToLast = false;
                    }
                }
            });
    

    adapter里添加

    public void addListData(int position){
            for (int i = 0; i <6; i++) {
                mList.add("底部添加" + i);
            }
            //通知适配器item内容删除
            notifyItemChanged(position);
        }
    

    这里的LayoutManager对象manager还可以获取到很多参数,比如

    可以用tm来实现更多逻辑功能

    自动加载

    10 ItemTouchHelper实现item删除,互相拉动

    一个大神写的

    Android实现RecyclerView侧滑删除和长按拖拽-ItemTouchHelper
    ,讲的很清楚,这里不再详解,贴上测试的代码,仅做记录

    在setAdapter后面添加

          ItemTouchHelper.Callback mCallback = new ItemTouchHelper.SimpleCallback(ItemTouchHelper.DOWN|ItemTouchHelper.UP, ItemTouchHelper.RIGHT) {
                @Override
                public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
                    int fromPosition = viewHolder.getAdapterPosition();//得到拖动ViewHolder的position
                    int toPosition = target.getAdapterPosition();//得到目标ViewHolder的position
                    if (fromPosition < toPosition){
    //                向下
                        for (int i = fromPosition; i < toPosition; i++) {
                            Collections.swap(list, i, i+1);
                        }
                    }else {
                        for (int i = fromPosition; i < toPosition; i++) {
                            //                向上
                            Collections.swap(list, i, i-1);
                        }
                    }
                    mTestRecycleViewAdapterMulType.notifyItemMoved(fromPosition, toPosition);
                    //返回true表示执行拖动
                    return true;
                }
    
                @Override
                public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
                    int position = viewHolder.getAdapterPosition();
                    list.remove(position);
                    mTestRecycleViewAdapterMulType.notifyItemRemoved(position);
                }
            };
    
            ItemTouchHelper mItemTouchHelper = new ItemTouchHelper(mCallback);
            mItemTouchHelper.attachToRecyclerView(mRecyclerView);
    
    

    效果

    1.gif

    五 RecycleView多种布局显示

    先看效果

    多布局

    RecycleView.Adapter也提供了getItemViewType方法,此方法和ListView加载多布局一样。

    这里需要注意的是这里的范型不再是自己写的ViewHolder

    public class TestRecycleViewAdapterMulType extends RecyclerView.Adapter<RecyclerView.ViewHolder>
    

    重写adapter的getItemViewType

     public int getItemViewType(int position) {
            if (position == 0) {
                //111代表顶部item
                return 111;
            } else if (position == getItemCount() - 1) {
                //111代表di部item
                return 112;
            }
            //111代表中间item
            return 110;
        }
    

    自定义3个ViewHolder,分别表示top ,bottom 和中间的item布局

    /**
         * 代表顶部item
         */
        class ViewHolderA extends RecyclerView.ViewHolder {
            ImageView mImageViewA;
    
            public ViewHolderA(View itemView) {
                super(itemView);
                mImageViewA = (ImageView) itemView.findViewById(R.id.top_imageview);
            }
        }
    
        /**
         * 代表di部item
         */
        class ViewHolderB extends RecyclerView.ViewHolder {
            ImageView mImageViewB;
    
            public ViewHolderB(View itemView) {
                super(itemView);
                mImageViewB = (ImageView) itemView.findViewById(R.id.bottom_imageview);
            }
        }
    
        /**
         * 代表中间item
         */
        class ViewHolderC extends RecyclerView.ViewHolder {
            TextView mTextView;
    
            public ViewHolderC(View itemView) {
                super(itemView);
                mTextView = (TextView) itemView.findViewById(R.id.recycle_textview);
            }
        }
    

    在onCreateViewHolder方法里

    @Override
        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View view = null;
            RecyclerView.ViewHolder holder = null;
            //此处动态加载ViewHolder的布局文件并返回holder
            switch (viewType) {
                case 111:
                    //111代表顶部item
                    view = LayoutInflater.from(mContext).inflate(R.layout.top, parent, false);
                    holder = new ViewHolderA(view);
                    break;
                case 112:
                    //112代表顶部item
                    view = LayoutInflater.from(mContext).inflate(R.layout.bottom, parent, false);
                    holder = new ViewHolderB(view);
                    break;
                case 110:
                    //112代表中间item
                    view = LayoutInflater.from(mContext).inflate(R.layout.recycleview_item, parent, false);
                    holder = new ViewHolderC(view);
                    break;
            }
            return holder;
        }
    

    最后是onBindViewHolder,在这里分别设置不同布局item数据

    @Override
        public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
    //        //这样写也行
    //        if(holder instanceof ViewHolderA){
    //            ViewHolderA holderA = (ViewHolderA) holder;
    //            holderA.mImageViewA.setImageResource(R.mipmap.ic_launcher);
    //        }else if(holder instanceof ViewHolderB).....
    //        .....
            switch (getItemViewType(position)) {
                case 111:
                    ViewHolderA holderA = (ViewHolderA) holder;
                    holderA.mImageViewA.setImageResource(R.mipmap.ic_launcher);
                    break;
                case 112:
                    ViewHolderB holderB = (ViewHolderB) holder;
                    holderB.mImageViewB.setImageResource(R.mipmap.ic_launcher);
                    break;
                case 110:
                    ViewHolderC holderC = (ViewHolderC) holder;
                    holderC.mTextView.setText(mList.get(position));
                    break;
            }
        }
    
    

    贴一下完整Adapter代码

    **
     * Created by NIWA on 2017/3/9.
     */
    
    public class TestRecycleViewAdapterMulType extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
        private Context mContext;
        private List<String> mList;
    
        public TestRecycleViewAdapterMulType(Context context, List<String> list) {
            mContext = context;
            mList = list;
            
        }
    
        @Override
        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View view = null;
            RecyclerView.ViewHolder holder = null;
            //此处动态加载ViewHolder的布局文件并返回holder
            switch (viewType) {
                case 111:
                    //111代表顶部item
                    view = LayoutInflater.from(mContext).inflate(R.layout.top, parent, false);
                    holder = new ViewHolderA(view);
                    break;
                case 112:
                    //112代表顶部item
                    view = LayoutInflater.from(mContext).inflate(R.layout.bottom, parent, false);
                    holder = new ViewHolderB(view);
                    break;
                case 110:
                    //112代表中间item
                    view = LayoutInflater.from(mContext).inflate(R.layout.recycleview_item, parent, false);
                    holder = new ViewHolderC(view);
                    break;
            }
            return holder;
        }
    
    
        @Override
        public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
    //        //这样写也行
    //        if(holder instanceof ViewHolderA){
    //            ViewHolderA holderA = (ViewHolderA) holder;
    //            holderA.mImageViewA.setImageResource(R.mipmap.ic_launcher);
    //        }else if(holder instanceof ViewHolderB).....
    //        .....
            switch (getItemViewType(position)) {
                case 111:
                    ViewHolderA holderA = (ViewHolderA) holder;
                    holderA.mImageViewA.setImageResource(R.mipmap.ic_launcher);
                    break;
                case 112:
                    ViewHolderB holderB = (ViewHolderB) holder;
                    holderB.mImageViewB.setImageResource(R.mipmap.ic_launcher);
                    break;
                case 110:
                    ViewHolderC holderC = (ViewHolderC) holder;
                    holderC.mTextView.setText(mList.get(position));
                    break;
            }
        }
    
        @Override
        public int getItemCount() {
            //生成的item的数量
            return mList.size();
        }
    
    
        /**
         * 代表顶部item
         */
        class ViewHolderA extends RecyclerView.ViewHolder {
            ImageView mImageViewA;
    
            public ViewHolderA(View itemView) {
                super(itemView);
                mImageViewA = (ImageView) itemView.findViewById(R.id.top_imageview);
            }
        }
    
        /**
         * 代表di部item
         */
        class ViewHolderB extends RecyclerView.ViewHolder {
            ImageView mImageViewB;
    
            public ViewHolderB(View itemView) {
                super(itemView);
                mImageViewB = (ImageView) itemView.findViewById(R.id.bottom_imageview);
            }
        }
    
        /**
         * 代表中间item
         */
        class ViewHolderC extends RecyclerView.ViewHolder {
            TextView mTextView;
    
            public ViewHolderC(View itemView) {
                super(itemView);
                mTextView = (TextView) itemView.findViewById(R.id.recycle_textview);
            }
        }
    
        @Override
        public int getItemViewType(int position) {
            if (position == 0) {
                //111代表顶部item
                return 111;
            } else if (position == getItemCount() - 1) {
                //因为item是从0开始,所以最后一项应该是getItemCount() - 1
                //111代表di部item
                return 112;
            }
            //111代表中间item
            return 110;
        }
    
    }
    

    最后在Activity里

    mTestRecycleViewAdapterMulType = new TestRecycleViewAdapterMulType(getApplicationContext(), list);
            mRecyclerView.setAdapter(mTestRecycleViewAdapterMulType);
    

    heiheihei

    六 注意

      1. 刷新数据的几个方法
    notifyItemInserted();
    notifyItemRangeInserted();
    
    notifyItemChanged();
    notifyItemRangeChanged();
    
    notifyItemRemoved();
    notifyItemRangeRemoved();
    

    七 开源库

    1. XRecyclerView

    据我所知,支付宝用了这个库,比较轻量级别

    • 用法和原生RecycleView一样
    • 封装好了下拉刷新,上拉加载,刷新动画
    • 增加头部,甚至增加俩个headerView

    2.BaseRecyclerViewAdapterHelper

    用了之后你才发现RecyclerView的Adapter也可以写的这么优雅,功能很全,ListView时代的感觉。


    当然一切开源库,不要过度依赖开源库,一切都要建立在踏实的基础上,以上多加练习。


    The End

    相关文章

      网友评论

      • 2c8460a66fc9:7 添加 删除时动画
        建議多加上一句
        對TestRecycleViewAdapter adapter
        做extra field
        否則adapter會讀不到

        這篇文章真的寫的太好了
        推薦!
      • 2c8460a66fc9:@Override public ViewHolderA onCreateViewHolder(ViewGroup parent, int viewType) { //此处动态加载ViewHolder的布局文件并返回holder View view = LayoutInflater.from(mContext).inflate(R.layout.recycleview_item, parent, false); ViewHolderA holderA = new ViewHolderA(view); return holderA; }
        ================
        你這邊少一行,所以所有item都跑不出來
        mContext = parent.getContext();
        minminaya:@rtoday12 感谢阅读
        2c8460a66fc9:阿...你是對的
        抱歉...
        是我自己沒看到
        minminaya:@rtoday12 请看第三,mContext是有值的喔
      • de57329d98b5:整篇教程Recycle和Recycler不分,对初学者太不友好了吧
        minminaya:@cSquared 好的
      • 心若冰清_:建议简猪进行下增加分割线的更新,因为使用mRecyclerView.addItemDecoration(new DividerItemDecoration(this,DividerItemDecoration.VERTICAL))是无法将分割线show出来的,正确的使用是,mRecyclerView.addItemDecoration(new DividerItemDecoration(this,manager.getOrientation()));
        minminaya:@心若冰清_ 特意去试了一下这个版本,发现并没有失效哦,至于你说的新的写法,看了下源代码发现DividerItemDecoration.VERTICAL值和linearLayoutManager.getOrientation()的值都是等于1的,所以俩种写法从根本意义上应该是一样的
        心若冰清_:@敏敏啊呀 RecyclerView: com.android.support:recyclerview-v7:25.3.1
        compileSdkVersion 25
        minminaya:@心若冰清_ 请问楼主你用的是什么版本的RecyclerView库,还有编译API是多少呢?:flushed:
      • 有梦想的青年罒:够详细的,好好学下
      • 且听风吟9527:请教一下,
        mRecycleView.addItemDecoration(new DividerItemDecoration(getApplicationContext(),DividerItemDecoration.VERTICAL));
        时,自定义的分割线没有显示,显示的是默认的分割线,而将getApplicationContext()改为this后,自定义的分割正常显示,能否解惑一下,谢谢!
        且听风吟9527:@敏敏啊呀 明白了,谢谢啊
        minminaya:@且听风吟9527 楼主你好,我以前用的这个版本是可以显示的刚刚试了一下buildTool 26,发现了你这个问题,去查了下这个context场景图,https://raw.githubusercontent.com/jiang111/awesome-android-tips/master/img/context_usage.png,并查看了DividerItemDecoration()类的源代码,发现,加载这个自定义属性并显示出来应该是属于Layout Inflation这一类,可以看到上面Application写的是No^2,这个2的意思是:在这些类中去layout inflate是合法的,但是会使用“系统默认”的主题样式,如果你自定义了某些样式可能不会被使用。就是这个原因才显示了默认样式。
      • 做个疯子: RecyclerView is not RecycleView
      • AndYMJ:仔细的看了一遍,感觉功力大增🤗🤗,📝📝明天手操一遍。再撸一遍
        minminaya:@YMJAndroid 加油:blush:
      • WenchelChow:挺全的
      • AndYMJ:太激动了。😀😀🤗
        minminaya: @YMJAndroid 😂
      • Cloverss:撸主写得很棒啊!!!:blush:
        minminaya:谢谢:relieved:

      本文标题:RecyclerView从入门到深入

      本文链接:https://www.haomeiwen.com/subject/plyggttx.html