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

来源:互联网 发布:group by mysql 编辑:程序博客网 时间:2024/05/01 21:59

以下是对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 implementsRecyclerView.OnItemTouchListener {private RecyclerView mRecyclerView;private GestureDetectorCompat mGestureDetectorCompat;public OnRecyclerViewItemClickListener(RecyclerView recyclerView) {mRecyclerView = recyclerView;mGestureDetectorCompat = new GestureDetectorCompat(recyclerView.getContext(),new ItemTouchGestureDetectorListener());}@Overridepublic boolean onInterceptTouchEvent(RecyclerView recyclerView,MotionEvent motionEvent) {mGestureDetectorCompat.onTouchEvent(motionEvent);return false;}@Overridepublic void onTouchEvent(RecyclerView recyclerView,MotionEvent motionEvent) {mGestureDetectorCompat.onTouchEvent(motionEvent);}private class ItemTouchGestureDetectorListener extendsGestureDetector.SimpleOnGestureListener {@Overridepublic 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;}@Overridepublic 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" })@Overridepublic 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() {@Overridepublic 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;}@Overridepublic 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;}@Overridepublic int getItemCount() {if (mWrapedAdapter == null) {return getHeadersCount() + getFootersCount();}return getHeadersCount() + mWrapedAdapter.getItemCount() + getFootersCount();}@Overridepublic 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);}@Overridepublic 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);} }}@Overridepublic 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() {@Overridepublic 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);}@Overridepublic int getItemCount() {return mDatas.size();}public void addAll(List<String> datas) {mDatas.addAll(datas);notifyDataSetChanged();}@Overridepublic void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {MyViewHolder myViewHolder  = (MyViewHolder) holder;myViewHolder.tvText.setText(mDatas.get(position));}@Overridepublic 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();@Overrideprotected 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() {@Overridepublic 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);}// 初始化头部和尾部viewView 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() {@Overridepublic void onClick(View v) {Toast.makeText(MainActivity.this, "header" , Toast.LENGTH_SHORT).show();}});mAdapter = new MyAdapter(this, mDatas);// 添加头部和尾部viewmRecyclerView.addHeaderView(header);        mRecyclerView.addFooterView(footer);        mRecyclerView.setAdapter(mAdapter);        // 监听item点击事件mRecyclerView.setOnItemClickListener(new RecyclerViewExt.OnItemClickListener() {@Overridepublic void onItemClick(ViewHolder vh, int position) {Toast.makeText(MainActivity.this, "onItemClick pos: " + position, Toast.LENGTH_SHORT).show();}@Overridepublic void onItemLongClick(ViewHolder vh, int position) {Toast.makeText(MainActivity.this, "onItemLongClick pos: " + position, Toast.LENGTH_SHORT).show();}});// 监听加载更多mRecyclerView.setOnLoadMoreListener(new OnLoadMoreListener() {@Overridepublic void onLoadMore(int begin) {handler.postDelayed(new Runnable() {@Overridepublic 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

1 0
原创粉丝点击