編輯:關於Android編程
RecyclerView與ListView原理是類似的:都是僅僅維護少量的View並且可以展示大量的數據集。RecyclerView用以下兩種方式簡化了數據的展示和處理:
使用LayoutManager來確定每一個item的排列方式。
為增加和刪除項目提供默認的動畫效果。
RecyclerView雖然作為ListView的替代者有著較好的性能提升,但是ListView的一些常用功能卻沒有提供,比如我們平時會經常用到的addHeaderView,addFooterView,既然RecyclerView沒有提供這個方法,我們應該如何為列表添加頭部和底部呢?通過看ListView的源碼可以知道ListView的添加Header和Footer是靠Adapter裡面動態添加的,所以我們按照這個思路也給RecyclerView添加HeaderView和FooterView,先看一下效果
如果你還不了解RecyclerView如何使用,可以看一下前幾篇博文
RecyclerView的使用之HelloWorld
RecyclerView的使用之多Item布局的加載
RecyclerView實現添加HeaderView和FooterView的核心就是在Adapter裡面的onCreateViewHolder根據viewType來判斷是列表項還是HeaderView來分別加載不同的布局文件,當然viewType的判斷規則也是由我們定義的,廢話不多說,看一下具體的實現效果。
1:Gradle配置 build.gradle
compile 'com.android.support:recyclerview-v7:23.1.1' compile 'com.android.support:cardview-v7:23.1.1'
2:主布局文件 activity_main.xml 很簡單裡面一個RecyclerView
<?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 xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/rv_list" /> </LinearLayout>
3:列表項布局 rv_item.xml 外面一個CardView的卡片式容器裡面一個TextView
<?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto" xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="8dp" android:id="@+id/cv_item" android:foreground="?android:attr/selectableItemBackground" card_view:cardCornerRadius="4dp" card_view:cardElevation="4dp" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/tv_item_text" android:text="test" android:layout_margin="8dp" /> </LinearLayout> </android.support.v7.widget.CardView>
4:列表頭部布局 rv_header.xml
<?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto" xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="8dp" android:id="@+id/cv_item" android:foreground="?android:attr/selectableItemBackground" card_view:cardCornerRadius="4dp" card_view:cardElevation="4dp" card_view:cardBackgroundColor="#4CAF50" > <LinearLayout android:layout_width="match_parent" android:layout_height="150dp" > <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:text="Header" android:textSize="30sp" android:textColor="#ffffff" android:gravity="center" /> </LinearLayout> </android.support.v7.widget.CardView>
5:列表底部布局 rv_footer.xml
<?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto" xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="8dp" android:id="@+id/cv_item" android:foreground="?android:attr/selectableItemBackground" card_view:cardCornerRadius="4dp" card_view:cardElevation="4dp" card_view:cardBackgroundColor="#E91E63" > <LinearLayout android:layout_width="match_parent" android:layout_height="150dp" > <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:text="Footer" android:textSize="30sp" android:textColor="#ffffff" android:gravity="center" /> </LinearLayout> </android.support.v7.widget.CardView>
6:*HeaderBottomAdapter.java,RecyclerView的Adapter,在getItemViewType方法裡面判斷了當前Item的類型,然後在onCreateViewHolder跟據item的類型分別加載不同的布局以實現HeaderView和FooterView,其他方法的含義可以參考注釋
import android.content.Context; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; /** * Created by Lijizhou on 2016/2/24. * Blog:http://blog.csdn.net/leejizhou * QQ:3107777777 */ public class HeaderBottomAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { //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; //模擬數據 public String [] texts={"java","python","C++","Php",".NET","js","Ruby","Swift","OC"}; private LayoutInflater mLayoutInflater; private Context mContext; private int mHeaderCount=1;//頭部View個數 private int mBottomCount=1;//底部View個數 public HeaderBottomAdapter(Context context) { mContext = context; mLayoutInflater = LayoutInflater.from(context); } //內容長度 public int getContentItemCount(){ return texts.length; } //判斷當前item是否是HeadView public boolean isHeaderView(int position) { return mHeaderCount != 0 && position < mHeaderCount; } //判斷當前item是否是FooterView public boolean isBottomView(int position) { return mBottomCount != 0 && position >= (mHeaderCount + getContentItemCount()); } //判斷當前item類型 @Override public int getItemViewType(int position) { int dataItemCount = getContentItemCount(); if (mHeaderCount != 0 && position < mHeaderCount) { //頭部View return ITEM_TYPE_HEADER; } else if (mBottomCount != 0 && position >= (mHeaderCount + dataItemCount)) { //底部View return ITEM_TYPE_BOTTOM; } else { //內容View return ITEM_TYPE_CONTENT; } } //內容 ViewHolder public static class ContentViewHolder extends RecyclerView.ViewHolder { private TextView textView; public ContentViewHolder(View itemView) { super(itemView); textView=(TextView)itemView.findViewById(R.id.tv_item_text); } } //頭部 ViewHolder public static class HeaderViewHolder extends RecyclerView.ViewHolder { public HeaderViewHolder(View itemView) { super(itemView); } } //底部 ViewHolder public static class BottomViewHolder extends RecyclerView.ViewHolder { public BottomViewHolder(View itemView) { super(itemView); } } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { if (viewType ==ITEM_TYPE_HEADER) { return new HeaderViewHolder(mLayoutInflater.inflate(R.layout.rv_header, parent, false)); } else if (viewType == mHeaderCount) { return new ContentViewHolder(mLayoutInflater.inflate(R.layout.rv_item, parent, false)); } else if (viewType == ITEM_TYPE_BOTTOM) { return new BottomViewHolder(mLayoutInflater.inflate(R.layout.rv_footer, parent, false)); } return null; } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { if (holder instanceof HeaderViewHolder) { } else if (holder instanceof ContentViewHolder) { ((ContentViewHolder) holder).textView.setText(texts[position - mHeaderCount]); } else if (holder instanceof BottomViewHolder) { } } @Override public int getItemCount() { return mHeaderCount + getContentItemCount() + mBottomCount; } }
7:最後一步,MainActivity.java
import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; public class MainActivity extends AppCompatActivity { private RecyclerView mRecyclerView; private HeaderBottomAdapter adapter; GridLayoutManager gridLayoutManager; LinearLayoutManager layoutManager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mRecyclerView=(RecyclerView)findViewById(R.id.rv_list); //List布局 layoutManager=new LinearLayoutManager(this); layoutManager.setOrientation(LinearLayoutManager.VERTICAL); mRecyclerView.setLayoutManager(layoutManager); mRecyclerView.setAdapter(adapter=new HeaderBottomAdapter(this)); //Grid布局 // gridLayoutManager=new GridLayoutManager(MainActivity.this, 2); // mRecyclerView.setLayoutManager(gridLayoutManager);//這裡用線性宮格顯示 類似於grid view // mRecyclerView.setAdapter(adapter=new HeaderBottomAdapter(this)); // // // gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { // @Override // public int getSpanSize(int position) { // return (adapter.isHeaderView(position) || adapter.isBottomView(position)) ? gridLayoutManager.getSpanCount() : 1; // } // }); } }
這裡注意一點,如果你的RecyclerView使用Grid類型列表在設置Adapter後需要調用這個方法,根據當前Item類型來判斷占據的橫向格數,這也是Adapter裡面實現isHeaderView和isBottomView的緣故
gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { @Override public int getSpanSize(int position) { return (adapter.isHeaderView(position) || adapter.isBottomView(position)) ? gridLayoutManager.getSpanCount() : 1; } });
Ok,RecyclerView添加Header和Footer就這樣輕松實現了,你也可以把Adapter再次封裝更有利於日常的開發。
關於使用RecyclerView添加Header和Footer的方法就給大家介紹到這裡,希望對大家有所幫助!
在前面的第二篇文章中,我們提過,View的事件分發是一種委托思想:上層委托下層,父容器委托子元素來處理這個流程。接下來,我們就將深入去學習View的事件分發機制。&nbs
ListView的下拉刷新很常見,很多開源的框架都能做到這個效果,當然也可以自己去實現。本篇案例是基於xlistview的。布局:<RelativeLayout x
(一)概述本節,我們繼續來研究Service(服務)組件,本節將會學習下Android中的AIDL跨進程通信的一些 概念,並不深入到源碼層次,暫時知道是什麼,會用即可!(
本文講述aidl的簡單使用首先我們來看綁定本地service的用法:第一步:創建接口和實體類public interface IController { publi