复杂RecyclerView的实现
来源:互联网 发布:淘宝入驻村淘的的条件 编辑:程序博客网 时间:2024/06/06 00:29
之前周末的时候写过一篇复杂ListView相关的文章,但是写的不够详尽(具体到每个方法),只是个人觉得没有必要写的那么详细,因为大部分的内容对于一个拥有安卓开发开发经验的人来说跑完Demo之后都会很好理解的。
但是现如今使用ListView的部分朋友已经转到RecyclerView这一黑科技控件下了,所以我便将之前的思路试着看移植到RecyclerView之中,中间遇到了两个坑,下面来喝大家分享一下!
首先,按照规律,我们来看下效果图:
下面我们来一步步实现:
首先想到的是RecyclerView的一些设置,这些其实也没啥好说的:
看代码:
myRecyclerViewAdapter = new MyRecyclerViewAdapter(this, users); LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this); linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); recyclerView.setLayoutManager(linearLayoutManager); recyclerView.setAdapter(myRecyclerViewAdapter);主要是一些设置的东西。
下面我们来看重点:
MyRecyclerViewAdapter的实现我们一步步进行分解
1.首先看顶部的ViewPager布局:
下面来看布局代码:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v4.view.ViewPager android:id="@+id/item1_vp" android:layout_width="match_parent" android:layout_height="200dp" android:text="item00"/></LinearLayout>
其实也很简单直接声明下,之后我们来看ViewPager的Adapter设定,我这里就简单地设定了Adapter:
public class ViewPagerAdapter extends PagerAdapter { private Context context; public ViewPagerAdapter(Context context) { this.context = context; } @Override public Object instantiateItem(ViewGroup container, int position) { TextView textView = new TextView(context); textView.setText(position + ""); container.addView(textView); return textView; } @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView((View) object); } @Override public boolean isViewFromObject(View view, Object object) { return view == object; } @Override public int getCount() { return 4; }}也是最最基础的东西了,没啥好说的,看不懂的童鞋面壁思过去。。。
2.两个线性布局,他俩存在的意义就是为了体现咱们的思路适应多种布局:
3.横向ScrollView,其实这里也可以用横向RecyclerView,只是这里为了避免嵌套引发的问题,使用了横向ScrollVIew:
布局如下:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <HorizontalScrollView android:id="@+id/horizontalscrollview" android:layout_width="match_parent" android:layout_height="match_parent" > <LinearLayout android:id="@+id/ll_main" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal"> </LinearLayout> </HorizontalScrollView></LinearLayout>
实现动态添加的代码如下:
LinearLayout rl_layout = null; TextView tv_title = null; TextView tv_sub_title = null; ImageView iv_test = null; for (int i = 0; i < 10; i++) { View view = LayoutInflater.from(ctx).inflate(R.layout.scroll_item_layout, null); int screenWidth = CommonUtil.getScreenWidth(ctx); int screenHeight = CommonUtil.getScreenHeight(ctx); //根据屏幕宽度设定横向滑动子View的宽度 view.setLayoutParams(new LinearLayout.LayoutParams(screenWidth / 2, 120)); rl_layout = (LinearLayout) view.findViewById(R.id.rl_layout); tv_title = (TextView) view.findViewById(R.id.tv_title); tv_sub_title = (TextView) view.findViewById(R.id.tv_sub_title); tv_sub_title = (TextView) view.findViewById(R.id.tv_sub_title); iv_test = (ImageView) view.findViewById(R.id.iv_test); tv_title.setText("主标题" + i); tv_sub_title.setText("子标题" + i); iv_test.setImageResource(R.mipmap.ic_launcher); final int finalI = i; rl_layout.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Toast.makeText(ctx, "view" + finalI, Toast.LENGTH_SHORT).show(); } }); itemHolder4.ll_main.addView(view); }这里犹豫ScrollView只能有一个直接的子布局,所以我们在这里向LinearLayout中添加布局,然后再添加到HorizontalScrollView之中。
其次,为了保证布局中,横向滚动的ScrollView保证一屏之中只有两个,所以这里我们获取屏幕的宽度,然后设定每个子View的宽度为半个屏幕,哈哈!
下面就来到了最精彩的时候了:
我们应该怎样整合这些复杂的布局呢?
RecyclerView.Adapter<RecyclerView.ViewHolder>中给我们提供了几个非常好用的方法:
@Override public int getItemViewType(int position) {}和//为每种布局定义自己的ViewHolder public class ViewHolder1 extends RecyclerView.ViewHolder { private ViewPager item1_vp; public ViewHolder1(View itemView) { super(itemView); item1_vp = (ViewPager) itemView.findViewById(R.id.item1_vp); } public void setData() { item1_vp.setAdapter(new ViewPagerAdapter(ctx)); } }下面我们来一步步解释下:
创建ViewHolder的时候会调用该方法:
@Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { RecyclerView.ViewHolder holder = null; switch (viewType) { case TYPE1: holder = new ViewHolder1(View.inflate(ctx, R.layout.itemlayout1, null)); break; case TYPE2: holder = new ViewHolder2(View.inflate(ctx, R.layout.itemlayout2, null)); break; case TYPE3: holder = new ViewHolder3(View.inflate(ctx, R.layout.itemlayout3, null)); break; case TYPE4: holder = new ViewHolder4(View.inflate(ctx, R.layout.horizontal_crollview_main, null)); break; default: break; } return holder; }总共有四种类型,分别标记下:
//为三种布局定义一个标识 private final int TYPE1 = 0; private final int TYPE2 = 1; private final int TYPE3 = 2; private final int TYPE4 = 3;
绑定ViewHolder的时候,调用如下方法:
@Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { //由于木有相关的viewType参数,只能通过方法来获取了 int viewType = getItemViewType(position); switch (viewType) { case TYPE1: ((ViewHolder1) holder).setData(); break; case TYPE2: ((ViewHolder2) holder).setData(position); break; case TYPE3: ((ViewHolder3) holder).setData(position); break; case TYPE4: ((ViewHolder4) holder).setData((ViewHolder4) holder); break; } }
在这里我把设定的方法全部放到ViewHolder里面了。
这里我们需要根据返回类型的不同进行相关设定:
@Override public int getItemViewType(int position) { //获取当前布局的数据 User u = users.get(position); //哪个字段不为空就说明这是哪个布局 //比如第一个布局只有item1_str这个字段,那么就判断这个字段是不是为空, //如果不为空就表明这是第一个布局的数据 //根据字段是不是为空,判断当前应该加载的布局 Log.i("LHD", u.toString()); Log.i("LHD", "第一个返回值" + u.getItem1_str()); Log.i("LHD", "第二个返回值" + u.getItem2_str()); Log.i("LHD", "第三个返回值" + u.getItem3_str()); if (u.getItem1_str() != null) { return TYPE1; } else if (u.getItem2_str() != null) { return TYPE2; } else if (u.getItem3_str() != null) {//如果前两个字段都为空,那就一定是加载第三个布局啦。 return TYPE3; } else { return TYPE4; } }
这样就可以得出了各种条目类型以及对应关系。
但是看到这里是不是有点儿乱呢,乱就对了,说明你已经在认真思考了,哈哈!
我来总结下,处理复杂RecyclerView的方法:
1.重写@Override public int getItemViewType(int position) {}非常重要,这里是进行子条目布局区分的重要方法,
2.重写
@Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {}方法可以根据type的不同返回不同的条目布局ViewHolder
3.重写:
@Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {}可以进行相关的绑定,也就是说白了进行初始化。
下面来贴上Adpater的完整源码:
public class MyRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { //定义常用的参数 private Context ctx; private int resourceId; //JavaBean private List<User> users; private LayoutInflater inflater; //为三种布局定义一个标识 private final int TYPE1 = 0; private final int TYPE2 = 1; private final int TYPE3 = 2; private final int TYPE4 = 3; public MyRecyclerViewAdapter(Context ctx, List<User> objects) { this.ctx = ctx; this.users = objects; //别忘了初始化inflater inflater = LayoutInflater.from(ctx); } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { RecyclerView.ViewHolder holder = null; switch (viewType) { case TYPE1: holder = new ViewHolder1(View.inflate(ctx, R.layout.itemlayout1, null)); break; case TYPE2: holder = new ViewHolder2(View.inflate(ctx, R.layout.itemlayout2, null)); break; case TYPE3: holder = new ViewHolder3(View.inflate(ctx, R.layout.itemlayout3, null)); break; case TYPE4: holder = new ViewHolder4(View.inflate(ctx, R.layout.horizontal_crollview_main, null)); break; default: break; } return holder; } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { //由于木有相关的viewType参数,只能通过方法来获取了 int viewType = getItemViewType(position); switch (viewType) { case TYPE1: ((ViewHolder1) holder).setData(); break; case TYPE2: ((ViewHolder2) holder).setData(position); break; case TYPE3: ((ViewHolder3) holder).setData(position); break; case TYPE4: ((ViewHolder4) holder).setData((ViewHolder4) holder); break; } } @Override public int getItemViewType(int position) { //获取当前布局的数据 User u = users.get(position); //哪个字段不为空就说明这是哪个布局 //比如第一个布局只有item1_str这个字段,那么就判断这个字段是不是为空, //如果不为空就表明这是第一个布局的数据 //根据字段是不是为空,判断当前应该加载的布局 Log.i("LHD", u.toString()); Log.i("LHD", "第一个返回值" + u.getItem1_str()); Log.i("LHD", "第二个返回值" + u.getItem2_str()); Log.i("LHD", "第三个返回值" + u.getItem3_str()); if (u.getItem1_str() != null) { return TYPE1; } else if (u.getItem2_str() != null) { return TYPE2; } else if (u.getItem3_str() != null) {//如果前两个字段都为空,那就一定是加载第三个布局啦。 return TYPE3; } else { return TYPE4; } } @Override public int getItemCount() { return users.size(); } //为每种布局定义自己的ViewHolder public class ViewHolder1 extends RecyclerView.ViewHolder { private ViewPager item1_vp; public ViewHolder1(View itemView) { super(itemView); item1_vp = (ViewPager) itemView.findViewById(R.id.item1_vp); } public void setData() { item1_vp.setAdapter(new ViewPagerAdapter(ctx)); } } public class ViewHolder2 extends RecyclerView.ViewHolder { private TextView item2_tv; public ViewHolder2(View itemView) { super(itemView); item2_tv = (TextView) itemView.findViewById(R.id.item2_tv); } public void setData(int position) { item2_tv.setText(users.get(position).getItem2_str()); } } public class ViewHolder3 extends RecyclerView.ViewHolder { private Button item3_btn; public ViewHolder3(View itemView) { super(itemView); item3_btn = (Button) itemView.findViewById(R.id.item3_btn); } public void setData(int position) { item3_btn.setText(users.get(position).getItem3_str()); } } public class ViewHolder4 extends RecyclerView.ViewHolder { private LinearLayout ll_main; public ViewHolder4(View itemView) { super(itemView); ll_main = (LinearLayout) itemView.findViewById(R.id.ll_main); } public void setData(ViewHolder4 itemHolder4) { LinearLayout rl_layout = null; TextView tv_title = null; TextView tv_sub_title = null; ImageView iv_test = null; for (int i = 0; i < 10; i++) { View view = LayoutInflater.from(ctx).inflate(R.layout.scroll_item_layout, null); int screenWidth = CommonUtil.getScreenWidth(ctx); int screenHeight = CommonUtil.getScreenHeight(ctx); //根据屏幕宽度设定横向滑动子View的宽度 view.setLayoutParams(new LinearLayout.LayoutParams(screenWidth / 2, 120)); rl_layout = (LinearLayout) view.findViewById(R.id.rl_layout); tv_title = (TextView) view.findViewById(R.id.tv_title); tv_sub_title = (TextView) view.findViewById(R.id.tv_sub_title); tv_sub_title = (TextView) view.findViewById(R.id.tv_sub_title); iv_test = (ImageView) view.findViewById(R.id.iv_test); tv_title.setText("主标题" + i); tv_sub_title.setText("子标题" + i); iv_test.setImageResource(R.mipmap.ic_launcher); final int finalI = i; rl_layout.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Toast.makeText(ctx, "view" + finalI, Toast.LENGTH_SHORT).show(); } }); itemHolder4.ll_main.addView(view); } } }}
我在编写代码中遇到的两个坑:
子布局已经设置match_parent了,但是条目布局还是包裹内容的形式展示出来了,这里做了个处理就好了,
<View android:layout_width="match_parent" android:layout_height="1dp" android:background="@color/colorBlack" />在布局的最下面加了一个View布局,撑开了整个布局条目,使之匹配父布局,目前原因未知,先这样处理了。
2.刷新控件适应的是XRefreshView,非常感谢作者啊,但是在上拉加载的时候始终会遮盖最新的条目,使之没法展示出来,这里我做了个小小的处理:
recyclerView.scrollBy(0,30);上滑一段距离,这样就可以展示出来了,提示用户下面还有内容可以下拉查看。嗯嗯,还行吧!
下面照旧是放出源码的时候了:
ComplexRecyclerView
谢谢!
阅读全文
0 0
- 复杂RecyclerView的实现
- 复杂RecyclerView的实现
- recyclerView实现复杂布局的好处
- 优雅地实现RecyclerView的复杂布局
- Android RecyclerView 复杂列表的实现
- 强大的RecyclerView实现复杂布局
- RecyclerView实现复杂布局
- 复杂RecyclerView实现
- RecyclerView实现复杂页面
- RecyclerView GridLayoutManager实现复杂的列数变化的布局
- RecyclerView GridLayoutManager实现复杂的列数变化的布局
- 不一样的RecyclerView优雅实现复杂列表布局(一)
- 不一样的RecyclerView优雅实现复杂列表布局(二)
- 不一样的RecyclerView优雅实现复杂列表局
- MultiType-Adapter 优雅的实现RecyclerVIew中的复杂布局
- 复杂RecyclerView的实现(添加底部瀑布流效果)
- android RecyclerView的复杂布局
- android RecyclerView的复杂布局
- CRC8查表法中表的计算过程
- UART串行通信
- 背景图片不被拉伸方案及设置图片透明效果
- linux 修改eth*
- 2017中国SaaS用户研究报告
- 复杂RecyclerView的实现
- Java 枚举(enum) 详解7种常见的用法
- 面向对象的程序设计(一)
- 腾讯浏览服务X5内核集成
- POWERSHELL命令获取日期是今年的第几周
- java 线程 Lock 锁使用Condition实现线程的等待(await)与通知(signal)
- 基于frp通过ssh访问公司(学校)内网机器【Ubuntu系统】
- 图解设计模式之Iterator(迭代器)模式
- 测试spring,mybatis时出现.BindingException: Invalid bound statement (not found): com.imooc.dao.Secki