Android开发-RecyclerView控件高级的使用(含下拉刷新上拉加载分页)

    xiaoxiao2022-07-04  170

    前 言

    Android RecyclerView控件是在2014年6月Google的I/O大会上推出的Android 5.0时特有的特性,该控件的功能非常强大,它代替了原来的ListView和GridView的控件,它除了能实现线性布局、网格布局样式外还可以实现瀑布流布局的样式。而且在RecyclerView在源码中实现了复用机制的功能,使在渲染界面和填充数据方面都比原来的ListView还要好,在滑动的过程中也比较顺畅。

    那么下面就来看看如何使用RecyclerView吧,本文将介绍RecyclerView的线性布局样式、网格布局样式、瀑布流布局样式以及嵌套布局样式的使用。

    RecyclerView线性布局样式的实现

    在使用RecyclerView控件之前先在AS项目的build.gradle里引入相关的依赖包。

    implementation 'com.android.support:recyclerview-v7:28.0.0'

    从依赖包中可以看到,该依赖包是在v7包下的,所在layout目录下xml布局文件中使用该布局时要写全引用的路径:android.support.v7.widget.RecyclerView。布局如下:

    <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/color_page_bg" android:orientation="vertical"> <com.hjq.bar.TitleBar android:id="@+id/mTitleBar" android:layout_width="match_parent" android:layout_height="40dp" android:background="@color/colorPrimaryDark" app:bar_style="transparent" app:icon_back="true" /> <include layout="@layout/item_loading_view" /> <com.scwang.smartrefresh.layout.SmartRefreshLayout android:id="@+id/refreshLayout" android:layout_width="match_parent" android:layout_height="match_parent" app:srlEnableFooterFollowWhenLoadFinished="true" app:srlEnableScrollContentWhenLoaded="true"> <android.support.v7.widget.RecyclerView android:id="@+id/rvMovieList" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginTop="5dp" android:visibility="gone" /> <com.scwang.smartrefresh.layout.footer.ClassicsFooter android:layout_width="match_parent" android:layout_height="wrap_content" app:srlClassicsSpinnerStyle="Translate" /> </com.scwang.smartrefresh.layout.SmartRefreshLayout> </LinearLayout>

    在该布局中的控件com.scwang.smartrefresh.layout.SmartRefreshLayout是使用目前在GitHub上比较火的对RecyclerView进行实现下拉刷新上拉加载分页功能的开源库,具体的使用的方式可以去该开源的地址去看看,该开源库的地址为:https://github.com/scwang90/SmartRefreshLayout 。

    在layout目录下创建一个xml布局,该布局是用来适配RecyclerView的线性布局加载的item条目的布局。该布局的样式如下:

    <?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/color_page_bg" android:paddingLeft="10dp" android:paddingTop="5dp" android:paddingRight="10dp" android:paddingBottom="5dp"> <android.support.v7.widget.CardView android:id="@+id/home_cardview" android:layout_width="100dp" android:layout_height="135dp" app:cardCornerRadius="4dp" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"> <ImageView android:id="@+id/home_item_movie_list_pic" android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="fitXY" /> </android.support.v7.widget.CardView> <TextView android:id="@+id/home_item_movie_list_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="12dp" android:text="肖申克的救赎" android:textColor="@color/color_black" android:textSize="18sp" android:textStyle="bold" app:layout_constraintStart_toEndOf="@+id/home_cardview" app:layout_constraintTop_toTopOf="@+id/home_cardview" /> <TextView android:id="@+id/home_item_movie_list_director" style="@style/home_style_movie_list_tv" android:text="导演:弗兰克·达拉邦特" app:layout_constraintStart_toEndOf="@+id/home_cardview" app:layout_constraintTop_toBottomOf="@+id/home_item_movie_list_title" /> <TextView android:id="@+id/home_item_movie_list_Starring" style="@style/home_style_movie_list_tv" android:layout_marginRight="10dp" android:text="主演:摩根·弗里曼,蒂姆·罗宾斯" app:layout_constraintStart_toEndOf="@+id/home_cardview" app:layout_constraintTop_toBottomOf="@+id/home_item_movie_list_director" /> <TextView android:id="@+id/home_item_movie_list_type" style="@style/home_style_movie_list_tv" android:layout_marginRight="10dp" android:text="类型:剧情、犯罪" app:layout_constraintStart_toEndOf="@+id/home_cardview" app:layout_constraintTop_toBottomOf="@+id/home_item_movie_list_Starring" /> <TextView android:id="@+id/home_item_movie_list_regions" style="@style/home_style_movie_list_tv" android:layout_marginRight="10dp" android:text="地区:美国" app:layout_constraintStart_toEndOf="@+id/home_cardview" app:layout_constraintTop_toBottomOf="@+id/home_item_movie_list_type" /> </android.support.constraint.ConstraintLayout>

    接着创建一个Adapter来绑定视图、渲染和填充数据以及设置RecyclerView item条目的点击事件的监听接口。代码如下:

    public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> { private Context mContext; private List<MovieDataModel> mList; private MovieDataModel data; private OnItemClikListener mOnItemClikListener; public RecyclerViewAdapter(Context context, List<MovieDataModel> mList) { this.mContext = context; this.mList = mList; } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(mContext).inflate(R.layout.item_movie_layout, parent, false); ViewHolder holder = new ViewHolder(view); return holder; } @Override public void onBindViewHolder(final ViewHolder holder, final int position) { data = mList.get(position); RequestOptions options = new RequestOptions() .placeholder(R.drawable.img_default_movie) .error(R.drawable.img_default_movie); Glide.with(mContext).load(data.getDownimgurl()).apply(options).into(holder.home_item_movie_list_pic); holder.home_item_movie_list_title.setText(data.getDownLoadName()); holder.home_item_movie_list_director.setText(data.getDirector()); holder.home_item_movie_list_Starring.setText(data.getStarring()); holder.home_item_movie_list_type.setText(data.getType()); holder.home_item_movie_list_regions.setText(data.getRegions()); if (mOnItemClikListener != null) { // 设置item条目短按点击事件的监听 holder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int pos = holder.getLayoutPosition(); mOnItemClikListener.onItemClik(holder.itemView, pos); } }); // 设置item条目长按点击事件的监听 holder.itemView.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { int pos = holder.getLayoutPosition(); mOnItemClikListener.onItemLongClik(holder.itemView, pos); return false; } }); } } @Override public int getItemCount() { return mList.size(); } public static class ViewHolder extends RecyclerView.ViewHolder { private ImageView home_item_movie_list_pic; private TextView home_item_movie_list_title; private TextView home_item_movie_list_director; private TextView home_item_movie_list_Starring; private TextView home_item_movie_list_type; private TextView home_item_movie_list_regions; public ViewHolder(View itemView) { super(itemView); home_item_movie_list_pic = (ImageView) itemView.findViewById(R.id.home_item_movie_list_pic); home_item_movie_list_title = (TextView) itemView.findViewById(R.id.home_item_movie_list_title); home_item_movie_list_director = (TextView) itemView.findViewById(R.id.home_item_movie_list_director); home_item_movie_list_Starring = (TextView) itemView.findViewById(R.id.home_item_movie_list_Starring); home_item_movie_list_type = (TextView) itemView.findViewById(R.id.home_item_movie_list_type); home_item_movie_list_regions = (TextView) itemView.findViewById(R.id.home_item_movie_list_regions); } } // 定义item条目点击事件接口 public interface OnItemClikListener { void onItemClik(View view, int position); void onItemLongClik(View view, int position); } public void setItemClikListener(OnItemClikListener mOnItemClikListener) { this.mOnItemClikListener = mOnItemClikListener; } }

    最后在Activity或者Fragment中进行对数据的解析和设置。代码如下:

    /** * RecyclerView线性布局样式 */ public class RecyclerViewActivity extends BaseActivity { @BindView(R.id.mTitleBar) TitleBar mTitleBar; @BindView(R.id.loading_view_ll) LinearLayout loading_view_ll; @BindView(R.id.loading_view) ImageView mLoadingView; @BindView(R.id.refreshLayout) RefreshLayout refreshLayout; @BindView(R.id.rvMovieList) RecyclerView rvMovieList; private boolean refreshType; private int page; private int oldListSize; private int newListSize; private int addListSize; private String viewType; private RecyclerViewAdapter adapter; private List<MovieDataModel> mList = new ArrayList<>(); @Override protected int getLayoutId() { return R.layout.activity_recycler_view; } @Override protected void initView() { ButterKnife.bind(this); Intent intent = getIntent(); viewType = intent.getStringExtra("ViewType"); mTitleBar.setOnTitleBarListener(new OnTitleBarListener() { @Override public void onLeftClick(View v) { finish(); } @Override public void onTitleClick(View v) { } @Override public void onRightClick(View v) { } }); AnimationDrawable anim = (AnimationDrawable) mLoadingView.getDrawable(); anim.start(); } @Override protected void initData() { // 开启自动加载功能(非必须) refreshLayout.setEnableAutoLoadMore(true); refreshLayout.setOnRefreshListener(new OnRefreshListener() { @Override public void onRefresh(@NonNull final RefreshLayout refreshLayout) { refreshLayout.getLayout().postDelayed(new Runnable() { @Override public void run() { refreshType = true; page = 1; parsingMovieListJson(); refreshLayout.finishRefresh(); refreshLayout.resetNoMoreData();//setNoMoreData(false); } }, 2000); } }); refreshLayout.setOnLoadMoreListener(new OnLoadMoreListener() { @Override public void onLoadMore(@NonNull final RefreshLayout refreshLayout) { refreshLayout.getLayout().postDelayed(new Runnable() { @Override public void run() { refreshType = false; if (page > 2) { ToastUtil.showToast("暂无更多的数据啦"); // 将不会再次触发加载更多事件 refreshLayout.finishLoadMoreWithNoMoreData(); return; } parsingMovieListJson(); refreshLayout.setEnableLoadMore(true); refreshLayout.finishLoadMore(); } }, 2000); } }); //触发自动刷新 refreshLayout.autoRefresh(); } private void parsingMovieListJson() { try { // 从assets目录中获取json数据,在真实的项目开发中需要通过网络请求从服务器json数据 String jsonData = BaseTools.getAssetsJson(this, "movie" + page + ".json"); if (refreshType && mList != null) { mList.clear(); oldListSize = 0; } else { oldListSize = mList.size(); } // 使用Google的Gson开始解析json数据 Gson gson = new Gson(); MovieBaseModel movieBaseModel = gson.fromJson(jsonData, MovieBaseModel.class); List<MovieDataModel> movieDataModelList = movieBaseModel.getData(); for (MovieDataModel movieDataModel : movieDataModelList) { MovieDataModel data = new MovieDataModel(); data.setMovClass(movieDataModel.getMovClass()); data.setDownLoadName(movieDataModel.getDownLoadName()); data.setDownimgurl(movieDataModel.getDownimgurl()); data.setDownLoadUrl(movieDataModel.getDownLoadUrl()); data.setMvdesc(movieDataModel.getMvdesc()); OtherBaseModel otherModelDesc = gson.fromJson(movieDataModel.getMvdesc(), OtherBaseModel.class); List<String> headerList = otherModelDesc.getHeader(); data.setDirector(headerList.get(1)); data.setStarring(headerList.get(2)); data.setType(headerList.get(3)); data.setRegions(headerList.get(4)); mList.add(data); } } catch (Exception e) { e.printStackTrace(); } newListSize = mList.size(); addListSize = newListSize - oldListSize; if (refreshType) { // 设置RecyclerView样式为竖直线性布局 rvMovieList.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)); adapter = new RecyclerViewAdapter(this, mList); if (viewType.equals("NoDividingLine")) { mTitleBar.setTitle("线性布局样式"); } else { mTitleBar.setTitle("线性布局(有分割线)样式"); // 设置分割线 rvMovieList.addItemDecoration(new CustomDecoration( this, LinearLayoutManager.VERTICAL, R.drawable.divider_mileage, 15)); } rvMovieList.setAdapter(adapter); } else { adapter.notifyItemRangeInserted(mList.size() - addListSize, mList.size()); adapter.notifyItemRangeChanged(mList.size() - addListSize, mList.size()); } page++; rvMovieList.setVisibility(View.VISIBLE); loading_view_ll.setVisibility(View.GONE); // item条目的点击事件回调 adapter.setItemClikListener(new RecyclerViewAdapter.OnItemClikListener() { // 短按点击事件回调 @Override public void onItemClik(View view, int position) { String videoTitle = mList.get(position).getDownLoadName(); ToastUtil.showToast(videoTitle); } // 长按点击事件回调 @Override public void onItemLongClik(View view, int position) { } }); } }

    从以上代码可以看到,refreshLayout.setOnRefreshListener(new OnRefreshListener()方法是实现下拉刷新数据的功能,refreshLayout.setOnLoadMoreListener(new OnLoadMoreListener()是实现上拉加载分页数据的功能。而 rvMovieList.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false))这段代码是设置RecyclerView样式为竖直线性布局。 rvMovieList.addItemDecoration(new CustomDecoration(this, LinearLayoutManager.VERTICAL, R.drawable.divider_mileage, 15))这段代码是实现RecyclerView item条目之间的分割线的效果,而RecyclerView与ListView不同是RecyclerView默认是没有分割线的,如果开发者需要实现分割线功能的话只能自己定义。最后adapter.setItemClikListener(new RecyclerViewAdapter.OnItemClikListener()该回调的接口是实现RecyclerView item条目的点击事件回调。

    在Activity里模拟以网络请求的方式从服务端获取json数据并解析设置到视图界面上,json的数据结构如下:

    { "Code":200, "Msg":"数据获取成功", "Data":[ { "movClass":"科幻片", "downLoadName":"海市蜃城", "downLoadUrl":"", "mvdesc":"{"header": ["别名:", "导演:孙田", "主演:刘端端,王滢,高强,刘依琳", "类型:科幻片 悬疑 科幻", "地区:大陆", "语言:国语", "上映:2019", "片长:91", "更新:2019-05-20 00:42:56", "总播放量:", "今日播放量:0", "总评分数:0", "评分次数:0"], "desc": "阿可是一个游戏公司的CEO兼游戏设计师,最近一直在设计一款即将上市的游戏《魔界通缉》,这款游戏为玩家提供了更加真实的体验,在最后的一次玩家测试时,一位玩家差点因为游戏丢了性命,且一直未查明原因。压力很大的阿可开始生活中经常出现幻觉。同时眼睛也出了问题。游戏设计如期完成,期间阿可一直阻止公司召开游戏发布会,希望能查清游戏的安全性,但被一个神秘人阻挠。游戏发布会如期召开,引起粉丝疯狂捧场,神秘人在发布会上也代替了阿可的发言。游戏上线后阿可发现游戏开始慢慢控制玩家,同时发生了越来越多的不可思议的事情。当阿可想删除游戏源代码时,所有玩家对阿可开始了真正的通缉……"}", "downimgurl":"https://tupian.tupianzy.com/pic/upload/vod/2019-05-20/201905201558283504.jpg", "mv_update_time":"2019-05-20", "downdtitle":"zuidam3u8,zuidall,迅雷下载", "id":"10313", "mv_md5_id":"4b406e86b4eaeea68fb7fc7c0608c348", "type":"00000000001" } ] }

    界面运行效果图如下:

    其中的第一张图是RecyclerView线性布局样式默认没有分割线的运行效果图,第二种是自定义有分割线的运行效果图。

    RecyclerView网格布局样式的实现

    RecyclerView网格布局样式的实现只需要修改item布局以及部分Adapter、Activity的代码。

    item布局的xml布局代码如下:

    <?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/cv_top_movie" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginStart="3dp" android:layout_marginTop="3dp" android:layout_marginEnd="3dp" android:layout_marginBottom="3dp" android:foreground="?attr/selectableItemBackgroundBorderless" app:cardCornerRadius="2dp" app:cardElevation="2dp"> <LinearLayout android:id="@+id/ll_item_top" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:paddingBottom="3dp"> <ImageView android:id="@+id/iv_photo" android:layout_width="match_parent" android:layout_height="145dp" android:scaleType="fitXY" app:layout_collapseMode="parallax" app:layout_collapseParallaxMultiplier="0.7" tools:background="@color/color_page_bg" /> <TextView android:id="@+id/tv_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_marginTop="3dp" android:ellipsize="marquee" android:focusable="true" android:focusableInTouchMode="true" android:singleLine="true" android:text="肖申克的救赎" android:textColor="@color/colorTitle" android:textSize="12sp" /> <TextView android:id="@+id/tv_regions" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:text="地区:美国" android:textSize="10sp" /> </LinearLayout> </android.support.v7.widget.CardView>

    修改以下Activity中的代码:

    // 设置RecyclerView样式为网格布局,一行显示3列 rvMovieList.setLayoutManager(new GridLayoutManager(this, 3)); adapter = new GridLayoutRVAdapter(this, mList); rvMovieList.setAdapter(adapter);

    可以看到,GridLayoutManager是设置RecyclerView样式为网格布局,其中的第二个参数设置一行显示3列item条目。

    界面运行效果图如下:

    RecyclerView瀑布流布局样式的实现

    RecyclerView瀑布流布局样式可能在实际的项目开发中用的比较少,比较常用的是前两种的线性布局和网格布局,不过瀑布流样式在电商的App中用的比较多,比如淘宝的Android端App的首页就用到RecyclerView瀑布流布局样式。如下图: RecyclerView瀑布流布局样式可以在网格布局样式的基础来修改实现,首先修改item条目的布局样式,布局代码如下:

    <?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/cv_top_movie" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginStart="3dp" android:layout_marginTop="3dp" android:layout_marginEnd="3dp" android:layout_marginBottom="3dp" android:foreground="?attr/selectableItemBackgroundBorderless" app:cardCornerRadius="2dp" app:cardElevation="2dp"> <LinearLayout android:id="@+id/ll_item_top" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:paddingBottom="3dp"> <ImageView android:id="@+id/iv_photo" android:layout_width="match_parent" android:layout_height="wrap_content" android:adjustViewBounds="true" android:scaleType="fitXY" app:layout_collapseMode="parallax" app:layout_collapseParallaxMultiplier="0.7" tools:background="@color/color_page_bg" /> <TextView android:id="@+id/tv_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_marginTop="3dp" android:ellipsize="marquee" android:focusable="true" android:focusableInTouchMode="true" android:singleLine="true" android:text="肖申克的救赎" android:textColor="@color/colorTitle" android:textSize="12sp" /> <TextView android:id="@+id/tv_regions" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:text="地区:美国" android:textSize="10sp" /> </LinearLayout> </android.support.v7.widget.CardView>

    从布局文件代码中可以看到,瀑布流的代码和网格的布局有两处的不同,就是把图像的控件ImageView的高度修改为"wrap_content"值,而网格是改为固定值,还有一处就是把在瀑布流的图像控件ImageView添加了android:adjustViewBounds="true"属性,这个属性的作用就是使显示图片能够自适合来显示,使瀑布流样式的效果更好看。

    接着修改Activity中的代码,修改的代码如下:

    // 设置RecyclerView样式为瀑布流布局,一行显示2列 rvMovieList.setLayoutManager(new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL)); adapter = new StaggeredGridRVAdapter(this, mList); rvMovieList.setAdapter(adapter);

    代码中的StaggeredGridLayoutManager是设置RecyclerView样式为网格布局,其中的第一个参数设置一行显示2列item条目,第二个参数设置竖直显示。

    界面运行效果图如下:

    RecyclerView嵌套布局样式的实现

    在实现RecyclerView嵌套布局样式之前先看一下嵌套布局的json数据结构:

    { "reason":"成功的返回", "data":[ { "title":"高清电影", "content":[ { "name":"异类侵袭", "tag":"地区:大陆", "url":"", "thumbnail_pic_s":"https://tupian.tupianzy.com/pic/upload/vod/2019-05-19/201905191558252942.png" } ] }, { "title":"热门剧集", "content":[ { "name":"筑梦情缘[DVD版]", "tag":"地区:大陆", "url":"", "thumbnail_pic_s":"https://tupian.tupianzy.com/pic/upload/vod/2019-05-10/201905101557455675.jpg" } ] } ], "error_code":0 }

    从json的数据结构中可以看出,"data"字段是一个数组字段,数组字段中包含若干个的集合字段,可以把数组字段当作是一个父布局的RecyclerView,若干个集合字段当作是一个子布局的RecyclerView。也就是说嵌套布局是由一个RecyclerView布局嵌套一个或多个RecyclerView的。

    而嵌套布局样式主要是Adapter设置数据绑定时比较麻烦,首次定义一个父Adapter,在由父Adapter去映射到子Adapter。父Adapter代码如下:

    public class MovieTypesAdapter extends RecyclerView.Adapter<MovieTypesAdapter.ViewHolder> { private Context mContext; private List<MovieTypesDataModel> mList; private MovieTypesDataModel data; private OnItemClikListener mOnItemClikListener; public MovieTypesAdapter(Context context, List<MovieTypesDataModel> mList) { this.mContext = context; this.mList = mList; } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(mContext).inflate(R.layout.movie_types_title, parent, false); ViewHolder holder = new ViewHolder(view); return holder; } @Override public void onBindViewHolder(final ViewHolder holder, final int position) { data = mList.get(position); holder.movieTypesTitle.setText(data.getTitle()); MovieTypesChildAdapter childAdapter = (MovieTypesChildAdapter) holder.movieTypesChild.getAdapter(); //适配器复用 if (childAdapter == null) { RecyclerView.LayoutManager manager = new GridLayoutManager(mContext, 3); holder.movieTypesChild.setLayoutManager(manager); holder.movieTypesChild.setAdapter(new MovieTypesChildAdapter(mContext, data.getContent(), position)); } else { childAdapter.setData(data.getContent()); //重新设置数据 childAdapter.notifyDataSetChanged(); } if (mOnItemClikListener != null) { holder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int pos = holder.getLayoutPosition(); mOnItemClikListener.onItemClik(holder.itemView, pos); } }); holder.itemView.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { int pos = holder.getLayoutPosition(); mOnItemClikListener.onItemLongClik(holder.itemView, pos); return false; } }); } } @Override public int getItemCount() { return mList == null ? 0 : mList.size(); } public static class ViewHolder extends RecyclerView.ViewHolder { private TextView movieTypesTitle; private RecyclerView movieTypesChild; public ViewHolder(View itemView) { super(itemView); movieTypesTitle = (TextView) itemView.findViewById(R.id.movieTypesTitle); movieTypesChild = (RecyclerView) itemView.findViewById(R.id.movieTypesChild); } } public interface OnItemClikListener { void onItemClik(View view, int position); void onItemLongClik(View view, int position); } public void setItemClikListener(OnItemClikListener mOnItemClikListener) { this.mOnItemClikListener = mOnItemClikListener; } }

    子Adapter代码如下:

    public class MovieTypesChildAdapter extends RecyclerView.Adapter<MovieTypesChildAdapter.ViewHolder> { private Context mContext; private List<MovieTypesDataModel.MovieTypesContentModel> childList; private int mPosition; private MovieTypesDataModel.MovieTypesContentModel data; private OnItemClikListener mOnItemClikListener; public MovieTypesChildAdapter(Context context, List<MovieTypesDataModel.MovieTypesContentModel> childList) { this.mContext = context; this.childList = childList; } public MovieTypesChildAdapter(Context context, List<MovieTypesDataModel.MovieTypesContentModel> childList, int position) { this.mContext = context; this.childList = childList; this.mPosition = position; } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(mContext).inflate(R.layout.item_movie_grid, parent, false); ViewHolder holder = new ViewHolder(view); return holder; } @Override public void onBindViewHolder(final ViewHolder holder, final int position) { data = childList.get(position); RequestOptions options = new RequestOptions() .placeholder(R.drawable.img_default_movie) .error(R.drawable.img_default_movie); Glide.with(mContext).load(data.getThumbnail_pic_s()).apply(options).into(holder.iv_photo); holder.tv_name.setText(data.getName()); holder.tv_regions.setText(data.getTag()); holder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int pos = holder.getLayoutPosition(); NestRVActivity.instance.OnClickListener(mPosition, pos); } }); holder.itemView.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { return false; } }); } @Override public int getItemCount() { return childList == null ? 0 : childList.size(); } public void setData(List<MovieTypesDataModel.MovieTypesContentModel> childList) { this.childList = childList; } public static class ViewHolder extends RecyclerView.ViewHolder { private ImageView iv_photo; private TextView tv_name; private TextView tv_regions; public ViewHolder(View itemView) { super(itemView); iv_photo = (ImageView) itemView.findViewById(R.id.iv_photo); tv_name = (TextView) itemView.findViewById(R.id.tv_name); tv_regions = (TextView) itemView.findViewById(R.id.tv_regions); } } public interface OnItemClikListener { void onItemClik(View view, int position); void onItemLongClik(View view, int position); } public void setItemClikListener(OnItemClikListener mOnItemClikListener) { this.mOnItemClikListener = mOnItemClikListener; } }

    界面运行效果图如下:

    apk安装包下载体验地址

    可以扫描以下二维码进行下载安装,或者点击以下链接 https://fukaimei.top/apk/RecyclerViewTest.apk 进行下载安装体验。 ———————— The end ————————

    如果您觉得这篇博客写的比较好的话,赞赏一杯咖啡吧~~


    Demo程序源码下载地址一(GitHub) Demo程序源码下载地址二(码云)

    最新回复(0)