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);
效果圖:

