前言
專注于為中小企業(yè)提供網(wǎng)站建設(shè)、網(wǎng)站制作服務(wù),電腦端+手機(jī)端+微信端的三站合一,更高效的管理,為中小企業(yè)山西免費(fèi)做網(wǎng)站提供優(yōu)質(zhì)的服務(wù)。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動(dòng)了1000多家企業(yè)的穩(wěn)健成長(zhǎng),幫助中小企業(yè)通過(guò)網(wǎng)站建設(shè)實(shí)現(xiàn)規(guī)模擴(kuò)充和轉(zhuǎn)變。
我們大家都知道ListView具有添加頭部和添加底部的方法,但是RecyclerView并沒(méi)有這樣子的方法。所以RecyclerView是不能添加底部和頭部的,但是能不能仿造ListView來(lái)實(shí)現(xiàn)RecyclerView添加頭部和底部呢?答案當(dāng)然是可行的。本文就來(lái)給大家介紹了關(guān)于Android封裝RecyclerView添加頭部和底部的相關(guān)內(nèi)容,分享出來(lái)供大家參考學(xué)習(xí),下面話不多說(shuō)了,來(lái)一起看看詳細(xì)的介紹吧。
首先看下實(shí)現(xiàn)的效果:

代碼如下:
public class WrapMyRecyclerView extends RecyclerView {
private Adapter mAdapter;
private ArrayList<View> mHeaderViewInfos = new ArrayList<>();//保存headerView
private ArrayList<View> mFooterViewInfos = new ArrayList<>();//保存footerView
public WrapMyRecyclerView(Context context) {
super(context);
}
public WrapMyRecyclerView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public WrapMyRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
/**
* 添加headerView
* @param v
*/
public void addHeaderView(View v) {
mHeaderViewInfos.add(v);
// Wrap the adapter if it wasn't already wrapped.
if (mAdapter != null) {
if (!(mAdapter instanceof RecyclerHeaderViewListAdapter)) {
wrapHeaderListAdapterInternal();
}
}
}
/**
* 添加一個(gè)footerView
* @param v
*/
public void addFooterView(View v) {
mFooterViewInfos.add(v);
// Wrap the adapter if it wasn't already wrapped.
if (mAdapter != null) {
if (!(mAdapter instanceof RecyclerHeaderViewListAdapter)) {
wrapHeaderListAdapterInternal();
}
}
}
/**
* 設(shè)置一個(gè)Adapter
* @param adapter
*/
@Override
public void setAdapter(Adapter adapter) {
if (mHeaderViewInfos.size() > 0 || mFooterViewInfos.size() > 0) {
mAdapter = wrapHeaderListAdapterInternal(mHeaderViewInfos, mFooterViewInfos, adapter);
} else {
mAdapter = adapter;
}
super.setAdapter(mAdapter);
}
private void wrapHeaderListAdapterInternal() {
mAdapter = wrapHeaderListAdapterInternal(mHeaderViewInfos, mFooterViewInfos, mAdapter);
}
/**
* 新建一個(gè)RecyclerHeaderViewListAdapter對(duì)象
* 最終的adapter實(shí)現(xiàn)它
* @param headerViewInfos
* @param footerViewInfos
* @param adapter
* @return
*/
protected RecyclerHeaderViewListAdapter wrapHeaderListAdapterInternal(
ArrayList<View> headerViewInfos,
ArrayList<View> footerViewInfos,
Adapter adapter) {
return new RecyclerHeaderViewListAdapter(headerViewInfos, footerViewInfos, adapter);
}
}這就是封裝的RecyclerView,里面主要有三個(gè)方法addHeaderView、 addFooterView和重寫(xiě)的setAdapter。這里的唯一的思想就是偷梁換柱,當(dāng)我們添加頭部、尾部或者設(shè)置adapter時(shí),真正的adapter并不是我們傳入的adapter,而是重新new 了一個(gè)RecyclerHeaderViewListAdapter。這才是RecyclerView最終設(shè)置的adapter。
其實(shí)我們看到ListView也是通過(guò)這樣子的思想來(lái)添加頭部和尾部的。

這就是ListView的addHeaderView方法,它會(huì)偷偷的創(chuàng)建HeaderViewListAdapter這個(gè)adapter。最終添加的header和footer在HeaderViewListAdapter里面實(shí)現(xiàn)。
public class RecyclerHeaderViewListAdapter extends RecyclerView.Adapter {
private final ArrayList<View> mHeaderViewInfos;//保存headerview數(shù)據(jù)
private final ArrayList<View> mFooterViewInfos;//保存footerView數(shù)據(jù)
private RecyclerView.Adapter mAdapter; //用戶自己構(gòu)造的adapter
private static final int RECYCLER_HEADER_VIEW = 0x001;//headerview類型
private static final int RECYCLER_FOOTER_VIEW = 0x002;//footerView類型
/**
* 構(gòu)造方法
* 初始化
* @param headerViewInfos
* @param footerViewInfos
* @param adapter
*/
public RecyclerHeaderViewListAdapter(ArrayList<View> headerViewInfos,
ArrayList<View> footerViewInfos,
RecyclerView.Adapter adapter) {
mAdapter = adapter;
if (headerViewInfos == null) {
mHeaderViewInfos = new ArrayList<>();
} else {
mHeaderViewInfos = headerViewInfos;
}
if (footerViewInfos == null) {
mFooterViewInfos = new ArrayList<>();
} else {
mFooterViewInfos = footerViewInfos;
}
}
/**
* 根據(jù)getItemViewType返回的條目類型
* 創(chuàng)建不同的itemview
* 傳入的adapter,回調(diào)它的onCreateViewHolder即可
* @param parent
* @param viewType
* @return
*/
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == RECYCLER_HEADER_VIEW){
return new HeaderViewLayout(mHeaderViewInfos.get(0));
}else if (viewType == RECYCLER_FOOTER_VIEW){
return new HeaderViewLayout(mFooterViewInfos.get(0));
}
return mAdapter.onCreateViewHolder(parent,viewType);
}
/**
* 綁定數(shù)據(jù)
* headerview和footerview不需要綁定數(shù)據(jù),直接return即可
* 傳入的adapter需要回調(diào)它的onBindViewHolder即可
* @param holder
* @param position
*/
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
//header
int numHeaders = getHeadersCount();
if (position < numHeaders) {
return ;
}
//adapter body
final int adjPosition = position - numHeaders;
int adapterCount = 0;
if (mAdapter != null) {
adapterCount = mAdapter.getItemCount();
if (adjPosition < adapterCount) {
mAdapter.onBindViewHolder(holder, adjPosition);
return ;
}
}
//footer
}
/**
* 返回條目的類型
* 傳入的adapter,回調(diào)它的getItemViewType即可
* @param position
* @return
*/
@Override
public int getItemViewType(int position) {
// Header
int numHeaders = getHeadersCount();
if (position < numHeaders) {
return RECYCLER_HEADER_VIEW;
}
// Adapter
final int adjPosition = position - numHeaders;
int adapterCount = 0;
if (mAdapter != null) {
adapterCount = mAdapter.getItemCount();
if (adjPosition < adapterCount) {
return mAdapter.getItemViewType(position);
}
}
// Footer (off-limits positions will throw an IndexOutOfBoundsException)
return RECYCLER_FOOTER_VIEW;
}
/**
* 總條目即:footerview的條目+headerview的條目+穿入的adapter條目
* @return
*/
@Override
public int getItemCount() {
if (mAdapter != null) {
return getFootersCount() + getHeadersCount() + mAdapter.getItemCount();
} else {
return getFootersCount() + getHeadersCount();
}
}
/**
* 獲取headerview的條目
* @return
*/
public int getHeadersCount() {
return mHeaderViewInfos.size();
}
/**
* 獲取footervie的條目
* @return
*/
public int getFootersCount() {
return mFooterViewInfos.size();
}
/**
* 這是footerview和headerview的ViewHolder需要
* 這里只是提供一個(gè)構(gòu)造器即可,實(shí)際上用處不大
*/
private static class HeaderViewLayout extends RecyclerView.ViewHolder{
public HeaderViewLayout(View itemView) {
super(itemView);
}
}
}這是實(shí)現(xiàn)添加header、footer和傳入adapter的RecyclerHeaderViewListAdapter。具體的邏輯都在文件的注釋里面有說(shuō)明。邏輯是仿造ListView的HeaderViewListAdapter來(lái)實(shí)現(xiàn)的。
其實(shí)就是創(chuàng)建一個(gè)adapter,然后根據(jù)不同的條目類型來(lái)創(chuàng)建條目和綁定條目的數(shù)據(jù)即可。
<?xml version="1.0" encoding="utf-8"?> <LinearLayout 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" android:orientation="vertical" tools:context="com.wrap.recycler.WrapRecyclerViewActivity"> <com.lwj.wrap.recycler.WrapMyRecyclerView android:id="@+id/wrap_recyclerview" android:layout_width="match_parent" android:layout_height="match_parent"/> </LinearLayout>
這是布局文件
public class WrapRecyclerViewActivity extends AppCompatActivity {
private WrapMyRecyclerView mRecyclerView;
private MyAdapter mMyAdapter;
private List<String> mList01 = new ArrayList<>();
private static final int WC = ViewGroup.LayoutParams.WRAP_CONTENT;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_wrap_recycler_view);
getData();
mRecyclerView = (WrapMyRecyclerView) this.findViewById(R.id.wrap_recyclerview);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
//加入headerView
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(WC,WC);
ImageView headerView = new ImageView(this);
headerView.setImageResource(R.drawable.timg);
headerView.setLayoutParams(params);
mRecyclerView.addHeaderView(headerView);
//設(shè)置adapter
mMyAdapter = new MyAdapter(this,mList01);
mRecyclerView.setAdapter(mMyAdapter);
//加入footerView
params = new ViewGroup.LayoutParams(WC,WC);
ImageView footerView = new ImageView(this);
footerView.setImageResource(R.drawable.hhfj);
footerView.setLayoutParams(params);
mRecyclerView.addFooterView(footerView);
mMyAdapter.notifyDataSetChanged();
}
public void getData() {
for (int i = 0; i < 3; i++) {
String data ="adapter...." + i;
mList01.add(data);
}
}
}使用直接調(diào)用addHeaderView、addFooterView即可。
除了這種方式來(lái)實(shí)現(xiàn)addHeaderView和addFooterView,另外一種方式就是封裝Adapter來(lái)實(shí)現(xiàn),原理還是保持不變:根據(jù)不同的條目類型來(lái)創(chuàng)建條目和綁定條目的數(shù)據(jù)。
public class MyCircleRecycViewAdapter extends RecyclerView.Adapter {
public List<CircleInfo.CirclePageInfo> infos = null;
private Context mContext;
private ListViewImgLoader mLoader;
private View VIEW_FOOTER;//尾部
private View VIEW_HEADER;//頭部
//Type
private int TYPE_NORMAL = 1000;
private int TYPE_HEADER = 1001;
private int TYPE_FOOTER = 1002;
private int tagType = TYPE_NORMAL;
public MyCircleRecycViewAdapter(Context context,List<CircleInfo.CirclePageInfo> datas) {
this.infos = datas;
this.mContext = context;
mLoader = new ListViewImgLoader();
mLoader.setMemoryCacheSize(1024 * 1024);
mLoader.setVisibleItemCount(12);
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == TYPE_FOOTER) {
tagType = TYPE_FOOTER;
return new MyCircleItemHolder(VIEW_FOOTER);
} else if (viewType == TYPE_HEADER) {
tagType = TYPE_HEADER;
return new MyCircleItemHolder(VIEW_HEADER);
} else {
tagType = TYPE_NORMAL;
View view = LayoutInflater.from(mContext).inflate(R.layout.circle_gridview_items, parent,false);
return new MyCircleItemHolder(view);
}
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (!isHeaderView(position) && !isFooterView(position)) {
if (haveHeaderView()) position--;
MyCircleItemHolder viewHolder = (MyCircleItemHolder)holder;
CircleInfo.CirclePageInfo mInfo = infos.get(position);
setData(viewHolder,mInfo);
}
}
@Override
public int getItemCount() {
int count = (infos == null ? 0 : infos.size());
if (VIEW_FOOTER != null) {
count++;
}
if (VIEW_HEADER != null) {
count++;
}
return count;
}
@Override
public int getItemViewType(int position)
{
if (isHeaderView(position)) {
return TYPE_HEADER;
} else if (isFooterView(position)) {
return TYPE_FOOTER;
} else {
return TYPE_NORMAL;
}
}
public void addHeaderView(View headerView) {
if (haveHeaderView()) {
throw new IllegalStateException("hearview has already exists!");
} else {
//避免出現(xiàn)寬度自適應(yīng)
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(Utils.getRealPixel(30), Utils.getRealPixel(230));
headerView.setLayoutParams(params);
VIEW_HEADER = headerView;
notifyItemInserted(0);
}
}
public void addFooterView(View footerView) {
if (haveFooterView()) {
throw new IllegalStateException("footerView has already exists!");
} else {
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
footerView.setLayoutParams(params);
VIEW_FOOTER = footerView;
// ifGridLayoutManager();
notifyItemInserted(getItemCount() - 1);
}
}
private boolean haveHeaderView() {
return VIEW_HEADER != null;
}
public boolean haveFooterView() {
return VIEW_FOOTER != null;
}
private boolean isHeaderView(int position) {
return haveHeaderView() && position == 0;
}
private boolean isFooterView(int position) {
return haveFooterView() && position == getItemCount() - 1;
}
private void setData(final MyCircleItemHolder viewHolder, final CircleInfo.CirclePageInfo mInfo) {
if(mInfo == null || mInfo == viewHolder.tagInfo)
{
return;
}else{
viewHolder.tagInfo = mInfo;
if(!StrUtils.isEnpty(mInfo.thread_unread)){
if(mInfo.thread_unread.equals("0")){
viewHolder.threaduUnreadTv.setVisibility(View.INVISIBLE);
}else{
viewHolder.threaduUnreadTv.setVisibility(View.VISIBLE);
viewHolder.threaduUnreadTv.setText(mInfo.thread_unread);
}
}else{
viewHolder.threaduUnreadTv.setVisibility(View.INVISIBLE);
}
if (!TextUtils.isEmpty(viewHolder.tagUrl)){
if(mInfo.circle_img_path != null && !(mInfo.circle_img_path.equals(viewHolder.tagUrl))){
setImage(viewHolder.mImageView,mInfo.circle_img_path);
}
}else{
setImage(viewHolder.mImageView,mInfo.circle_img_path);
}
if (!TextUtils.isEmpty(mInfo.circle_img_path)){
viewHolder.tagUrl = mInfo.circle_img_path;
}
if(mInfo.circleName != null){
if(mInfo.circleName.length() > 5){
String s = mInfo.circleName.substring(0,5) + "...";
viewHolder.textView.setText(s);
}else{
viewHolder.textView.setText(mInfo.circleName);
}
}
}
}
private void setImage(final ColorFilterImageView mImageView, final String imgUrl){
mImageView.setBackgroundColor(0xffadadad);
mImageView.setImageBitmap(null);
if(!TextUtils.isEmpty(imgUrl))
{
mLoader.loadImage(mImageView.hashCode(), imgUrl, 300, new DnImg.OnDnImgListener()
{
@Override
public void onProgress(String url, int downloadedSize, int totalSize)
{
// TODO Auto-generated method stub
}
@Override
public void onFinish(String url, String file, Bitmap bmp)
{
if(url.equals(imgUrl))
{
mImageView.setImageBitmap(bmp);
}
}
});
}else{
mImageView.setBackgroundColor(0xffadadad);
mImageView.setImageBitmap(null);
}
}
class MyCircleItemHolder extends RecyclerView.ViewHolder{
private ColorFilterImageView mImageView;
private TextView textView;
private CircleInfo.CirclePageInfo tagInfo;
private String tagUrl;
private TextView threaduUnreadTv;
public MyCircleItemHolder(final View itemView) {
super(itemView);
if(tagType == TYPE_NORMAL){
mImageView = (ColorFilterImageView)itemView.findViewById(R.id.quan_icon);
mImageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
textView = (TextView)itemView.findViewById(R.id.quan_name);
threaduUnreadTv = (TextView)itemView.findViewById(R.id.quan_num);
mImageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mListener != null){
mListener.oncliItem(itemView,tagInfo,threaduUnreadTv);
}
}
});
}
}
}
public OnclickMyCircleItemListener mListener;
public void setOnclickMyCircleItemListener(OnclickMyCircleItemListener l){
this.mListener = l;
}
public interface OnclickMyCircleItemListener{
void oncliItem(View view,CircleInfo.CirclePageInfo info,View threadNumTv);
}
public void pauseLoader(){
if(mLoader != null)
{
mLoader.pause();
}
}
public void resumeLoader(){
if(mLoader != null)
{
mLoader.resume();
}
}
public void closeLoader(){
if(mLoader != null)
{
mLoader.close();
}
}
}總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)各位Android開(kāi)發(fā)者們的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)創(chuàng)新互聯(lián)的支持。
當(dāng)前題目:Android中封裝RecyclerView實(shí)現(xiàn)添加頭部和底部示例代碼
標(biāo)題鏈接:http://chinadenli.net/article20/gegico.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供自適應(yīng)網(wǎng)站、網(wǎng)站策劃、外貿(mào)網(wǎng)站建設(shè)、云服務(wù)器、App開(kāi)發(fā)、網(wǎng)站維護(hù)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)