第一部分
RecyclerVIew是一個可以替代listview和Gallery的有效空間而且在support-v7中有了低版本支持,具體使用方式還是規規矩矩的適配器加控件模式。我們先來看看官網的介紹:
介紹
RecyclerView
is a more advanced and flexible version of ListView
. This widget is a container for large sets of views that can be recycled and scrolled very efficiently. Use the RecyclerView
widget when you have lists with elements that change dynamically.
RecyclerView比listview更先進更靈活,對於很多的視圖它就是一個容器,可以有效的重用和滾動。當數據動態變化的時候請使用它。
RecyclerView
is easy to use, because it provides:
- A layout manager for positioning items
- Default animations for common item operations
- You also have the flexibility to define custom layout managers and animations for this widget.
RecyclerView使用起來很方便因為它提供:
- 它為item的定位提供一個layoutmanager
- 為item的操作提供一個缺省的animations
- 您還可以靈活地定義這個小部件的自定義布局管理器和動畫
To use the RecyclerView
widget, you have to specify an adapter and a layout manager. To create an adapter, you extend the RecyclerView.Adapter
class. The details of the implementation depend on the specifics of your dataset and the type of views. For more information, see the examplesbelow.
為了使用RecyclerVIew,你必須指定一個adapter和一個layoutmanager,為了創建一個adapter,你必須得繼承RecyclerView.Adapter,詳細的實現方法取決與你的數據集和你視圖的類型。
Google官方的一個例子:
1.布局文件activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="${relativePackage}.${activityClass}" > <!-- A RecyclerView with some commonly used attributes --> <android.support.v7.widget.RecyclerView android:id="@+id/my_recycler_view" android:layout_width="match_parent" android:layout_height="match_parent" android:scrollbars="horizontal" /> </RelativeLayout>
2.item的布局文件,就是一個textview
<?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:text="Large Text" android:textAppearance="?android:attr/textAppearanceLarge" />
3.主要代碼
3.1 定義控件和布局
/* * recyclerview提供這些內置的布局管理器: * linearlayoutmanager 顯示垂直滾動列表或水平的項目。 * gridlayoutmanager 顯示在一個網格項目。 * staggeredgridlayoutmanager 顯示在交錯網格項目。 * 自定義的布局管理器,需要繼承recyclerview.layoutmanager類。 * * add/remove items時的動畫是默認啟用的。 * 自定義這些動畫需要繼承RecyclerView.ItemAnimator,並實現RecyclerView.setItemAnimator() */
private RecyclerView mRecyclerView; private RecyclerView.Adapter<MyAdapter.ViewHolder> mAdapter; private LinearLayoutManager mLayoutManager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); String [] myDataset = {"Android","ios","jack","tony","window","mac","1234","hehe","495948"}; mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view); // improve performance if you know that changes in content // do not change the size of the RecyclerView mRecyclerView.setHasFixedSize(true); // use a linear layout manager mLayoutManager = new LinearLayoutManager(this); //設置RecycleView的顯示方向:(默認為垂直) 水平 mLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); mRecyclerView.setLayoutManager(mLayoutManager); // specify an adapter (see also next example) mAdapter = new MyAdapter(myDataset); mRecyclerView.setAdapter(mAdapter); }
3.2 適配器
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> { private String[] mDataset; // Provide a reference to the type of views that you are using // (custom viewholder) public class ViewHolder extends RecyclerView.ViewHolder { public TextView mTextView; public ViewHolder(TextView v) { super(v); mTextView = v; } } // Provide a suitable constructor (depends on the kind of dataset) public MyAdapter(String[] myDataset) { mDataset = myDataset; } // Create new views (invoked by the layout manager) @Override public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { // create a new view View v = LayoutInflater.from(parent.getContext()).inflate( R.layout.my_text_view, parent, false); // set the view's size, margins, paddings and layout parameters ViewHolder vh = new ViewHolder((TextView) v); return vh; } // Replace the contents of a view (invoked by the layout manager) @Override public void onBindViewHolder(ViewHolder holder, int position) { // - get element from your dataset at this position // - replace the contents of the view with that element holder.mTextView.setText(mDataset[position]); } // Return the size of your dataset (invoked by the layout manager) @Override public int getItemCount() { return mDataset.length; } }
全部代碼:
package com.kale.recyclerviewtest; import android.app.Activity; import android.os.Bundle; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; public class MainActivity extends Activity { private RecyclerView mRecyclerView; private RecyclerView.Adapter<MyAdapter.ViewHolder> mAdapter; private LinearLayoutManager mLayoutManager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); String [] myDataset = {"Android","ios","jack","tony","window","mac","1234","hehe","495948"}; mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view); // improve performance if you know that changes in content // do not change the size of the RecyclerView mRecyclerView.setHasFixedSize(true); // use a linear layout manager mLayoutManager = new LinearLayoutManager(this); //設置RecycleView的顯示方向:(默認為垂直) 水平 mLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); mRecyclerView.setLayoutManager(mLayoutManager); // specify an adapter (see also next example) mAdapter = new MyAdapter(myDataset); mRecyclerView.setAdapter(mAdapter); } public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> { private String[] mDataset; // Provide a reference to the type of views that you are using // (custom viewholder) public class ViewHolder extends RecyclerView.ViewHolder { public TextView mTextView; public ViewHolder(TextView v) { super(v); mTextView = v; } } // Provide a suitable constructor (depends on the kind of dataset) public MyAdapter(String[] myDataset) { mDataset = myDataset; } // Create new views (invoked by the layout manager) @Override public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { // create a new view View v = LayoutInflater.from(parent.getContext()).inflate( R.layout.my_text_view, parent, false); // set the view's size, margins, paddings and layout parameters ViewHolder vh = new ViewHolder((TextView) v); return vh; } // Replace the contents of a view (invoked by the layout manager) @Override public void onBindViewHolder(ViewHolder holder, int position) { // - get element from your dataset at this position // - replace the contents of the view with that element holder.mTextView.setText(mDataset[position]); } // Return the size of your dataset (invoked by the layout manager) @Override public int getItemCount() { return mDataset.length; } } }
PS:這個控件好就好在可以自定義動畫和布局的方向,在以前還需要我們自己寫橫向滑動的listview,現在有了它就方便多了。但缺點是沒有listview那么完善,沒添加頭、尾視圖的功能。再說下它的動畫和布局類,以后用到的話就知道了。
(1)為每個條目位置提供了layout管理器(RecyclerView.setLayoutManager)
(2)為每個條目設置了操作動畫(RecyclerView.setItemAnimator)
第二部分
現在我們知道它是什么,怎么用了后。我們就想自己實現點擊效果,要知道它是不提供itemclicklistner的,所以需要換個思路,在viewHolder中進行實現。其實這樣的分離讓代碼更加簡單和便於維護了。下面的代碼僅僅是概要演示,具體實際操作中我們完全可以利用viewholder來提升滑動的性能,如果viewHolder 中有這個視圖那么就調出,如果沒有那么就重新findviewById。
1.viewHolder
viewholder中傳入了一個父視圖,直接綁定監聽器。然后根據需要找到子視圖,進行操作。
/** * @author:Jack Tony * @tips :寫一個viewHolder,用來得到控件。 * @date :2014-11-1 */ public class MyViewHolder extends RecyclerView.ViewHolder implements OnClickListener,OnLongClickListener{ private TextView mTextView; private int mPosition; public MyViewHolder(View rootView) { super(rootView); //給父控件綁定監聽器 rootView.setOnClickListener(this); //通過findviewbyId找到item中的控件進行設置 mTextView = (TextView)rootView.findViewById(R.id.textView1); ImageView imageView = (ImageView)rootView.findViewById(R.id.imageView1); imageView.setImageResource(R.drawable.kale); } public void setPosition(int position) { mPosition = position; } @Override public boolean onLongClick(View v) { // TODO 自動生成的方法存根 return false; } @Override public void onClick(View v) { // TODO 自動生成的方法存根 Toast.makeText(MainActivity.this, "click "+mPosition, 0).show(); } }
2.Adapter
因為用了自己寫的MyHolder,所以這里類的泛型中應該傳入自己的這個viewHolder的類名。具體寫法還是和第一部分中的寫法一樣,甚至簡單了很多。因為這里我們只需要關系數據源和位置即可。
/** * @author:Jack Tony * @tips :這里面完全可以根據viewholder是否為null進行優化 * @date :2014-11-1 */ public class Adapter extends RecyclerView.Adapter<MyViewHolder>{ private String[] mDataset; private MyViewHolder mViewHoder; public Adapter(String[] myDataset) { mDataset = myDataset; } @Override public int getItemCount() { // TODO 自動生成的方法存根 return mDataset.length; } @Override public void onBindViewHolder(MyViewHolder holder, int position) { mViewHoder.mTextView.setText(mDataset[position]); mViewHoder.setPosition(position); } @Override public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false); mViewHoder = new MyViewHolder(v); return mViewHoder; } }
3.Animation
通過繼承RecyclerView.ItemAnimator這個類就可以給RecylerView添加item動畫,至於具體的實現網上沒有什么資料。所以我這里也沒想出怎么玩的,以后再補上吧。這里先給出空實現。
public class MyAnim extends RecyclerView.ItemAnimator{ @Override public boolean animateAdd(ViewHolder arg0) { // TODO 自動生成的方法存根 return false; } @Override public boolean animateChange(ViewHolder arg0, ViewHolder arg1, int arg2, int arg3, int arg4, int arg5) { // TODO 自動生成的方法存根 return false; } @Override public boolean animateMove(ViewHolder holder, int fromX, int fromY, int toX, int toY) { // TODO 自動生成的方法存根 return false; } @Override public boolean animateRemove(ViewHolder arg0) { // TODO 自動生成的方法存根 return false; } @Override public void endAnimation(ViewHolder arg0) { // TODO 自動生成的方法存根 } @Override public void endAnimations() { // TODO 自動生成的方法存根 } @Override public boolean isRunning() { // TODO 自動生成的方法存根 return false; } @Override public void runPendingAnimations() { // TODO 自動生成的方法存根 } }
mRecyclerView.setItemAnimator(new MyAnim());
全部代碼:
package com.kale.recyclerviewtest; import android.app.Activity; import android.os.Bundle; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView.ViewHolder; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnLongClickListener; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends Activity { private RecyclerView mRecyclerView; private Adapter mAdapter; private LinearLayoutManager mLayoutManager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); String [] myDataset = {"Android","ios","jack","tony","window","mac","C#","hehe","C++"}; mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view); // improve performance if you know that changes in content // do not change the size of the RecyclerView mRecyclerView.setHasFixedSize(true); // use a linear layout manager mLayoutManager = new LinearLayoutManager(this); //設置RecycleView的顯示方向:(默認為垂直) 水平 mLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); mRecyclerView.setLayoutManager(mLayoutManager); // specify an adapter (see also next example) mAdapter = new Adapter(myDataset); mRecyclerView.setAdapter(mAdapter); mRecyclerView.setItemAnimator(new MyAnim()); } /** * @author:Jack Tony * @tips :寫一個viewHolder,用來得到控件。 * @date :2014-11-1 */ public class MyViewHolder extends RecyclerView.ViewHolder implements OnClickListener,OnLongClickListener{ private TextView mTextView; private int mPosition; public MyViewHolder(View rootView) { super(rootView); //給父控件綁定監聽器 rootView.setOnClickListener(this); //通過findviewbyId找到item中的控件進行設置 mTextView = (TextView)rootView.findViewById(R.id.textView1); ImageView imageView = (ImageView)rootView.findViewById(R.id.imageView1); imageView.setImageResource(R.drawable.kale); } public void setPosition(int position) { mPosition = position; } @Override public boolean onLongClick(View v) { // TODO 自動生成的方法存根 return false; } @Override public void onClick(View v) { // TODO 自動生成的方法存根 Toast.makeText(MainActivity.this, "click "+mPosition, 0).show(); } } /** * @author:Jack Tony * @tips :這里面完全可以根據viewholder是否為null進行優化 * @date :2014-11-1 */ public class Adapter extends RecyclerView.Adapter<MyViewHolder>{ private String[] mDataset; private MyViewHolder mViewHoder; public Adapter(String[] myDataset) { mDataset = myDataset; } @Override public int getItemCount() { // TODO 自動生成的方法存根 return mDataset.length; } @Override public void onBindViewHolder(MyViewHolder holder, int position) { mViewHoder.mTextView.setText(mDataset[position]); mViewHoder.setPosition(position); } @Override public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false); mViewHoder = new MyViewHolder(v); return mViewHoder; } } public class MyAnim extends RecyclerView.ItemAnimator{ @Override public boolean animateAdd(ViewHolder arg0) { // TODO 自動生成的方法存根 return false; } @Override public boolean animateChange(ViewHolder arg0, ViewHolder arg1, int arg2, int arg3, int arg4, int arg5) { // TODO 自動生成的方法存根 return false; } @Override public boolean animateMove(ViewHolder holder, int fromX, int fromY, int toX, int toY) { // TODO 自動生成的方法存根 return false; } @Override public boolean animateRemove(ViewHolder arg0) { // TODO 自動生成的方法存根 return false; } @Override public void endAnimation(ViewHolder arg0) { // TODO 自動生成的方法存根 } @Override public void endAnimations() { // TODO 自動生成的方法存根 } @Override public boolean isRunning() { // TODO 自動生成的方法存根 return false; } @Override public void runPendingAnimations() { // TODO 自動生成的方法存根 } } }
源碼下載:http://download.csdn.net/detail/shark0017/8110309
參考自:
http://blog.csdn.net/jjwwmlp456/article/details/40540233
http://blog.csdn.net/a396901990/article/details/40187769
http://blog.csdn.net/guxiao1201/article/details/40423361