RecyclerVeiw 与ListView区别:
recyclerView 缓存的Holder而不是View, RecyclerView 不管布局、不管动画、不管分隔、 只管view 的复用,并支持多种刷新模式:notifyDataSetChanged(), notifyItemInserted(position), notifyItemRemoved(position)等多种刷新模式,很大程度提高效率。
LayoutManager布局管理器:
LinearLaoutManager:线形
GridLayoutManager:网格
StaggeredManager:错乱样式(瀑布流)
简单使用:
在xmlk 中的布局
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
RecyclerView Adapter
/**
* 说明:基本使用
* 波粒:1050189980 2018/6/20
*/
public class SimpleAdapter extends RecyclerView.Adapter<SimpleAdapter.MyHolder> {
protected List<String> mData;
private Context mContext;
private LayoutInflater mLayoutInflater;
OnItemClick mOnItemClick;
public SimpleAdapter(Context contex, List<String> data) {
mContext = contex;
mData = data;
mLayoutInflater = LayoutInflater.from(mContext);
}
/**
* 添加数据
*/
public void add(int position) {
mData.add(position, "新增");
notifyItemInserted(position);
}
/**
* 删除数据
*/
public void delete(int position) {
mData.remove(position);
notifyItemRemoved(position);
}
/**
* 点击事件
*/
public interface OnItemClick {
void click(View view, int position);
void longClick(View view, int position);
}
/**
* 设置事件
*/
public void setOnItmeClick(OnItemClick onItmeClick) {
mOnItemClick = onItmeClick;
}
/**
* 创建Holder 对象
*/
@Override
public MyHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = mLayoutInflater.inflate(R.layout.itme_simple, parent, false);
return new MyHolder(view);
}
/**
* 绑定Holder 设置数据与事件
*/
@Override
public void onBindViewHolder(final MyHolder holder, final int position) {
holder.textView.setText(mData.get(position));
if (mOnItemClick != null) {
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mOnItemClick.click(holder.itemView, holder.getLayoutPosition());
}
});
holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
mOnItemClick.longClick(holder.itemView, holder.getLayoutPosition());
return false;
}
});
}
}
/**
* item大小
*/
@Override
public int getItemCount() {
return mData.size();
}
public class MyHolder extends RecyclerView.ViewHolder {
TextView textView;
public MyHolder(View itemView) {
super(itemView);
textView = itemView.findViewById(R.id.textView);
}
}
}
在Activity 中使用
/**
* RecyclerView 的简单使用
*/
public class SimpleActivity extends AppCompatActivity {
RecyclerView mRecyclerView;
private List<String> mData;
SimpleAdapter simpleAdapter;
SimpleStaggeredAdapter simpleStaggeredAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_simple);
mRecyclerView = findViewById(R.id.recyclerView);
mData = new ArrayList<>();
//添加数据源
for (int i = 'A'; i <= 'z'; i++) {
mData.add("" + (char) i);
}
simpleStaggeredAdapter = new SimpleStaggeredAdapter(this, mData);
simpleAdapter = new SimpleAdapter(this, mData);
//设置adapter
mRecyclerView.setAdapter(simpleAdapter);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
//设置管理器
mRecyclerView.setLayoutManager(linearLayoutManager);
//设置动画
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
//设置分隔线
DividerItemDecoration decoration1 = new DividerItemDecoration(this, DividerItemDecoration.VERTICAL);
mRecyclerView.addItemDecoration(decoration1);
//设置事件
simpleAdapter.setOnItmeClick(new SimpleAdapter.OnItemClick() {
@Override
public void click(View view, int position) {
Toast.makeText(SimpleActivity.this, "click" + position, Toast.LENGTH_SHORT).show();
}
@Override
public void longClick(View view, int position) {
simpleAdapter.delete(position);
Toast.makeText(SimpleActivity.this, "longClick" + position, Toast.LENGTH_SHORT).show();
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
//导入菜单布局
getMenuInflater().inflate(R.menu.menu_simple, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
//线型
if (item.getItemId() == R.id.listView) {
mRecyclerView.setAdapter(simpleAdapter);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
//网格
} else if (item.getItemId() == R.id.gridView) {
mRecyclerView.setAdapter(simpleAdapter);
mRecyclerView.setLayoutManager(new GridLayoutManager(this, 4));
//瀑布流
} else if (item.getItemId() == R.id.horizontal) {
mRecyclerView.setAdapter(simpleAdapter);
mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(5, StaggeredGridLayoutManager.HORIZONTAL));
//横向滑动
} else if (item.getItemId() == R.id.staggeredView) {
mRecyclerView.setAdapter(simpleStaggeredAdapter);
mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(5, StaggeredGridLayoutManager.VERTICAL));
//添加数据
} else if (item.getItemId() == R.id.add) {
simpleAdapter.add(1);
//减少数据
} else if (item.getItemId() == R.id.delete) {
simpleAdapter.delete(1);
}
return super.onOptionsItemSelected(item);
}
}
效果如下:
组合使用:
(支持下拉刷新与自动加载,支持多布局与多数据源)
通过一个adaper 进行实现,使用者只需传入布局id与数据源即可,使用简单方便,不用重复写adapter.
在xml 在使用
<cashierdesk.xkeshi.com.simple.x_view.recyclerview.XRecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
自定义 Adapter
/**
* 说明:RecyclerView 包裹Adapter
* 杨阳:360621904 2018/5/30
*/
@SuppressWarnings({"unchecked", "unused"})
public abstract class WrapperAdapter extends RecyclerView.Adapter<WrapperViewHolder> {
private IWrapperAdapterListener.OnItemClick mOnItemClick;
private IWrapperAdapterListener.OnItemLongClick mOnItemLongClick;
private Map<ItemType, List> mTypeList;
private LayoutInflater inflater;
private MyListenerImp myListenerImp;
private RecyclerView.ViewHolder holder;
private RecyclerView mRecyclerView;
/**
* item 的UI 存储需要跨列的类型(目前是加载类型)
*/
private List<Integer> mItemTypeData;
@SuppressWarnings("WeakerAccess")
public WrapperAdapter(@NonNull Context context) {
mTypeList = new LinkedHashMap<>();
this.inflater = LayoutInflater.from(context);
myListenerImp = new MyListenerImp();
mItemTypeData = new ArrayList<>();
}
/**
* 添加单布局holder
*
* @param LayoutId 布局Id
* @param data 数据源
*/
public void addHolder(int LayoutId, @NonNull List data) {
mTypeList.put(new ItemType(LayoutId), data);
}
/**
* 添加多布局holder,实体对象必须实现 {@link IWrapperAdapterMoreType}这个接口
*
* @param data 数据源
*/
public void addMoreHolder(@NonNull List<IWrapperAdapterMoreType> data) {
mTypeList.put(new ItemType(IWrapperAdapterMoreType.class.hashCode()), data);
}
public void addFloorLoadingHolder(int layoutId, @NonNull List<IWrapperAdapterFloorType> data,
IWrapperAdapterListener.OnLoadingFloorItemShowCallback onLoadingFloorItemShowCallback) {
mTypeList.put(new ItemTypeTwo(layoutId, onLoadingFloorItemShowCallback), data);
mItemTypeData.add(layoutId);
}
/**
* 设置item 的数据
*
* @param holder item 对应的Holder
* @param object item 对应的数据对象
*/
public abstract void setItemData(WrapperViewHolder holder, Object object);
public void setOnItemClick(IWrapperAdapterListener.OnItemClick onItemLick) {
mOnItemClick = onItemLick;
}
public void setOnItemLongClick(IWrapperAdapterListener.OnItemLongClick onItemLongClick) {
mOnItemLongClick = onItemLongClick;
}
@Override
public WrapperViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new WrapperViewHolder(inflater.inflate(viewType, parent, false), viewType);
}
@Override
public void onBindViewHolder(final WrapperViewHolder holder, final int position) {
setItemData(holder, getValue(position));
Object object = getValue(position);
//把holder,position,data 添加到view tag 中
holder.itemView.setTag(R.id.tag_key_holder, holder);
holder.itemView.setTag(R.id.tag_key_position, holder.getLayoutPosition());
holder.itemView.setTag(R.id.tag_key_data, object);
if (mOnItemClick != null && !(object instanceof IWrapperAdapterFloorType))
holder.itemView.setOnClickListener(myListenerImp);
if (mOnItemLongClick != null)
holder.itemView.setOnLongClickListener(myListenerImp);
if (mOnItemClick != null || mOnItemLongClick != null)
holder.setItemBackground();
//判断是否是加载的itemView
if (object instanceof IWrapperAdapterFloorType) {
ItemTypeTwo typeTwo = (ItemTypeTwo) getKey(position);
assert typeTwo != null;
if (typeTwo.mOnLoadingFloorItemShowCallback != null)
typeTwo.mOnLoadingFloorItemShowCallback.floorItemShowCallback(holder.itemView, holder, holder.getLayoutPosition(), object);
}
}
@Override
public int getItemCount() {
return getSumCount();
}
@Override
public int getItemViewType(int position) {
return getMyItemViewType(position);
}
@Override
public void onViewAttachedToWindow(WrapperViewHolder holder) {
super.onViewAttachedToWindow(holder);
// 处理StaggeredGridLayoutManager,设置充满整行
ViewGroup.LayoutParams layoutParams = holder.itemView.getLayoutParams();
if (null != layoutParams && layoutParams instanceof StaggeredGridLayoutManager.LayoutParams) {
if (mItemTypeData.contains(mRecyclerView.getAdapter().getItemViewType(holder.getLayoutPosition())))
((StaggeredGridLayoutManager.LayoutParams) layoutParams).setFullSpan(true);
}
}
@Override
public void onAttachedToRecyclerView(final RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
mRecyclerView = recyclerView;
// 处理GridLayoutManager,设置充满整行
RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
if (layoutManager instanceof GridLayoutManager) {
final GridLayoutManager gridLayoutManager = (GridLayoutManager) layoutManager;
gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
if (mItemTypeData.contains(mRecyclerView.getAdapter().getItemViewType(position))) {
return gridLayoutManager.getSpanCount();
}
return 1;
}
});
}
}
/**
* 事件回调的处理
*/
class MyListenerImp implements View.OnClickListener, View.OnLongClickListener {
@Override
public void onClick(View view) {
mOnItemClick.click(view, (WrapperViewHolder) view.getTag(R.id.tag_key_holder), (int) view.getTag(R.id.tag_key_position), view.getTag(R.id.tag_key_data));
}
@Override
public boolean onLongClick(View view) {
mOnItemLongClick.longClick(view, (WrapperViewHolder) view.getTag(R.id.tag_key_holder), (int) view.getTag(R.id.tag_key_position), view.getTag(R.id.tag_key_data));
return false;
}
}
/**
* 总条目数
*/
private int getSumCount() {
int sumCount = 0;
for (Map.Entry entry : mTypeList.entrySet()) {
if (entry.getValue() != null)
sumCount += ((List) entry.getValue()).size();
}
return sumCount;
}
/**
* 条目UI 类型
*/
private int getMyItemViewType(int position) {
int count = 0;
for (Map.Entry entry : mTypeList.entrySet()) {
List list = (List) entry.getValue();
//多布局
if (list.get(0) instanceof IWrapperAdapterMoreType && ((count + list.size()) > position)) {
int moreCount = count;
for (int i = 0; i < list.size(); i++) {
if (moreCount == position) {
return ((IWrapperAdapterMoreType) list.get(i)).getItemViewId();
}
moreCount++;
}
}
//统一布局
count += ((List) entry.getValue()).size();
if (count > position) {
return ((ItemType) entry.getKey()).layoutId;
}
}
return -1;
}
private ItemType getKey(int position) {
int sumCount = 0;
for (Map.Entry entry : mTypeList.entrySet()) {
sumCount += ((List) entry.getValue()).size();
if (sumCount > position) {
return (ItemType) entry.getKey();
}
}
return null;
}
/**
* 获取数据对象
*/
private Object getValue(int position) {
int sumCount = 0;
for (Map.Entry entry : mTypeList.entrySet()) {
for (int i = 0; i < ((List) entry.getValue()).size(); i++) {
if (sumCount == position) {
return ((List) entry.getValue()).get(i);
}
sumCount++;
}
}
return null;
}
/**
* 布局的类型
*/
class ItemType {
//布局的id
int layoutId;
ItemType(int layoutId) {
this.layoutId = layoutId;
}
}
class ItemTypeTwo extends ItemType {
IWrapperAdapterListener.OnLoadingFloorItemShowCallback mOnLoadingFloorItemShowCallback;
ItemTypeTwo(int layoutId, IWrapperAdapterListener.OnLoadingFloorItemShowCallback callback) {
super(layoutId);
this.mOnLoadingFloorItemShowCallback = callback;
}
}
}
Activity 中使用
/**
* RecyclerView 组合的封闭使用
*/
public class TestXRecyclerViewActivity2 extends AppCompatActivity {
XRecyclerView mRecyclerView;
private List<String> mData;
private List<String> mData1;
private List<IWrapperAdapterMoreType> mData2;
WrapperAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test_xrecyclerview);
mRecyclerView = findViewById(R.id.recyclerView);
mData = new ArrayList<>();
mData1 = new ArrayList<>();
mData2 = new ArrayList<>();
addData();
adapter = new WrapperAdapter(TestXRecyclerViewActivity2.this) {
@Override
public void setItemData(WrapperViewHolder holder, Object object) {
setHolderData(holder, object);
}
};
//设置数据,与布局id
adapter.addHolder(R.layout.item_more_one, mData);
adapter.addHolder(R.layout.item_more_two, mData);
adapter.addHolder(R.layout.item_more_three, mData);
adapter.addHolder(R.layout.item_more_one, mData1);
adapter.addMoreHolder(mData2);
//设置布局,动画、adapter
// LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
GridLayoutManager linearLayoutManager = new GridLayoutManager(this, 2, StaggeredGridLayoutManager.VERTICAL, false);
// StaggeredGridLayoutManager linearLayoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
mRecyclerView.setLayoutManager(linearLayoutManager);
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
mRecyclerView.setAdapter(adapter);
//添加线
VerticalDividerItemDecoration decoration = new VerticalDividerItemDecoration.Builder(this)
.colorResId(R.color.colorGreen)
.sizeResId(R.dimen.db_size)
.build();
mRecyclerView.addItemDecoration(decoration);
//添加线
HorizontalDividerItemDecoration decorationH = new HorizontalDividerItemDecoration.Builder(this)
.colorResId(R.color.colorGreen)
.sizeResId(R.dimen.db_size)
.showLastDivider()
.build();
mRecyclerView.addItemDecoration(decorationH);
//设置事件与回调
setListener();
}
int count;
/**
* 设置事件与回调
*/
private void setListener() {
/**
* 设置点击事件
*/
adapter.setOnItemClick(new IWrapperAdapterListener.OnItemClick() {
@Override
public void click(View view, WrapperViewHolder holder, int position, Object data) {
if (data instanceof String) {
String str = (String) data;
Toast.makeText(TestXRecyclerViewActivity2.this, "position:" + str + "--" + position, Toast.LENGTH_SHORT).show();
}
if (data instanceof MyWrapperAdapterMoreType) {
MyWrapperAdapterMoreType data1 = (MyWrapperAdapterMoreType) data;
Toast.makeText(TestXRecyclerViewActivity2.this, "position:" + data1.str + "--" + position, Toast.LENGTH_SHORT).show();
}
}
});
/**
* 刷新的回调
*/
mRecyclerView.setRefreshListener(new IXRecyclerViewBiz.RefreshListener() {
@Override
public void onRefreshListener() {
mData.clear();
mData.add("new");
mData2.add(new MyWrapperAdapterMoreType(2, "新22"));
adapter.notifyDataSetChanged();
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
mRecyclerView.stopRefreshing();
count = 0;
// mRecyclerView.finishLoading();
}
}, 1000);
}
});
/**
* 加载更多回调
*/
mRecyclerView.setLoadingListener(new IXRecyclerViewBiz.LoadingListener() {
@Override
public void onLoadingListener() {
Log.e("BBB", "加载的回调");
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
mData2.add(new MyWrapperAdapterMoreType(1, "加载新" + count));
mData2.add(new MyWrapperAdapterMoreType(1, "加载新" + count));
mData2.add(new MyWrapperAdapterMoreType(2, "加载新" + count));
mData2.add(new MyWrapperAdapterMoreType(1, "加载新" + count));
mData2.add(new MyWrapperAdapterMoreType(3, "加载新" + count));
mData2.add(new MyWrapperAdapterMoreType(1, "加载新" + count));
adapter.notifyDataSetChanged();
mRecyclerView.stopRefreshing();
count++;
if (count == 4) {
mRecyclerView.finishLoading();
}
}
}, 1000);
}
});
}
/**
* 设置UI 数据
*/
private void setHolderData(WrapperViewHolder holder, Object object) {
if (object instanceof String && R.layout.item_more_one == holder.getLayoutId()) {
String str = (String) object;
holder.setText(R.id.textView, str);
} else if (object instanceof MyWrapperAdapterMoreType) {
MyWrapperAdapterMoreType data = (MyWrapperAdapterMoreType) object;
if (R.layout.item_more_one == holder.getLayoutId()) {
holder.setText(R.id.textView, data.str + "");
} else if (R.layout.item_more_two == holder.getLayoutId()) {
holder.setText(R.id.textView1, data.str + "");
holder.setText(R.id.textView2, data.str + "");
} else if (R.layout.item_more_three == holder.getLayoutId()) {
holder.setText(R.id.three_1, data.str + "");
holder.setText(R.id.three_2, data.str + "");
holder.setText(R.id.three_3, data.str + "");
}
} else if (object instanceof String && R.layout.item_more_two == holder.getLayoutId()) {
String str = (String) object;
holder.setText(R.id.textView1, str);
holder.setText(R.id.textView2, str);
} else if (object instanceof String && R.layout.item_more_three == holder.getLayoutId()) {
String str = (String) object;
holder.setText(R.id.three_1, str);
holder.setText(R.id.three_2, str);
holder.setText(R.id.three_3, str);
}
}
/**
* 添加数据
*/
private void addData() {
for (int i = 'A'; i <= 'C'; i++) {
mData.add("" + (char) i);
}
mData1.add("1111111");
mData1.add("1111111");
mData1.add("1111111");
mData1.add("1111111");
mData1.add("1111111");
mData2.add(new MyWrapperAdapterMoreType(3, "我是3"));
mData2.add(new MyWrapperAdapterMoreType(2, "我是2"));
mData2.add(new MyWrapperAdapterMoreType(2, "我是2"));
mData2.add(new MyWrapperAdapterMoreType(2, "我是2"));
mData2.add(new MyWrapperAdapterMoreType(2, "我是2"));
mData2.add(new MyWrapperAdapterMoreType(2, "我是2"));
mData2.add(new MyWrapperAdapterMoreType(1, "我是1"));
}
class MyWrapperAdapterMoreType implements IWrapperAdapterMoreType {
int type;
String str;
MyWrapperAdapterMoreType(int type, String str) {
this.type = type;
this.str = str;
}
@Override
public int getItemViewType() {
return type;
}
@Override
public int getItemViewId() {
if (type == 1) {
return R.layout.item_more_one;
} else if (type == 2) {
return R.layout.item_more_two;
} else {
return R.layout.item_more_three;
}
}
}
}
效果展示
源码中有例子请运行查看:
- 有带刷新与加载的自定义RecyclerView
- 有支持DataBinding 适配器
- 有分隔线
源码地址下载