标签: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打造完成了,效果如何呢,上图不解释
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:android recyleview listview gridview 瀑布流
原文地址:http://blog.csdn.net/tabolt/article/details/46894351