ListView雖然使用的效果很好可是也是有缺點的android
不使用一些技巧來提高它的運行效率,性能就很是差app
擴展性也不是很好ide
只能實現數據的縱向滾動效果函數
實現橫向滾動是作不到的佈局
Android提供一個更強大的滾動控件---RecylerView性能
是一個加強版的ListViewgradle
不只能夠輕鬆實現和ListView一樣效果優化
還優化了ListView中 存在的不足之處ui
目前官方更推薦使用RecyclerViewthis
將來會有更多的程序主鍵從ListView轉向RecyclerView
一、基本用法
首先再app/build.gradle文件中引入:
compile 'com.android.support:recyclerview-v7:23.4.0'
再first_activity中:
<?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.v7.widget.RecyclerView android:id="@+id/recyler_view" android:layout_width="match_parent" android:layout_height="match_parent"> </android.support.v7.widget.RecyclerView> </LinearLayout>
新建一個適配類
繼承RecyclerView.Adapter,而且將泛型指定爲內部類ViewHolder
public class FruitAdaperRecyler extends RecyclerView.Adapter<FruitAdaperRecyler.ViewHolder> { private List<Fruit> fruitList; @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.fruit_item,null,false); ViewHolder viewHolder = new ViewHolder(view); return viewHolder; } @Override public void onBindViewHolder(ViewHolder holder, int position) { Fruit fruit = fruitList.get(position); holder.textView.setText(fruit.getName()); holder.imageView.setImageResource(fruit.getId()); } @Override public int getItemCount() { return fruitList.size(); } //自定義的內部類 class ViewHolder extends RecyclerView.ViewHolder{ //佈局文件中的兩個控件 ImageView imageView; TextView textView; public ViewHolder(View itemView) { super(itemView); imageView = (ImageView) itemView.findViewById(R.id.image_view); textView = (TextView) itemView.findViewById(R.id.text_view); } } //構造器 public FruitAdaperRecyler(List<Fruit> fruits){ this.fruitList = fruits; } }
首先定義一個內部類ViewHolder
須要繼承RecyclerHolder
而後再構造參數中要傳入一個view參數
這個參數一般就是RecyclerView子項的最外層佈局
那麼就能夠經過findViewById()方法獲取到佈局中的ImageView和TextView的實例
FruitAdaperRecyler類中有一個構造函數就是將要展現的數據傳進來
而且複製給一個全局變量,後續的操做都是在全局變量的基礎上進行的
FruitAdaperRecyler繼承RecyclerView.Adapter就須要實現其中的三個方法
一、omCreateViewHolder()方法就是用於建立viewholder的實例,再方法中將fruit_item佈局加載進來
而後建立一個viewHolder實例,並把加載出來的佈局傳入傳入到構造函數中
最後將viewHolder的實例返回
二、onBinbViewHolder()方法用於對Recycler子項的數據進行賦值,會在每個子項被滾動到屏幕內時執行
這裏經過position參數能夠得到到當前的Fruit的實例,而後進行設置id和name
三、getItemCount()就是返回REcyclerView一共有多少個子項,直接返回數據源的長度便可
mainAcctivity中的代碼:
public class MainActivity extends AppCompatActivity { private List<Fruit> fruitList = new ArrayList<>(); private void initFruit(){ Fruit apple = new Fruit("Apple1",R.drawable.qq); fruitList.add(apple); Fruit apple1 = new Fruit("Apple2",R.drawable.qq); fruitList.add(apple1); Fruit apple2 = new Fruit("Apple3",R.drawable.qq); fruitList.add(apple2); Fruit apple3 = new Fruit("Apple4",R.drawable.qq); fruitList.add(apple3); Fruit apple4 = new Fruit("Apple5",R.drawable.qq); fruitList.add(apple4); Fruit apple5 = new Fruit("Apple6",R.drawable.qq); fruitList.add(apple5); Fruit apple6 = new Fruit("Apple7",R.drawable.qq); fruitList.add(apple6); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.firstlayout); ActionBar actionBar = getSupportActionBar(); if (actionBar != null){ actionBar.hide(); } //初始化 initFruit(); RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyler_view); LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this); recyclerView.setLayoutManager(linearLayoutManager); FruitAdaperRecyler fruitAdaperRecyler = new FruitAdaperRecyler(fruitList); recyclerView.setAdapter(fruitAdaperRecyler); } }
使用initFruit進行初始化數據
再onCreate()方法中首先獲取RecyclerView的實例
而後建立一個LinearLayoutManager對象,在這裏是線性佈局的意思
再進行建立FruitAdapterRecyler的實例
而且將水果的數據傳入
醉胡調用RecyclerView的setAdapter()方法來完成適配器的設置
此時RecyrView和數據之間的關聯創建完成
實現了和ListView幾乎同樣的效果
再實現的過程當中邏輯清晰
文件中的佈局元素都是水平排列的
適用於縱向滾動的場景
實現橫向滾動則須要改爲垂直排列
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="100dp" android:layout_height="match_parent"> <ImageView android:id="@+id/image_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" /> <TextView android:id="@+id/text_view" android:layout_marginTop="10dp" android:layout_gravity="center_horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout>
將LinerLayout改爲垂直方向的排列
此時設置的寬度時100dp
將寬度指定爲固定的值能夠有效的包裹文字,防止其過長或者太短的美觀問題
進行修改代碼:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.firstlayout); ActionBar actionBar = getSupportActionBar(); if (actionBar != null){ actionBar.hide(); } //初始化 initFruit(); RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyler_view); LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this); linearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); recyclerView.setLayoutManager(linearLayoutManager); FruitAdaperRecyler fruitAdaperRecyler = new FruitAdaperRecyler(fruitList); recyclerView.setAdapter(fruitAdaperRecyler); }
之加入了一行代碼
調用LinearLayoutManager的setOrientation()方法來設置不久排列的排列方向
此時的設置表示橫向排列
默認是縱向排列
處LInearLayoutManager以外
還提供了GridLayoutManager、StaggeredGridLayoutManager這兩種內置的佈局排列方式
前者能夠實現網格佈局
後者能夠實現瀑布流佈局
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="5dp"> <ImageView android:id="@+id/image_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" /> <TextView android:id="@+id/text_view" android:layout_marginTop="10dp" android:layout_gravity="center_horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout>
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.firstlayout); ActionBar actionBar = getSupportActionBar(); if (actionBar != null){ actionBar.hide(); } //初始化 initFruit(); RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyler_view); StaggeredGridLayoutManager staggeredGridLayoutManager = new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL); recyclerView.setLayoutManager(staggeredGridLayoutManager); FruitAdaperRecyler fruitAdaperRecyler = new FruitAdaperRecyler(fruitList); recyclerView.setAdapter(fruitAdaperRecyler); }
StaggeredGridLayoutManager staggeredGridLayoutManager = new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL);
第一個參數用於指定列數
第二個參數用於指定佈局的排列方向
結果展現:
全部的點擊事件都有具體的View去註冊
代碼以下:
public class FruitAdaperRecyler extends RecyclerView.Adapter<FruitAdaperRecyler.ViewHolder> { private List<Fruit> fruitList; @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.fruit_item,null,false); final ViewHolder viewHolder = new ViewHolder(view); //點擊事件的監聽 viewHolder.fruitView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int position = viewHolder.getAdapterPosition(); Fruit fruit = fruitList.get(position); Toast.makeText(v.getContext(),"clicked:"+fruit.getName(),Toast.LENGTH_LONG).show(); } }); viewHolder.imageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int position = viewHolder.getAdapterPosition(); Fruit fruit = fruitList.get(position); Toast.makeText(v.getContext(),"click image :" + fruit.getName(),Toast.LENGTH_LONG).show(); } }); return viewHolder; } @Override public void onBindViewHolder(ViewHolder holder, int position) { Fruit fruit = fruitList.get(position); holder.textView.setText(fruit.getName()); holder.imageView.setImageResource(fruit.getId()); } @Override public int getItemCount() { return fruitList.size(); } //自定義的內部類 class ViewHolder extends RecyclerView.ViewHolder{ //佈局文件中的兩個控件 ImageView imageView; TextView textView; View fruitView; public ViewHolder(View itemView) { super(itemView); fruitView=itemView; imageView = (ImageView) itemView.findViewById(R.id.image_view); textView = (TextView) itemView.findViewById(R.id.text_view); } } //構造器 public FruitAdaperRecyler(List<Fruit> fruits){ this.fruitList = fruits; } }
首先是在ViewHolder中添加了fruitView變量來保存子項最外層的佈局實例
而後再onCreateViewHolder()方法中註冊點擊事件
首先是獲取用戶點擊的position
而後經過position獲取用戶拿到享用的Fruit實例
最後將內容進行顯示
點擊文字和圖片均可以正常的進行打印顯示的信息