RecyclerView添加头脚布局,使用SwipeRefreshLayout的实现
2016-05-13 12:25
671 查看
上篇文章记录了将viewpager抽取出来,那么这篇文章我们继续来实现,将viewpager做为头布局添加给RecyclerView。这使用到了一种设计模式 - 包装类设计模式,大家可以先了解下这个模式更有利于理解,我也会把本篇实现的思路给出个思维导图的。
看下效果图吧:
![](https://img-blog.csdn.net/20160518152513934)
首先来个bean对象,等下封装数据使用:
然后我们创建一个类WrapRecyclerView继承自RecyclerView:
然后我们在创建个类RecylerWrapAdapter继承自RecyclerView.Adapter对adapter进行包装:
现在包装类写完了,但我们的RecyclerView还没有Adapter的,那我们就创建吧,和使用普通RecyclerView的Adapter一样:
OK,现在大功告成,我们已经在MainActivity的initRecycler()方法中使用了,运行就可以看到效果了。
对包装类设计模式不熟悉的朋友可能会有些疑问,下面给大家贴出我做的思维导图:
![](https://img-blog.csdn.net/20160513122207988)
最好的方法还是自己写出来,断点下就清楚这个设计模式和执行流程了。如有哪里不足,欢迎指教。
Reference:
http://www.it165.net/pro/html/201507/48065.html
http://blog.csdn.net/lmj623565791/article/details/45059587
https://github.com/DevLight-Mobile-Agency/NavigationTabBar
项目代码已经发布到github,地址:https://github.com/viewpager/HeadApplication
看下效果图吧:
首先来个bean对象,等下封装数据使用:
public class Item { private String maintitle; private String subtitle; public Item(String maintitle, String subtitle){ this.maintitle = maintitle; this.subtitle = subtitle; } public String getMaintitle() { return maintitle; } public String getSubtitle() { return subtitle; } }
然后我们创建一个类WrapRecyclerView继承自RecyclerView:
// 将recycle进行封装 public class WrapRecyclerView extends RecyclerView { private ArrayList<View> mHeadViewList = new ArrayList<View>(); private ArrayList<View> mFootViewList = new ArrayList<View>(); private Adapter mAdapter; public WrapRecyclerView(Context context) { super(context); } public WrapRecyclerView(Context context, AttributeSet attrs) { super(context, attrs); } public WrapRecyclerView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public void addHeaderView(View view){ mHeadViewList.clear(); mHeadViewList.add(view); if (mAdapter != null){ if (!(mAdapter instanceof RecylerWrapAdapter)){ mAdapter = new RecylerWrapAdapter(mHeadViewList,mFootViewList,mAdapter); } } } public void addFootView(View view){ mFootViewList.clear(); mFootViewList.add(view); if (mAdapter != null){ if (!(mAdapter instanceof RecylerWrapAdapter)){ mAdapter = new RecylerWrapAdapter(mHeadViewList,mFootViewList,mAdapter); } } } @Override public void setAdapter(Adapter adapter) { if (mHeadViewList.isEmpty() && mFootViewList.isEmpty()){ super.setAdapter(adapter); }else{ adapter = new RecylerWrapAdapter(mHeadViewList,mFootViewList,adapter); super.setAdapter(adapter); } mAdapter = adapter; } }
//在布局使用,使用系统的SwipeRefreshLayout包裹下 <android.support.v4.widget.SwipeRefreshLayout android:id="@+id/srl_refresh" android:layout_width="match_parent" android:layout_height="match_parent"> <com.wb.head.widget.WrapRecyclerView android:id="@+id/recycler" android:layout_width="match_parent" android:layout_height="match_parent"/> </android.support.v4.widget.SwipeRefreshLayout> //然后在MainActivity的onCreate中获取实例,进行初始化。还是我们上篇的那个MainActivity recycler = (WrapRecyclerView) findViewById(R.id.recycler); refresh = (SwipeRefreshLayout) findViewById(R.id.srl_refresh); initRecycler(); initRefresh();
private void initRecycler(){ ll_headparent.removeView(rl_head); recycler.addHeaderView(rl_head); TextView textView = new TextView(this); textView.setText("我是脚布局"); textView.setBackgroundColor(getResources().getColor(R.color.colorAccent)); ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,50); textView.setGravity(Gravity.CENTER); textView.setLayoutParams(params); recycler.addFootView(textView); mRecylerAdpater = new RecylerAdpater(loadData(0,6)); recycler.setAdapter(mRecylerAdpater); recycler.setLayoutManager(new LinearLayoutManager(this)); recycler.setHasFixedSize(true); onRecyclerClick(); } // 如果连续快速点击,条目的动画会有一个bug,所以使用了一个标记来禁止点击连续点击 boolean isClick = false; private void onRecyclerClick(){ mRecylerAdpater.setOnItemClickLitener(new RecylerAdpater.OnItemClickLitener() { @Override public void onItemClick(View view, int position) { if (!isClick){ isClick = true; Toast.makeText(MainActivity.this, "点了我position" + position, Toast.LENGTH_SHORT).show(); ViewCompat.animate(view).setDuration(200).scaleX(0.9f).scaleY(0.9f).setInterpolator(new CycleInterpolator()) .setListener(new ViewPropertyAnimatorListener() { @Override public void onAnimationStart(View view) {} @Override public void onAnimationEnd(View view) { isClick = false; } @Override public void onAnimationCancel(View view) {} }).withLayer().start(); } } @Override public void onItemLongClick(View view, int position) { Toast.makeText(MainActivity.this, "长按了我position" + position, Toast.LENGTH_SHORT).show(); } }); } private class CycleInterpolator implements android.view.animation.Interpolator { private final float mCycles = 0.5f; @Override public float getInterpolation(final float input) { return (float) Math.sin(2.0f * mCycles * Math.PI * input); } } ArrayList<Item> items = new ArrayList<Item>(); private ArrayList loadData(int start,int end){ items.clear(); for (int i = start; i < end; i++) { items.add(new Item("Item title :" + i,"This is the Item number :" + i)); } return items; } // 模仿访问网络,进行刷新数据 private void initRefresh(){ refresh.setColorSchemeResources(android.R.color.holo_blue_light, android.R.color.holo_red_light,android.R.color.holo_orange_light, android.R.color.holo_green_light); refresh.setProgressBackgroundColorSchemeColor(getResources().getColor(android.R.color.white)); refresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { new Handler().postDelayed(new Runnable() { @Override public void run() { items.clear(); mRecylerAdpater = new RecylerAdpater(loadData(10, 16)); recycler.setAdapter(mRecylerAdpater); mRecylerAdpater.notifyDataSetChanged(); onRecyclerClick(); refresh.setRefreshing(false); } }, 4000); } }); }
然后我们在创建个类RecylerWrapAdapter继承自RecyclerView.Adapter对adapter进行包装:
public class RecylerWrapAdapter extends RecyclerView.Adapter{ private RecyclerView.Adapter mAdapter; private ArrayList<View> mHeaderViews; private ArrayList<View> mFootViews; private final ArrayList<View> EMPTY_INFO_LIST = new ArrayList<View>(); private int mCurrentPosition; public RecylerWrapAdapter(ArrayList<View> mHeaderViews,ArrayList<View> mFootViews,RecyclerView.Adapter mAdapter){ this.mAdapter = mAdapter; if (mHeaderViews == null){ this.mHeaderViews = EMPTY_INFO_LIST; }else{ this.mHeaderViews = mHeaderViews; } if (mFootViews == null){ this.mFootViews = EMPTY_INFO_LIST; }else{ this.mFootViews = mFootViews; } } public int getHeaderCount(){ return mHeaderViews.size(); } public int getFootCount(){ return mFootViews.size(); } /** * 返回该position对应的item的id * @param position * @return */ @Override public long getItemId(int position) { int heads = getHeaderCount(); if (mAdapter != null && position >= heads){ int adjposition = position - heads; //减去头布局的当前位置 int adapterCount = mAdapter.getItemCount(); //总共有多少条目 if (adjposition < adapterCount){ // 当前位置如果是在条目中的 return mAdapter.getItemId(adjposition); } } return -1; } @Override public int getItemCount() { if (mAdapter != null){ return getHeaderCount() + getFootCount() + mAdapter.getItemCount(); }else{ return getHeaderCount() +getFootCount(); } } /** * 判断应该返回的是头布局还是正常子布局还是脚布局 在onCreateViewHolder中使用 * @param position * @return */ @Override public int getItemViewType(int position) { mCurrentPosition = position; int heads = getHeaderCount(); // 也就是说recycle的第一个条目位置为头布局 if (position < heads){ // 返回类型为头布局 return RecyclerView.INVALID_TYPE; } int adjposition = position - heads; //减去头布局后当前布局的位置 int adapterCount = 0; if (mAdapter != null){ adapterCount = mAdapter.getItemCount(); if (adjposition < adapterCount){ //返回类型为正常布局 return mAdapter.getItemViewType(adjposition); } } // 返回类型为脚布局 return RecyclerView.INVALID_TYPE - 1; } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { if (viewType == RecyclerView.INVALID_TYPE){ // 返回头布局 return new HeaderViewHolder(mHeaderViews.get(0)); }else if (viewType == RecyclerView.INVALID_TYPE - 1){ // 返回脚布局 return new HeaderViewHolder(mFootViews.get(0)); } // 返回正常布局 return mAdapter.onCreateViewHolder(parent,viewType); } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { int heads = getHeaderCount(); if (position < heads) return; int adjPosition = position - heads; int adapterCount = 0; if (mAdapter != null){ adapterCount = mAdapter.getItemCount(); if (adjPosition < adapterCount){ // 绑定正常条目数据 mAdapter.onBindViewHolder(holder,adjPosition); return; } } } private class HeaderViewHolder extends RecyclerView.ViewHolder{ public HeaderViewHolder(View itemView) { super(itemView); } } }
现在包装类写完了,但我们的RecyclerView还没有Adapter的,那我们就创建吧,和使用普通RecyclerView的Adapter一样:
public class RecylerAdpater extends RecyclerView.Adapter<RecylerAdpater.MyViewHolder> { private List items; public RecylerAdpater(List list){ super(); items = list; } @Override public int getItemCount() { return items.size(); } @Override public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item,parent,false); return new MyViewHolder(v); } @Override public void onBindViewHolder(final MyViewHolder holder, int position) { Item item = (Item)items.get(position); holder.mTitle.setText(item.getMaintitle()); holder.mSubtitle.setText(item.getSubtitle()); if (mOnItemClickLitener != null){ // 设置点击事件 通过系统view类的回调设置我们的回调 holder.ll_item.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int pos = holder.getLayoutPosition(); mOnItemClickLitener.onItemClick(holder.ll_item,pos); } }); // 设置长按事件 通过系统view类的回调设置我们的回调 holder.ll_item.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { int pos = holder.getLayoutPosition(); mOnItemClickLitener.onItemLongClick(holder.ll_item,pos); return true; } }); } } class MyViewHolder extends RecyclerView.ViewHolder{ TextView mTitle; TextView mSubtitle; LinearLayout ll_item; public MyViewHolder(View itemView) { super(itemView); mTitle = (TextView) itemView.findViewById(R.id.maintitle); mSubtitle = (TextView) itemView.findViewById(R.id.subtitle); ll_item = (LinearLayout) itemView.findViewById(R.id.ll_item); } } //回调接口用于点击事件 public interface OnItemClickLitener{ void onItemClick(View view,int position); void onItemLongClick(View view,int position); } private OnItemClickLitener mOnItemClickLitener; public void setOnItemClickLitener(OnItemClickLitener mOnItemClickLitener){ this.mOnItemClickLitener = mOnItemClickLitener; } }
OK,现在大功告成,我们已经在MainActivity的initRecycler()方法中使用了,运行就可以看到效果了。
对包装类设计模式不熟悉的朋友可能会有些疑问,下面给大家贴出我做的思维导图:
最好的方法还是自己写出来,断点下就清楚这个设计模式和执行流程了。如有哪里不足,欢迎指教。
Reference:
http://www.it165.net/pro/html/201507/48065.html
http://blog.csdn.net/lmj623565791/article/details/45059587
https://github.com/DevLight-Mobile-Agency/NavigationTabBar
项目代码已经发布到github,地址:https://github.com/viewpager/HeadApplication
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories