可以添加头部和尾部View并且支持setOnItemClickListener和滑到底部自动加载更多的RecyclerView

以下是对RecyclerView的功能扩展,使其具备通ListView一样的功能,能添加头部和尾部View并且支持setOnItemClickListener和滑到底部自动加载更多的RecyclerView


效果图如下:


代码如下

/**
 * 支持添加头部View 、尾部View 、
 * 设置item单击和长按事件和上拉加载
 * 更多的RecyclerView
 *
 */
public class RecyclerViewExt extends RecyclerView {
	
	private Adapter<ViewHolder> mAdapter;
	private List<View> mHeaderViews;
	private List<View> mFooterViews;
	
	private boolean isLoadingMore = false;

	public RecyclerViewExt(Context context) {
		super(context);
		init();
	}

	public RecyclerViewExt(Context context, @Nullable AttributeSet attrs) {
		super(context, attrs);
		init();
	}

	public RecyclerViewExt(Context context, @Nullable AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		init();
	}
	
	private void init() {
		mHeaderViews = new ArrayList<View>();
		mFooterViews = new ArrayList<View>();
		registerOnScrollListener();
	}
	
	/** for OnItemClickListener start */
	private OnItemClickListener mItemClickListener;
	
	public OnItemClickListener getOnItemClickListener() {
		return mItemClickListener;
	}

	public void setOnItemClickListener(OnItemClickListener itemClickListener) {
		mItemClickListener = itemClickListener;
		removeOnItemTouchListener(mOnRecyclerViewItemClickListener);
		addOnItemTouchListener(mOnRecyclerViewItemClickListener);
	}

	public interface OnItemClickListener {
		
		public void onItemClick(RecyclerView.ViewHolder vh, int position);

		public void onItemLongClick(RecyclerView.ViewHolder vh, int position);
	}

	private OnRecyclerViewItemClickListener mOnRecyclerViewItemClickListener = new OnRecyclerViewItemClickListener(this);
	private class OnRecyclerViewItemClickListener implements
			RecyclerView.OnItemTouchListener {

		private RecyclerView mRecyclerView;
		private GestureDetectorCompat mGestureDetectorCompat;

		public OnRecyclerViewItemClickListener(RecyclerView recyclerView) {
			mRecyclerView = recyclerView;
			mGestureDetectorCompat = new GestureDetectorCompat(
					recyclerView.getContext(),
					new ItemTouchGestureDetectorListener());
		}

		@Override
		public boolean onInterceptTouchEvent(RecyclerView recyclerView,
				MotionEvent motionEvent) {
			mGestureDetectorCompat.onTouchEvent(motionEvent);
			return false;
		}

		@Override
		public void onTouchEvent(RecyclerView recyclerView,
				MotionEvent motionEvent) {
			mGestureDetectorCompat.onTouchEvent(motionEvent);
		}

		private class ItemTouchGestureDetectorListener extends
				GestureDetector.SimpleOnGestureListener {

			@Override
			public boolean onSingleTapUp(MotionEvent e) {
				if (mItemClickListener == null) {
					return false;
				}
				View clickedChild = mRecyclerView.findChildViewUnder(e.getX(), e.getY());
				if (clickedChild != null) {
					RecyclerView.ViewHolder vh = mRecyclerView.getChildViewHolder(clickedChild);
					if (vh != null) {
						if (vh.getItemViewType() != RecyclerViewAdapterWrapper.VIEW_TYPE_HEADER
								&& vh.getItemViewType() != RecyclerViewAdapterWrapper.VIEW_TYPE_FOOTER) {
							if (hasHeader()) {
								mItemClickListener.onItemClick(vh, vh.getAdapterPosition() - getHeadersCount());
							} else {
								mItemClickListener.onItemClick(vh, vh.getAdapterPosition());
							}
							return true;
						}
					}
				}
				return false;
			}

			@Override
			public void onLongPress(MotionEvent e) {
				if (mItemClickListener == null) {
					return;
				}
				View clickedChild = mRecyclerView.findChildViewUnder(e.getX(), e.getY());
				if (clickedChild != null) {
					RecyclerView.ViewHolder vh = mRecyclerView .getChildViewHolder(clickedChild);
					if (vh != null) {
						if (vh.getItemViewType() != RecyclerViewAdapterWrapper.VIEW_TYPE_HEADER
								&& vh.getItemViewType() != RecyclerViewAdapterWrapper.VIEW_TYPE_FOOTER) {
							if (hasHeader()) {
								mItemClickListener.onItemLongClick(vh, vh.getAdapterPosition() - getHeadersCount());
							} else {
								mItemClickListener.onItemLongClick(vh, vh.getAdapterPosition());
							}
							
						}
					}
				}
			}
		}

	}
	
	/** for OnItemClickListener end */
	
	/** for header view and footer view start */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	@Override
	public void setAdapter(Adapter adapter) {
		if (mHeaderViews.isEmpty() && mFooterViews.isEmpty()) {
			super.setAdapter(adapter);
		} else {
			adapter = new RecyclerViewAdapterWrapper(mHeaderViews, mFooterViews, adapter);
			super.setAdapter(adapter);
		}
		mAdapter = adapter;
	}
	
	/** 
	 *  
	 * */
	public void addHeaderView(View headerView) {
		mHeaderViews.clear();
		ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
				ViewGroup.LayoutParams.WRAP_CONTENT) ;
		headerView.setLayoutParams(params);
		mHeaderViews.add(headerView);
		if (mAdapter != null) {
			if (!(mAdapter instanceof RecyclerViewAdapterWrapper)) {
				mAdapter =  new RecyclerViewAdapterWrapper(mHeaderViews, mFooterViews, mAdapter);
			}
		} 
	}
	
	public void addFooterView(View footetView) {
		mFooterViews.clear();
		ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
				ViewGroup.LayoutParams.WRAP_CONTENT) ;
		footetView.setLayoutParams(params);
		mFooterViews.add(footetView);
		if (mAdapter != null) {
			if (!(mAdapter instanceof RecyclerViewAdapterWrapper)) {
				mAdapter =  new RecyclerViewAdapterWrapper(mHeaderViews, mFooterViews, mAdapter);
			}
		}
	}
	
	public static class RecyclerViewAdapterWrapper extends Adapter<ViewHolder> {

		private static final ArrayList<View> EMPTY_INFO_VIEW_LIST = new ArrayList<View>();
		
		private static final int VIEW_TYPE_HEADER = RecyclerView.INVALID_TYPE;
		private static final int VIEW_TYPE_FOOTER = VIEW_TYPE_HEADER - 1;

		private Adapter<ViewHolder> mWrapedAdapter;
		private List<View> mHeaderViews;
		private List<View> mFooterViews;

		public RecyclerViewAdapterWrapper(List<View> headerViews,
				List<View> footerViews, Adapter<ViewHolder> adapter) {
			mWrapedAdapter = adapter;
			if (headerViews == null) {
				mHeaderViews = EMPTY_INFO_VIEW_LIST;
			} else {
				mHeaderViews = headerViews;
			}
			
			if (footerViews == null) {
				mFooterViews = EMPTY_INFO_VIEW_LIST;
			} else {
				mFooterViews = footerViews;
			}
			
			mWrapedAdapter.registerAdapterDataObserver(new AdapterDataObserver() {
				@Override
				public void onChanged() {
					super.onChanged();
					RecyclerViewAdapterWrapper.this.notifyDataSetChanged();
				}
			});
			
		}
		
		public int getHeadersCount() {
			return mHeaderViews.size();
		}
		
		public int getFootersCount() {
			return mFooterViews.size();
		}
		
		public Adapter<ViewHolder> getWrapedAdapter() {
			return mWrapedAdapter;
		}

		@Override
		public int getItemViewType(int position) {
			
			int headersCount = getHeadersCount();
			
			if (position < headersCount) {
				return VIEW_TYPE_HEADER;
			}
			
			int adjPosition = position - headersCount;
			int adapterCount = 0;
			if (mWrapedAdapter != null) {
				adapterCount = mWrapedAdapter.getItemCount();
				if (adjPosition < adapterCount) {
					return mWrapedAdapter.getItemViewType(adjPosition);
				}
			}
			return VIEW_TYPE_FOOTER;
		}

		@Override
		public int getItemCount() {
			if (mWrapedAdapter == null) {
				return getHeadersCount() + getFootersCount();
			}
			return getHeadersCount() + mWrapedAdapter.getItemCount() + getFootersCount();
		}
		
		@Override
		public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
			if (viewType == VIEW_TYPE_HEADER) {
				return new HeaderOrFooterViewHolder(mHeaderViews.get(0));
			} else if (viewType == VIEW_TYPE_FOOTER) {
				return new HeaderOrFooterViewHolder(mFooterViews.get(0));
			}
			return mWrapedAdapter.onCreateViewHolder(parent, viewType);
		}

		@Override
		public void onBindViewHolder(ViewHolder viewHolder, int position) {
			int headersCount = getHeadersCount();
			/** header */
			if (position < headersCount) {
				return;
			}
			int adjPosition = position - headersCount;
			int adapterCount = 0;
			if (mWrapedAdapter != null) {
				adapterCount = mWrapedAdapter.getItemCount();
				if (adjPosition < adapterCount) {
					mWrapedAdapter.onBindViewHolder(viewHolder, adjPosition);
				} 
			}

		}
		
		@Override
		public long getItemId(int position) {
		    int headersCount = getHeadersCount();
		    if (mWrapedAdapter != null && position >= headersCount) {
		        int adjPosition = position - headersCount;
		        int adapterCount = mWrapedAdapter.getItemCount();
		        if (adjPosition < adapterCount) {
		            return mWrapedAdapter.getItemId(adjPosition);
		        }
		    }
		    return -1;
		}
		
		/** header or footer view holder */
		public static class HeaderOrFooterViewHolder extends RecyclerView.ViewHolder {

			public HeaderOrFooterViewHolder(View itemView) {
				super(itemView);
			}
		}
	}
	
	public boolean hasHeader() {
		return !mHeaderViews.isEmpty();
	}
	
	public boolean hasFooter() {
		return ! mFooterViews.isEmpty();
	}
	
	public int getHeadersCount() {
		return mHeaderViews.size();
	}
	
	public int getFootersCount() {
		return mFooterViews.size();
	}
	
	public int getAdapterItemCount() {
		if (mAdapter == null) {
			return 0;
		}
		return mAdapter.getItemCount();
	}
	
	public Adapter<ViewHolder> getWrapedAdapter() {
		if (mAdapter == null) {
			return null;
		}
		if (!(mAdapter instanceof RecyclerViewAdapterWrapper)) {
			return mAdapter;
		}
		RecyclerViewAdapterWrapper adapter = (RecyclerViewAdapterWrapper) mAdapter;
		return adapter.getWrapedAdapter();
	}
	
	public int getWrapedAdapterItemCount() {
		return getWrapedAdapter().getItemCount();
	}
	
	public void registerAdapterDataObserver(AdapterDataObserver observer) {
        if (mAdapter != null) {
            mAdapter.registerAdapterDataObserver(observer);
        }
    }

    public void unregisterAdapterDataObserver(AdapterDataObserver observer) {
        if (mAdapter != null) {
            mAdapter.unregisterAdapterDataObserver(observer);
        }
    }
	
	/** for header view and footer view end */
	
    
    /** for OnLoadMoreListener start */
	public interface OnLoadMoreListener {
		public void onLoadMore(int begin);
	}
	
	private OnLoadMoreListener mOnMoreListener;
	
	public OnLoadMoreListener getOnMoreListener() {
		return mOnMoreListener;
	}

	public void setOnLoadMoreListener(OnLoadMoreListener onMoreListener) {
		mOnMoreListener = onMoreListener;
	}

	private void registerOnScrollListener() {
		addOnScrollListener(new OnScrollListener() {
			@Override
			public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
				super.onScrolled(recyclerView, dx, dy);
				if (mOnMoreListener != null && !isLoadingMore && dy > 0) {
					int lastVisiblePosition = getLastVisiblePosition();
					if (lastVisiblePosition == (hasHeader() ? getWrapedAdapterItemCount()
							: getWrapedAdapterItemCount() - 1)) {
						isLoadingMore = true;
						mOnMoreListener.onLoadMore(getWrapedAdapterItemCount() - 1);
					}
				}
			}
			
		});
		
	}
	
	private int getLastVisiblePosition() {
        int position;
        if (getLayoutManager() instanceof LinearLayoutManager) {
            position = ((LinearLayoutManager) getLayoutManager()).findLastVisibleItemPosition();
        } else if (getLayoutManager() instanceof GridLayoutManager) {
            position = ((GridLayoutManager) getLayoutManager()).findLastVisibleItemPosition();
        } else if (getLayoutManager() instanceof StaggeredGridLayoutManager) {
            StaggeredGridLayoutManager layoutManager = (StaggeredGridLayoutManager) getLayoutManager();
            int[] lastPositions = layoutManager.findLastVisibleItemPositions(new int[layoutManager.getSpanCount()]);
            position = getMaxPosition(lastPositions);
        } else {
            position = getLayoutManager().getItemCount() - 1;
        }
        return position;
    }
	
	private int getMaxPosition(int[] positions) {
        int size = positions.length;
        int maxPosition = Integer.MIN_VALUE;
        for (int i = 0; i < size; i++) {
            maxPosition = Math.max(maxPosition, positions[i]);
        }
        return maxPosition;
    }

	public boolean isLoadingMore() {
		return isLoadingMore;
	}

	public void setLoadingMore(boolean isLoadingMore) {
		this.isLoadingMore = isLoadingMore;
	}
	
	/** for OnLoadMoreListener end */

}

使用方法:

Adapter:

public class MyAdapter extends Adapter<RecyclerView.ViewHolder> {
	private List<String> mDatas;
	private LayoutInflater mInflater;

	public MyAdapter(Context context, List<String> datas) {
		mDatas = new ArrayList<String>(datas);
		mInflater = LayoutInflater.from(context);
	}

	@Override
	public int getItemCount() {
		return mDatas.size();
	}
	
	public void addAll(List<String> datas) {
		mDatas.addAll(datas);
		notifyDataSetChanged();
	}


	@Override
	public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
		MyViewHolder myViewHolder  = (MyViewHolder) holder;
		myViewHolder.tvText.setText(mDatas.get(position));
	}

	@Override
	public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
		ViewHolder holder = null;
		View itemView = mInflater.inflate(R.layout.item_data, parent, false);
		holder = new MyViewHolder(itemView);
		return holder;
	}
	
	 class MyViewHolder extends RecyclerView.ViewHolder {
		TextView tvText;
		public MyViewHolder(View arg0) {
			super(arg0);
			tvText = (TextView) arg0.findViewById(R.id.tv_text);
		}
		
	}

}

MainActivity:

public class MainActivity extends Activity {
	
	private RecyclerViewExt mRecyclerView;
	private ArrayList<String> mDatas = new ArrayList<String>();
	private MyAdapter mAdapter;
	
	private Handler handler = new Handler();

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		mRecyclerView = (RecyclerViewExt) findViewById(R.id.rv);
		
		// 设置网格布局管理器
		final GridLayoutManager layoutManager = new GridLayoutManager(this, 2, GridLayoutManager.VERTICAL, false);
		layoutManager.setSpanSizeLookup(new SpanSizeLookup() {
			
			@Override
			public int getSpanSize(int position) {
				if (mRecyclerView.hasHeader()
						|| mRecyclerView.hasFooter()) {
					if (position == 0 ||
							 position == mRecyclerView.getAdapterItemCount() -1) {
						return 2;
					}
				}
				return 1;
			}
		});
		
		// 设置线性布局管理器
//		final LinearLayoutManager layoutManager = new LinearLayoutManager(this, GridLayoutManager.VERTICAL, false);
		mRecyclerView.setLayoutManager(layoutManager);
		
		
		// 初始化数据
		for (int i = 0; i < 16; i++) {
			mDatas.add("data item " + i);
		}
		
		// 初始化头部和尾部view
		View header = LayoutInflater.from(this).inflate(R.layout.header, new LinearLayout(this));
		View footer = LayoutInflater.from(this).inflate(R.layout.footer, new LinearLayout(this));
		
		// 为头部添加点击事件
		header.setClickable(true);
		header.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				Toast.makeText(MainActivity.this, "header" , Toast.LENGTH_SHORT).show();
				
			}
		});
		mAdapter = new MyAdapter(this, mDatas);
		
		// 添加头部和尾部view
		mRecyclerView.addHeaderView(header);
        mRecyclerView.addFooterView(footer);
        mRecyclerView.setAdapter(mAdapter);
		
		
        // 监听item点击事件
		mRecyclerView.setOnItemClickListener(new RecyclerViewExt.OnItemClickListener() {
			
			@Override
			public void onItemClick(ViewHolder vh, int position) {
				Toast.makeText(MainActivity.this, "onItemClick pos: " + position, Toast.LENGTH_SHORT).show();
			}
			
			@Override
			public void onItemLongClick(ViewHolder vh, int position) {
				Toast.makeText(MainActivity.this, "onItemLongClick pos: " + position, Toast.LENGTH_SHORT).show();
			}
		});
	
		// 监听加载更多
		mRecyclerView.setOnLoadMoreListener(new OnLoadMoreListener() {
			
			@Override
			public void onLoadMore(int begin) {
				handler.postDelayed(new Runnable() {
					
					@Override
					public void run() {
						List<String> datas = new ArrayList<String>();
						for (int i = 0; i < 8; i++) {
							datas.add("More Data_" + i);
						}
						mAdapter.addAll(datas);
						// 重置加载状态
						mRecyclerView.setLoadingMore(false);

					}
				}, 500);
			}
		});

	}

}


源码下载:http://download.csdn.net/detail/han_han_1/9565069

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值