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

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打造完成了,效果如何呢,上图不解释

源代码下载链接

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

时间: 2024-11-08 14:13:30

RecyclerView:打造自己熟悉的完美控件的相关文章

Android 自定义 HorizontalScrollView 打造再多图片(控件)也不怕 OOM 的横向滑动效果

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38140505 自从Gallery被谷歌废弃以后,Google推荐使用ViewPager和HorizontalScrollView来实现Gallery的效果.的确HorizontalScrollView可以实现Gallery的效果,但是HorizontalScrollView存在一个很大的问题,如果你仅是用来展示少量的图片,应该是没问题的,但是如果我希望HorizontalScr

如何打造Android自定义的下拉列表框控件

一.概述 Android中的有个原生的下拉列表控件Spinner,但是这个控件有时候不符合我们自己的要求, 比如有时候我们需要类似windows 或者web网页中常见的那种下拉列表控件,类似下图这样的: 这个时候只有自己动手写一个了.其实实现起来不算很难, 本文实现的方案是采用TextView +ImageView+PopupWindow的组合方案. 先来看看我们的自己写的控件效果图吧:(源码在文章下面最后给出哈!) 二.自定义下拉列表框控件的实现 1. 自定义控件用到的布局文件和资源: 结果框

Android 打造任意层级树形控件 考验你的数据结构和设计

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/40212367,本文出自:[张鸿洋的博客] 1.概述 大家在项目中或多或少的可能会见到,偶尔有的项目需要在APP上显示个树形控件,比如展示一个机构组织,最上面是boss,然后各种部门,各种小boss,最后各种小罗罗:整体是一个树形结构:遇到这样的情况,大家可能回去百度,因为层次多嘛,可能更容易想到ExpandableListView , 因为这玩意层级比Listview多,但是E

Android 打造随意层级树形控件 考验你的数据结构和设计

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/40212367,本文出自:[张鸿洋的博客] 1.概述 大家在项目中或多或少的可能会见到,偶尔有的项目须要在APP上显示个树形控件,比方展示一个机构组织,最上面是boss.然后各种部门.各种小boss,最后各种小罗罗.总体是一个树形结构.遇到这种情况,大家可能回去百度.由于层次多嘛,可能更easy想到ExpandableListView , 由于这玩意层级比Listview多.可是

Android 打造任意层级树形控件 考验你的数据结构和设计

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/40212367,本文出自:[张鸿洋的博客] 1.概述 大家在项目中或多或少的可能会见到,偶尔有的项目需要在APP上显示个树形控件,比如展示一个机构组织,最上面是boss,然后各种部门,各种小boss,最后各种小罗罗:整体是一个树形结构:遇到这样的情况,大家可能回去百度,因为层次多嘛,可能更容易想到ExpandableListView , 因为这玩意层级比Listview多,但是E

全新控件RecyclerView

Android 5.0引入了一个全新的列表控件-RecyclerView,这个控件更为灵活,同时也拥有比ListView和GridView控件较多的优点:例如Item View的创建.View的回收以及重用等机制. RecyclerView控件提供了以下两种方法来进行简化和处理大数量集合: 采用LayoutManager来处理Item的布局 提供Item操作的默认动画,例如在增加或者删除item的时候 可以自定义LayoutManager或者设置添加/删除的动画,整体的RecyclerView结

Android5.0控件-RecyclerView

Android 5.0引入了一个全新的列表控件-RecyclerView,这个控件更为灵活,同时也拥有比ListView和GridView控件较多的优点:例如Item View的创建.View的回收以及重用等机制. RecyclerView控件提供了以下两种方法来进行简化和处理大数量集合: ?l 采用LayoutManager来处理Item的布局 ?l 提供Item操作的默认动画,例如在增加或者删除item的时候 可以自定义LayoutManager或者设置添加/删除的动画,整体的Recycle

自个儿写Android的下拉刷新/上拉加载控件

前段时间自己写了一个能够"通用"的,支持下拉刷新和上拉加载的自定义控件.可能现如今这已经不新鲜了,但有兴趣的朋友还是可以一起来看看的. 与通常的View配合使用(比如ImageView) 与ListView配合使用 与RecyclerView配合使用 与SrcollView配合使用 局部刷新(但想必这种需要实际应该还是不多的-.) 好啦,效果大概就是这样.如果您看后觉得有一点兴趣.那么,以下是相关的信息: GitHub地址: https://github.com/RawnHwang/S

【WPF学习】第二十章 内容控件

原文:[WPF学习]第二十章 内容控件 内容控件(content control)是更特殊的控件类型,它们可包含并显示一块内容.从技术角度看,内容控件时可以包含单个嵌套元素的控件.与布局容器不同的是,内容控件只能包含一个子元素,而布局容器主要愿意可以包含任意多个牵头元素. 正如前面所介绍,所有WPF布局容器都继承自抽象类Panel,该类提供了对包含多个元素的支持.类似地,所有内容控件都继承自抽象类ContentControl.下图显示了ContentControl类的层次结构. 图 Conten