Android之RecyclerView

本讲内容:RecyclerView控件


一、RecyclerView控件概述

该控件用于在有限的窗口中展示大量数据集,例如:ListView、GridView。

1、可以通过布局管理器LayoutManager控制其显示的方式
2、可以通过ItemDecoration控制Item间的间隔
3、可以通过ItemAnimator控制Item增删的动画


示例一:

  

下面是res/layout/activity_main.xml 布局文件:

<RelativeLayout 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.support.v7.widget.RecyclerView
        android:id="@+id/id_recyclerview"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</RelativeLayout>


下面是res/layout/item_textview.xml 布局文件:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:background="#44ff0000"
    android:layout_height="72dp" >

    <TextView
        android:id="@+id/id_item"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center" />

</FrameLayout>


下面是SimpleAdapter.java文件:

public class SimpleAdapter extends RecyclerView.Adapter<MyViewHolder> {

	private LayoutInflater mInflater;
	private Context mContext;
	private List<String> mDatas;

	public SimpleAdapter(Context context, List<String> datas) {
		this.mContext = context;
		this.mDatas = datas;
		mInflater = LayoutInflater.from(context);// 加载布局管理器
	}

	public int getItemCount() {
		return mDatas.size();
	}

	/**
	 * 绑定ViewHolder
	 */
	public void onBindViewHolder(MyViewHolder holder, int position) {
		holder.tv.setText(mDatas.get(position));
	}

	/**
	 * 创建ViewHolder
	 */
	public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
		//将xml布局转换为view对象
		View view = mInflater.inflate(R.layout.item_textview, parent, false);
		MyViewHolder viewHolder = new MyViewHolder(view);
		return viewHolder;
	}

	class MyViewHolder extends ViewHolder {
		TextView tv;

		public MyViewHolder(View view) {
			super(view);
			tv = (TextView) view.findViewById(R.id.id_item);
		}
	}

}


下面是DividerItemDecoration.java文件:(如果要设置分隔线则要用到)

public class DividerItemDecoration extends RecyclerView.ItemDecoration {

	private static final int[] ATTRS = new int[] { android.R.attr.listDivider };

	public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;

	public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;

	private Drawable mDivider;

	private int mOrientation;

	public DividerItemDecoration(Context context, int orientation) {
		final TypedArray a = context.obtainStyledAttributes(ATTRS);
		mDivider = a.getDrawable(0);
		a.recycle();
		setOrientation(orientation);
	}

	public void setOrientation(int orientation) {
		if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) {
			throw new IllegalArgumentException("invalid orientation");
		}
		mOrientation = orientation;
	}

	@Override
	public void onDraw(Canvas c, RecyclerView parent) {
		Log.v("recyclerview - itemdecoration", "onDraw()");
		if (mOrientation == VERTICAL_LIST) {
			drawVertical(c, parent);
		} else {
			drawHorizontal(c, parent);
		}
	}

	public void drawVertical(Canvas c, RecyclerView parent) {
		final int left = parent.getPaddingLeft();
		final int right = parent.getWidth() - parent.getPaddingRight();

		final int childCount = parent.getChildCount();

		for (int i = 0; i < childCount; i++) {
			final View child = parent.getChildAt(i);
			android.support.v7.widget.RecyclerView v = new android.support.v7.widget.RecyclerView(
					parent.getContext());
			final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
					.getLayoutParams();
			final int top = child.getBottom() + params.bottomMargin;
			final int bottom = top + mDivider.getIntrinsicHeight();
			mDivider.setBounds(left, top, right, bottom);
			mDivider.draw(c);
		}
	}

	public void drawHorizontal(Canvas c, RecyclerView parent) {
		final int top = parent.getPaddingTop();
		final int bottom = parent.getHeight() - parent.getPaddingBottom();

		final int childCount = parent.getChildCount();
		for (int i = 0; i < childCount; i++) {
			final View child = parent.getChildAt(i);
			final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
					.getLayoutParams();
			final int left = child.getRight() + params.rightMargin;
			final int right = left + mDivider.getIntrinsicHeight();
			mDivider.setBounds(left, top, right, bottom);
			mDivider.draw(c);
		}
	}

	@Override
	public void getItemOffsets(Rect outRect, int itemPosition,
			RecyclerView parent) {
		if (mOrientation == VERTICAL_LIST) {
			outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
		} else {
			outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
		}
	}
}

下面是MainActivity.java主界面文件:

public class MainActivity extends Activity {

	private RecyclerView mRecyclerView;
	private List<String> mDatas;
	private SimpleAdapter mAdapter;

	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		initViews();
		initDatas();

		mAdapter = new SimpleAdapter(this, mDatas);
		mRecyclerView.setAdapter(mAdapter);

		// 设置RecyclerView的布局管理:1、创建一个线性布局管理器2、设置布局管理器
		LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this,
				LinearLayoutManager.VERTICAL, false);
		mRecyclerView.setLayoutManager(linearLayoutManager);

		// 设置RecyclerView的Item间分隔线
		mRecyclerView.addItemDecoration(new DividerItemDecoration(this,
				DividerItemDecoration.VERTICAL_LIST));
	}

	private void initViews() {
		mRecyclerView = (RecyclerView) findViewById(R.id.id_recyclerview);
	}

	private void initDatas() {
		mDatas = new ArrayList<String>();
		for (int i = 'A'; i <= 'z'; i++) {
			mDatas.add("" + (char) i);
		}
	}
}

该白色分割线是系统默认的,可以在theme.xml中找到该属性的使用情况。那么,使用系统的listDivider有什么好处呢?就是方便我们去随意的改变,该属性我们可以直接声明在:(注意在不同版本values-v11和values-v14也写上

<style name="AppTheme" parent="AppBaseTheme">
        <!-- All customizations that are NOT specific to a particular API-level can go here. -->
    	<item name="android:listDivider">@drawable/divider</item>  
    </style>

下面是res/drawable/divider.xml 自定义分隔线文件:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle" >

    <gradient
        android:centerColor="#ff00ff00"
        android:endColor="#ff0000ff"
        android:startColor="#ffff0000"
        android:type="linear" />

    <size android:height="4dp" />

</shape>


二、LayoutManager

上面实现了类似ListView样子的Demo,通过使用其默认的LinearLayoutManager。

RecyclerView.LayoutManager吧,这是一个抽象类,好在系统提供了3个实现类:

  1. LinearLayoutManager 现行管理器,支持横向、纵向。
  2. GridLayoutManager 网格布局管理器
  3. StaggeredGridLayoutManager 瀑布就式布局管理器

示例二:实现类似GridView


//mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
mRecyclerView.setLayoutManager(new GridLayoutManager(this,4));

下面是res/layout/item_textview.xml 布局文件:(去掉设置分隔线,通过背景色设置分隔线)

<span style="color:#333333;"><?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:background="#44ff0000"
    </span><span style="color:#ff0000;">android:layout_margin="3dp"</span><span style="color:#333333;">
    android:layout_height="72dp" >

    <TextView
        android:id="@+id/id_item"
        android:layout_width="</span><span style="color:#ff0000;">72dp</span><span style="color:#333333;">"
        android:layout_height="match_parent"
        android:gravity="center" />

</FrameLayout></span>

示例三: StaggeredGridLayoutManager 瀑布就式布局管理器

mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(4,StaggeredGridLayoutManager.HORIZONTAL));
第二个参数传一个orientation,如果传入的是StaggeredGridLayoutManager.VERTICAL代表有多少列;那么传入的如果是StaggeredGridLayoutManager.HORIZONTAL就代表有多少行

示例四:


下面是res/layout/activity_main.xml 布局文件:

<RelativeLayout 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.support.v7.widget.RecyclerView
        android:id="@+id/id_recyclerview"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</RelativeLayout>

下面是res/layout/masonry_item.xml 布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_margin="2dp"
    android:background="#ffffff"
    android:orientation="vertical" >

    <ImageView
        android:id="@+id/masonry_item_img"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:adjustViewBounds="true"
        android:scaleType="centerCrop" />

    <TextView
        android:id="@+id/masonry_item_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center" />

</LinearLayout>


为了简单起见,我们假设每个item的数据是一个产品信息

public class Product {
	private int img;
	private String title;

	public Product(int img, String title) {
		this.img = img;
		this.title = title;
	}

	public int getImg() {
		return img;
	}

	public void setImg(int img) {
		this.img = img;
	}

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

}


下面是SimpleAdapter.java文件:

public class SimpleAdapter extends RecyclerView.Adapter<MyViewHolder> {

	private LayoutInflater mInflater;
	private Context mContext;
	private List<Product> mDatas;
	
	public interface OnItemClickListener{
		void onItemClick(View view,int position);
		void onItemLongClick(View view,int position);
	}
	
	/**
	 * 自定义接口点击事件
	 */
	private OnItemClickListener mOnItemClickListener;
	
	public void setOnItemClickListener(OnItemClickListener listener){
		this.mOnItemClickListener=listener;
	}

	public SimpleAdapter(Context context, List<Product> datas) {
		this.mContext = context;
		this.mDatas = datas;
		mInflater = LayoutInflater.from(context);// 加载布局管理器
	}

	public int getItemCount() {
		return mDatas.size();
	}

	/**
	 * 绑定ViewHolder
	 */
	public void onBindViewHolder(final MyViewHolder holder, final int position) {
		holder.mImageView.setImageResource(mDatas.get(position).getImg());
		holder.mTextView.setText(mDatas.get(position).getTitle());
		
		if(mOnItemClickListener!=null){
			holder.mImageView.setOnClickListener(new OnClickListener() {
				
				public void onClick(View v) {
					mOnItemClickListener.onItemClick(holder.mImageView, position);
				}
			});
			
			holder.mImageView.setOnLongClickListener(new OnLongClickListener() {
				
				public boolean onLongClick(View v) {
					mOnItemClickListener.onItemLongClick(holder.mImageView, position);
					return false;
				}
			});
		}
	}

	/**
	 * 创建ViewHolder
	 */
	public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
		//将xml布局转换为view对象
		View view = mInflater.inflate(R.layout.masonry_item, parent, false);
		MyViewHolder viewHolder = new MyViewHolder(view);
		return viewHolder;
	}

	class MyViewHolder extends ViewHolder {
		ImageView mImageView;
		TextView mTextView;

		public MyViewHolder(View view) {
			super(view);
			mImageView=(ImageView) view.findViewById(R.id.masonry_item_img);
			mTextView=(TextView) view.findViewById(R.id.masonry_item_title);
		}
	}

}

下面是MainActivity.java主界面文件:

public class MainActivity extends Activity {

	private RecyclerView mRecyclerView;
	private List<Product> productList;
	private SimpleAdapter mAdapter;

	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		mRecyclerView = (RecyclerView) findViewById(R.id.id_recyclerview);
		mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(2,
				StaggeredGridLayoutManager.VERTICAL));
		initDatas();
		mAdapter = new SimpleAdapter(this, productList);
		mRecyclerView.setAdapter(mAdapter);
		
		mAdapter.setOnItemClickListener(new OnItemClickListener() {
			
			public void onItemLongClick(View view, int position) {
				Toast.makeText(MainActivity.this, "long click:"+position, Toast.LENGTH_LONG).show();
			}
			
			public void onItemClick(View view, int position) {
				Toast.makeText(MainActivity.this, "click:"+position, Toast.LENGTH_LONG).show();
			}
		});
	}

	private void initDatas() {
		productList = new ArrayList<Product>();
		Product p1 = new Product(R.drawable.p1, "我是照片1");
		productList.add(p1);
		Product p2 = new Product(R.drawable.p2, "我是照片2");
		productList.add(p2);
		Product p3 = new Product(R.drawable.p3, "我是照片3");
		productList.add(p3);
		Product p4 = new Product(R.drawable.p4, "我是照片4");
		productList.add(p4);
		Product p5 = new Product(R.drawable.p5, "我是照片5");
		productList.add(p5);
		Product p6 = new Product(R.drawable.p6, "我是照片6");
		productList.add(p6);
		Product p7 = new Product(R.drawable.p2, "我是照片7");
		productList.add(p7);
		Product p8 = new Product(R.drawable.p1, "我是照片8");
		productList.add(p8);
		Product p9 = new Product(R.drawable.p4, "我是照片9");
		productList.add(p9);
		Product p10 = new Product(R.drawable.p6, "我是照片10");
		productList.add(p10);
		Product p11 = new Product(R.drawable.p3, "我是照片11");
		productList.add(p11);
	}
}


参考文章http://blog.csdn.net/lmj623565791/article/details/45059587


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值