1.RecyclerView :出现也不知道多久了,没怎么使用过,上次写的笔记乱七八糟的,再次仔细的整理下。
使用需加入依赖
compile 'com.android.support:recyclerview-v7:25.2.0'
2.总结一下内容
<1>可以实现横向滑动
<2>可以实现纵向滑动
<3>可以实现瀑布流
<4>可以实现吸顶模式
<5>加入自定义分割线
<6>实现数据分组效果
3.先实现ListView的效果图,实现下拉刷新,上划加载更多
实现下拉刷新需要借助SwipeRefreshLayout 嵌套在recyclerView的外部
android.support.v4.widget.SwipeRefreshLayout
上划加载更多可以依靠recyclerView的自身监听 addOnScrollListener 当newState==RecyclerView.SCROLL_STATE_IDLE则代表滑动到了底部,然后执行加载 更多的操作。效果图:
4.看实现代码:
布局还有一个recyclerView和SwipeRefreshLayout
<android.support.v4.widget.SwipeRefreshLayout android:layout_height="match_parent" android:layout_width="match_parent" android:id="@+id/swipeRefreshLayout"> <android.support.v7.widget.RecyclerView android:layout_height="match_parent" android:layout_width="match_parent" android:id="@+id/recyclerView"/> </android.support.v4.widget.SwipeRefreshLayout>
条目布局一个ImageView和一个textView
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:orientation="horizontal" android:layout_height="60dp"> <ImageView android:layout_height="60dp" android:layout_width="60dp" android:id="@+id/imageView" android:scaleType="centerCrop" android:src="@mipmap/image"/> <TextView android:layout_width="match_parent" android:layout_height="60dp" android:gravity="center_horizontal|center_vertical" android:textColor="@color/colorPrimary" android:id="@+id/textView"/> </LinearLayout>
adapter继承了RecyclerView.Adapter其泛型为ViewHolder,viewholder继承RecyclerView.ViewHolder。
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder>{ List<String> data; Context context; public RecyclerViewAdapter(Context context, List<String> data) { this.context = context; this.data = data; } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view= LayoutInflater.from(context).inflate(R.layout.recycleritem_layout,parent,false); final ViewHolder holder=new ViewHolder(view); holder.imageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int position=holder.getAdapterPosition(); Toast.makeText(context,"点击了第"+position+"个图片",Toast.LENGTH_SHORT).show(); } }); holder.textView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int position=holder.getAdapterPosition(); Toast.makeText(context,"点击了第"+position+"个文字条目",Toast.LENGTH_SHORT).show(); } }); return holder; } @Override public void onBindViewHolder(ViewHolder holder, int position) { String s=data.get(position); holder.textView.setText(s); } @Override public int getItemCount() { return data.size(); } class ViewHolder extends RecyclerView.ViewHolder{ View viewItem; ImageView imageView; TextView textView; public ViewHolder(View itemView) { super(itemView); viewItem=itemView; imageView= (ImageView) itemView.findViewById(R.id.imageView); textView= (TextView) itemView.findViewById(R.id.textView); } } }
在activity中初始了数据,并加载,其中
linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
设置了recyclerView的滑动方向为垂直,这里也可以设置为水平方向的滑动。
public class MainActivity extends AppCompatActivity { private static final String TAG = "MainActivity"; RecyclerView recyclerView; List<String>data=new ArrayList<>(); SwipeRefreshLayout swipeRefreshLayout; RecyclerViewAdapter recyclerViewAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); recyclerView= (RecyclerView) findViewById(R.id.recyclerView); swipeRefreshLayout= (SwipeRefreshLayout) findViewById(R.id.swipeRefreshLayout); for(int i=0;i<15;i++){ data.add("第"+i+"项数据"); } LinearLayoutManager linearLayoutManager=new LinearLayoutManager(this); linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); recyclerView.setLayoutManager(linearLayoutManager); recyclerViewAdapter=new RecyclerViewAdapter(this,data); recyclerView.setAdapter(recyclerViewAdapter); /** * 刷新 */ swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { handler.sendEmptyMessageDelayed(100,100); } }); /** * 加载更多 */ recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState);
// 这里在加入判断,判断是否滑动到底部 if(newState==RecyclerView.SCROLL_STATE_IDLE){ List<String> dataNew=new ArrayList<>(); for(int i=0;i<30;i++){ dataNew.add("加载更多后第"+i+"项数据"); } data.addAll(dataNew); recyclerViewAdapter.notifyDataSetChanged(); } } }); } Handler handler=new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); List<String> dataNew=new ArrayList<>(); for(int i=0;i<30;i++){ dataNew.add("刷新后第"+i+"项数据"); } data.clear(); data.addAll(0,dataNew); //data.add(0, "下拉刷新出来的数据"); swipeRefreshLayout.setRefreshing(false); recyclerViewAdapter.notifyDataSetChanged(); } }; }
5.判断是否滑动到底部
在滑动停止时,判断是否滑动到底部,然后在判断是否需要加载更多
public static boolean isSlideToBottom(RecyclerView recyclerView) { if (recyclerView == null) return false; if (recyclerView.computeVerticalScrollExtent() + recyclerView.computeVerticalScrollOffset() >= recyclerView.computeVerticalScrollRange()) return true; return false; }
5.给Recyclerview加上头布局和底部布局。
重新recyclerViewAdapter里面的getItemViewType方法,判断itemview是内容还是头布局或底部布局。
@Override public int getItemViewType(int position) { if (headeraccount != 0 && position < headeraccount) { /** * 头部 */ return ITEM_TYPE_HEADER; } else if (footaccount != 0 && position >= (headeraccount + data.size())) { /** * 尾部 */ return ITEM_TYPE_BOTTOM; } else { /** * 有效数据 */ return ITEM_TYPE_CONTENT; } }
adapter代码:
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{ List<String> data; Context context; int headeraccount=1; int footaccount=1; //item类型 public static final int ITEM_TYPE_HEADER = 0; public static final int ITEM_TYPE_CONTENT = 1; public static final int ITEM_TYPE_BOTTOM = 2; @Override public int getItemViewType(int position) { if (headeraccount != 0 && position < headeraccount) { /** * 头部 */ return ITEM_TYPE_HEADER; } else if (footaccount != 0 && position >= (headeraccount + data.size())) { /** * 尾部 */ return ITEM_TYPE_BOTTOM; } else { /** * 有效数据 */ return ITEM_TYPE_CONTENT; } } public RecyclerViewAdapter(Context context, List<String> data) { this.context = context; this.data = data; } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { if (viewType == ITEM_TYPE_HEADER) { return new HeaderViewHolder(LayoutInflater.from(context).inflate(R.layout.header_layout, parent, false)); } if (viewType == ITEM_TYPE_BOTTOM) { return new HeaderViewHolder(LayoutInflater.from(context).inflate(R.layout.header_layout, parent, false)); } if (viewType == ITEM_TYPE_CONTENT) { View view = LayoutInflater.from(context).inflate(R.layout.recycleritem_layout, parent, false); final ContextViewHolder holder = new ContextViewHolder(view); holder.imageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int position = holder.getAdapterPosition(); Toast.makeText(context, "点击了第" + position + "个图片", Toast.LENGTH_SHORT).show(); } }); holder.textView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int position = holder.getAdapterPosition(); Toast.makeText(context, "点击了第" + position + "个文字条目", Toast.LENGTH_SHORT).show(); } }); return holder; } return null; } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { if(holder instanceof HeaderViewHolder){ }else if(holder instanceof FootViewHolder){ }else if(holder instanceof ContextViewHolder){ String s= data.get(position-headeraccount); ((ContextViewHolder) holder).textView.setText(s); } } @Override public int getItemCount() { return data.size()+headeraccount+footaccount; } class ContextViewHolder extends RecyclerView.ViewHolder{ View viewItem; ImageView imageView; TextView textView; public ContextViewHolder(View itemView) { super(itemView); viewItem=itemView; imageView= (ImageView) itemView.findViewById(R.id.imageView); textView= (TextView) itemView.findViewById(R.id.textView); } } class FootViewHolder extends RecyclerView.ViewHolder{ public FootViewHolder(View itemView) { super(itemView); } } class HeaderViewHolder extends RecyclerView.ViewHolder{ public HeaderViewHolder(View itemView) { super(itemView); } } }
头布局和底部布局都只是一个imageView
<?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="100dp"> <ImageView android:layout_height="100dp" android:layout_width="match_parent" android:scaleType="centerCrop" android:src="@mipmap/img"/> </LinearLayout>
实现效果图:
6.给recyclerView添加item分割线
继承 RecyclerView.ItemDecoration
public class SpacesItemDecoration extends RecyclerView.ItemDecoration{ private int dividerHeight; private Paint paint; public SpacesItemDecoration(Context context) { dividerHeight = context.getResources().getDimensionPixelSize(R.dimen.margin); paint=new Paint(); paint.setColor(context.getResources().getColor(R.color.colorAccent)); } @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { super.getItemOffsets(outRect, view, parent, state); /** * 类似加了一个bottom的padding */ outRect.bottom = dividerHeight; } @Override public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { super.onDraw(c, parent, state); int childCount = parent.getChildCount(); int left = parent.getPaddingLeft(); int right = parent.getWidth() - parent.getPaddingRight(); for (int i = 0; i < childCount - 1; i++) { View view = parent.getChildAt(i); float top = view.getBottom(); float bottom = view.getBottom() + dividerHeight; /** * 绘制的矩形也就是从,item的左上角,到右下角,类似于背景, * 正好显示出一个横线,就是getItemOffsets空出来的范围 * */ c.drawRect(left, top, right, bottom, paint); } } }
recyclerView.setAdapter(recyclerViewAdapter); SpacesItemDecoration decoration=new SpacesItemDecoration(getApplicationContext()); recyclerView.addItemDecoration(decoration);
效果图: