码迷,mamicode.com
首页 > 其他好文 > 详细

RecyclerView:打造自己熟悉的完美控件

时间:2015-07-15 16:58:39      阅读:129      评论:0      收藏:0      [点我收藏+]

标签:android   recyleview   listview   gridview   瀑布流   

      RecyclerView控件问世已经有很长的一段时间了,想必很多人对它的基本用法很熟悉了,再此就不赘述。它可以完美的替代ListView与GridView,纵向横向皆可,瀑布流也能搞定!这么多功能,只要这一个控件就可实现,想想都心动。个人而言,用起来的话还是稍显繁琐一些,所以自己动手打造一个熟悉完美的控件。

1.布局管理器:LayoutManger

  要用RecyclerView显示内容,LayoutManger是必不可少的,里面的方法setLayoutManger就是设置这个玩意的,但是对于可能一个不是很熟悉的控件,往往总会有遗漏的地方。在我们以往的ListView或者是GridView中,都没有设置过这个东西,所以咱就想了,可不可以重新继承RecyclerView自己打造一个类似Listview的控件,可以省去不必要的麻烦呢。

RecyclerView在调用方法setLayoutManger的时候已经获取到自己的实例,即不为null,

所以BaseRecycleView继承RecyclerView的时候在onFinishInflate中设置布局管理器,

这里我抽象出一个方法setFinalLayoutManger,可以根据需求自己定义。

public abstract void setFinalLayoutManger();

<span style="font-size:18px;"><span style="white-space:pre">	</span>@Override
	protected void onFinishInflate() {
		super.onFinishInflate();
		setFinalLayoutManger();
		addItemDecoration(new DividerItemDecoration(getContext()));
	}</span>

2.没有点击和长按事件,自己动手设置呗

(1)定义点击和长按事件接口

<span style="font-size:18px;"><span style="white-space:pre">	</span>//点击事件监听接口
	public interface OnItemClickListener{
		void onItemClick(View itemView,int position);
	}</span>
<span style="font-size:18px;"><span style="white-space:pre"></span><pre name="code" class="java"><span style="white-space:pre">	</span>//长按事件监听接口
	public interface OnLongItemClickListener{
		void onLongItemClick(View itemView,int position);
	}</span>


(2)对外开放设置监听事件的方法,当你在用的时候到底是先设置监听呢还是先设置adpter,不同的人有不同的习惯,所以我在此做了以下处理。

<span style="font-size:18px;"><span style="white-space:pre">	</span>public void setAdapter(Adapter adapter) {
		super.setAdapter(adapter);
		if(adapter instanceof BaseRecyleAdapter){
			BaseRecyleAdapter brAdapter = (BaseRecyleAdapter) adapter;
			if(mListener != null){
				brAdapter.setOnItemClickListener(mListener);
			}
			
			if(mLongListener != null){
				brAdapter.setOnLongItemClickListener(mLongListener);
			}
		}
	}
	
	/**
	 *设置行点击事件 
	 */
	public void setOnItemClickListener(OnItemClickListener listener){
		this.mListener = listener;
		@SuppressWarnings("rawtypes")
		BaseRecyleAdapter adapter = cast();
		adapter.setOnItemClickListener(mListener);
	}
	
	/**
	 *设置行长按事件 
	 */
	public void setOnLongClickListener(OnLongItemClickListener listener){
		this.mLongListener = listener;
		@SuppressWarnings("rawtypes")
		BaseRecyleAdapter adapter = cast();
		adapter.setOnLongItemClickListener(mLongListener);
	}
	
	/**
	 *获取继承自BaseRecyleAdapter的adapter 
	 */
	@SuppressWarnings("rawtypes")
	private BaseRecyleAdapter cast(){
		
		Adapter adapter = getAdapter();
		
		if(adapter != null){
			if(adapter instanceof BaseRecyleAdapter){
				BaseRecyleAdapter brAdapter = (BaseRecyleAdapter) adapter;
				return brAdapter;
			}else{
				throw new ClassCastException("getAdapter() from recyclerView can not cast BaseRecyleAdapter," +
						"so userd adapter should extends BaseRecyleAdapter");
			}
		}
		return null;
	}</span>
在设置adapter的时候,会判断监听事件是否已经设置,如果设置了,就调用BaseRecycleAdapter中的设置监听事件的方法(BaseRecycleAdapter也是重写,后续会列出);在设置监听事件的时候,会判断adapter是否已经设置,如果设置了,就调用BaseRecycleAdapter中的设置监听事件的方法。重复以下,设置的adapter必须继承自BaseRecycleAdapter。

基本的BaseRecycleView已经基本竣工了,接下来就是实现自己需要的FinalRecycleView的重构了

3.打造自己满意的FinalRecycleView(继承自BaseRecycleView)

(1)这个FinalRecycleView是一个多样化的RecycleView,所以用到了自定义属性。在res/values中创建attrs.xml

<span style="font-size:18px;"><span style="font-size:18px;"><?xml version="1.0" encoding="utf-8"?>
<resources>
    
    <declare-styleable name="FinalRecycleViewStyle">
        <attr name="showStyle" format="integer"/> <!-- 显示形式,list or grid -->
        <attr name="spanCount" format="integer"/> <!-- grid列数 -->
    </declare-styleable>
    
    
</resources></span></span>

(2)在res/values中创建integer.xml(用来表示attrs中showStyle的)

<span style="font-size:18px;"><?xml version="1.0" encoding="utf-8"?>
<resources>
    <integer name="LISTVIEW_VERTICAL">1000</integer>
    <integer name="LISTVIEW_HORIZONTAL">1001</integer>
    <integer name="GRIDVIEW_NORMAL">1002</integer>
    <integer name="STAGGERED_HORIZONTAL">1003</integer>
    <integer name="STAGGERED_VERTICAL">1004</integer>
</resources></span>
(3)属性获取,想必会自定义控件的这个都难不倒你们,就不在赘述了。

(4)最关键的方法到了,setFinalLayoutManger,这个就是我们在BaseRecyleView中抽象方法,setlayoutManger就在这里面进行设置了。

<span style="font-size:18px;">        if(showStyle == res.getInteger(R.integer.LISTVIEW_VERTICAL)){
	<span style="white-space:pre">	</span>setLayoutManager(new LinearLayoutManager(mContext));
	}else if(showStyle == res.getInteger(R.integer.LISTVIEW_HORIZONTAL)){
		setLayoutManager(new LinearLayoutManager(mContext, LinearLayoutManager.HORIZONTAL, false));
	}else if(showStyle == res.getInteger(R.integer.GRIDVIEW_NORMAL)){
		setLayoutManager(new GridLayoutManager(mContext, spanCount));
	}else if(showStyle == res.getInteger(R.integer.STAGGERED_HORIZONTAL)){
		setLayoutManager(new StaggeredGridLayoutManager(spanCount, StaggeredGridLayoutManager.HORIZONTAL));
	}else if(showStyle == res.getInteger(R.integer.STAGGERED_VERTICAL)){
		setLayoutManager(new StaggeredGridLayoutManager(spanCount, StaggeredGridLayoutManager.VERTICAL));
	}</span>
根据自己设置的不同showStyle来设置不同的布局管理器,很简单的,不说了好吗?!

4.FinalRecycleView打造完成,接下来就是FinalViewHolder,这个很简单,直接继承RecyclerView.ViewHolder代码如下:

<span style="font-size:18px;">package com.dandy.recycleview;

import android.support.v7.widget.RecyclerView;
import android.util.SparseArray;
import android.view.View;
import android.widget.TextView;

public class FinalViewHolder extends RecyclerView.ViewHolder{

	private View mConvertView;
	private SparseArray<View> mViews;
	
	public FinalViewHolder(View view) {
		super(view);
		this.mConvertView = view;
		this.mViews = new SparseArray<View>();
	}
	
	/**
	 * 通过控件的Id获取对于的控件,如果没有则加入views
	 * @param viewId
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public <T extends View> T getView(int viewId) {
		View view = mViews.get(viewId);
		if (view == null) {
			view = mConvertView.findViewById(viewId);
			mViews.put(viewId, view);
		}
		return (T) view;
	}
	
	/**
	 * 为TextView设置字符串
	 * @param viewId
	 * @param text
	 * @param visible
	 * @return
	 */
	public void setText(int viewId, String text) {
		TextView view = getView(viewId);
		if(view != null && text != null){
			view.setText(text);
		}
	}
	
	public View getContentView(){
		return mConvertView;
	}
	
}
</span>
(5)最后就是我们的BaseRecyleAdapter的打造,重写onCreateViewHolder与onBindViewHolder方法,并且在

onBindViewHolder方法中设置监听事件,这部分比较简单,代码如下:

<span style="font-size:18px;">package com.dandy.recycleview;

import java.util.List;
import com.dandy.recycleview.BaseRecycleView.OnItemClickListener;
import com.dandy.recycleview.BaseRecycleView.OnLongItemClickListener;

import android.content.Context;
import android.support.v7.widget.RecyclerView.Adapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnLongClickListener;
import android.view.ViewGroup;
import android.view.View.OnClickListener;

public abstract class BaseRecyleAdapter <T> extends Adapter<FinalViewHolder>{
	
	public OnItemClickListener mListener;
	public OnLongItemClickListener mLongListener;
	public Context mContext;
	public List<T> mDatas;
	public int itemLayoutId;
	
	public BaseRecyleAdapter(Context context,List<T> datas,int itemLayoutId) {
		this.mContext = context;
		this.mDatas = datas;
		this.itemLayoutId = itemLayoutId;
	}
	
	@Override
	public int getItemCount() {
		if(mDatas != null){
			return mDatas.size();
		}
		return 0;
	}
	
	@Override
	public FinalViewHolder onCreateViewHolder(ViewGroup viewGroup, int position) {
		View view = LayoutInflater.from(mContext).inflate(itemLayoutId,viewGroup,false);
		return new FinalViewHolder(view);
	}
	
	@Override
	public void onBindViewHolder(FinalViewHolder viewHolder, final int position) {
		viewHolder.getContentView().setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				if(mListener != null){
					mListener.onItemClick(v, position);
				}
			}
		});
		
		viewHolder.getContentView().setOnLongClickListener(new OnLongClickListener() {
			
			@Override
			public boolean onLongClick(View v) {
				if(mLongListener != null){
					mLongListener.onLongItemClick(v, position);
					return true;
				}
				return false;
			}
		});
		
		convertBindViewHolder(viewHolder,position);
	}
	
	public abstract void convertBindViewHolder(FinalViewHolder viewHolder, final int position);
	
	public void setOnItemClickListener(OnItemClickListener listener){
		this.mListener = listener;
	}
	
	public void setOnLongItemClickListener(OnLongItemClickListener listener){
		this.mLongListener = listener;
	}
}
</span>
(6)自己满意的RecyleView打造完成了,效果如何呢,上图不解释

技术分享技术分享


源代码下载链接


版权声明:本文为博主原创文章,未经博主允许不得转载。

RecyclerView:打造自己熟悉的完美控件

标签:android   recyleview   listview   gridview   瀑布流   

原文地址:http://blog.csdn.net/tabolt/article/details/46894351

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!