没有管界面,只做功能的实现记录。几种管理器的效果图
1、RecyclerView的依赖
implementation 'com.android.support:recyclerview-v7:26.1.0'
2、MainActivity
这个MainActivity主要是LinearLayoutManager和GridLayoutManager的用法。
public class MainActivity extends AppCompatActivity {
private List<String> mDatas;
private RecyclerView mRecyclerView;
private HomeAdapter mAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
mRecyclerView = (RecyclerView) findViewById(R.id.id_recyclerview);
mAdapter = new HomeAdapter(this, mDatas);
// 垂直排列的布局管理器
// mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
// 网格布局的布局管理器
mRecyclerView.setLayoutManager(new GridLayoutManager(this, 4));
// mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(4, StaggeredGridLayoutManager.VERTICAL));
mRecyclerView.setAdapter(mAdapter);
// mRecyclerView.addItemDecoration(new GridSpacingItemDecoration(4, 3, true));
// 设置分割线size、颜色等,可单独设置,LinearLayoutManager、GridLayoutManager均可使用。
GridItemDecoration.Builder builder = new GridItemDecoration.Builder(this);
builder.dividerVerSize = 3;
builder.dividerHorSize = 3;// LinearLayoutManager需去掉此设置
builder.color(R.color.colorPrimaryDark);
mRecyclerView.addItemDecoration(new GridItemDecoration(builder));
// 设置item动画
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
initEvent();
}
private void initEvent() {
mAdapter.setOnItemClickLitener(new HomeAdapter.OnItemClickLitener() {
@Override
public void onItemClick(View view, int position) {
Toast.makeText(MainActivity.this, position + " click",
Toast.LENGTH_SHORT).show();
}
@Override
public void onItemLongClick(View view, int position) {
Toast.makeText(MainActivity.this, position + " long click",
Toast.LENGTH_SHORT).show();
}
});
}
protected void initData() {
mDatas = new ArrayList<>();
for (int i = 'A'; i < 'z'; i++) {
mDatas.add("" + (char) i);
}
}
// 以下是点击事件
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.id_action_add:
mAdapter.addData(1);
break;
case R.id.id_action_delete:
mAdapter.removeData(1);
break;
case R.id.id_action_gridview:
mRecyclerView.setLayoutManager(new GridLayoutManager(this, 4));
break;
case R.id.id_action_listview:
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
break;
case R.id.id_action_horizontalGridView:
mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(4,
StaggeredGridLayoutManager.HORIZONTAL));
break;
case R.id.id_action_staggeredgridview:
Intent intent = new Intent(this, StaggeredGridLayoutActivity.class);
startActivity(intent);
break;
}
return true;
}
}
3、MainActivity的对应的Adapter
public class HomeAdapter extends RecyclerView.Adapter<HomeAdapter.MyViewHolder> {
private List<String> mDatas;
private LayoutInflater mInflater;
public HomeAdapter(Context context, List<String> datas) {
mInflater = LayoutInflater.from(context);
mDatas = datas;
}
public interface OnItemClickLitener {
void onItemClick(View view, int position);
void onItemLongClick(View view, int position);
}
private OnItemClickLitener mOnItemClickLitener;
public void setOnItemClickLitener(OnItemClickLitener mOnItemClickLitener) {
this.mOnItemClickLitener = mOnItemClickLitener;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
MyViewHolder holder = new MyViewHolder(mInflater.inflate(
R.layout.item_home, parent, false));
return holder;
}
@Override
public void onBindViewHolder(final MyViewHolder holder, int position) {
holder.tv.setText(mDatas.get(position));
// 如果设置了回调,则设置点击事件
if (mOnItemClickLitener != null) {
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int pos = holder.getLayoutPosition();
mOnItemClickLitener.onItemClick(holder.itemView, pos);
}
});
holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
int pos = holder.getLayoutPosition();
mOnItemClickLitener.onItemLongClick(holder.itemView, pos);
removeData(pos);
return false;
}
});
}
}
@Override
public int getItemCount() {
return mDatas.size();
}
public void addData(int position) {
mDatas.add(position, "Insert One");
notifyItemInserted(position);
}
public void removeData(int position) {
mDatas.remove(position);
notifyItemRemoved(position);
}
class MyViewHolder extends RecyclerView.ViewHolder {
TextView tv;
public MyViewHolder(View view) {
super(view);
tv = view.findViewById(R.id.id_num);
}
}
}
4、StaggeredGridLayout瀑布流的Activity
public class StaggeredGridLayoutActivity extends AppCompatActivity {
private static final String TAG = "StaggeredGridLayoutActi";
private RecyclerView mRecyclerView;
private List<String> mDatas;
private StaggeredHomeAdapter mStaggeredHomeAdapter;
private MyAdapter myAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_staggered_grid_layout);
mRecyclerView = findViewById(R.id.id_recyclerview);
// mStaggeredHomeAdapter = new StaggeredHomeAdapter(this, mDatas);
myAdapter = new MyAdapter(getData());
mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL));
mRecyclerView.setAdapter(myAdapter);
GridItemDecoration.Builder builder = new GridItemDecoration.Builder(this);
builder.dividerVerSize = 3;
builder.dividerHorSize = 3;
builder.color(R.color.colorPrimaryDark);
mRecyclerView.addItemDecoration(new GridItemDecoration(builder));
// 设置item动画
// mRecyclerView.addItemDecoration(new GridSpacingItemDecoration(4, 10, true));
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
mRecyclerView.setHasFixedSize(true);
// initEvent();
}
// 点击事件,与前面的写法一致。
// private void initEvent() {
// mStaggeredHomeAdapter.setOnItemClickLitener(new StaggeredHomeAdapter.OnItemClickLitener() {
// @Override
// public void onItemClick(View view, int position) {
// Toast.makeText(StaggeredGridLayoutActivity.this,
// position + " click", Toast.LENGTH_SHORT).show();
// }
//
// @Override
// public void onItemLongClick(View view, int position) {
// Toast.makeText(StaggeredGridLayoutActivity.this,
// position + " long click", Toast.LENGTH_SHORT).show();
// }
// });
// }
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main_staggered, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.id_action_add:
mStaggeredHomeAdapter.addData(1);
break;
case R.id.id_action_delete:
mStaggeredHomeAdapter.removeData(1);
break;
}
return true;
}
List<Integer> resIds;
private List<Integer> getData() {
resIds = new ArrayList<>();
resIds.add(R.drawable.meizhi005);
resIds.add(R.drawable.meizhi003);
resIds.add(R.drawable.meizhi002);
resIds.add(R.drawable.meizhi008);
resIds.add(R.drawable.meizhi1);
resIds.add(R.drawable.meizhi004);
resIds.add(R.drawable.meizhi005);
resIds.add(R.drawable.meizhi006);
resIds.add(R.drawable.meizhi008);
resIds.add(R.drawable.meizhi006);
resIds.add(R.drawable.meizhi003);
resIds.add(R.drawable.meizhi009);
resIds.add(R.drawable.meizhi010);
resIds.add(R.drawable.meizhi011);
resIds.add(R.drawable.meizhi012);
resIds.add(R.drawable.meizhi013);
resIds.add(R.drawable.meizhi014);
resIds.add(R.drawable.meizhi015);
resIds.add(R.drawable.meizhi016);
resIds.add(R.drawable.meizhi017);
resIds.add(R.drawable.meizhi018);
resIds.add(R.drawable.meizhi019);
resIds.add(R.drawable.meizhi003);
resIds.add(R.drawable.meizhi005);
resIds.add(R.drawable.meizhi020);
return resIds;
}
}
5、StaggeredGridLayoutActivity对应的Adapter
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
private List<Integer> resIds;
public MyAdapter(List<Integer> resIds) {
this.resIds = resIds;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View item = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_photo, parent, false);
return new MyViewHolder(item);
}
@Override
public void onBindViewHolder(final MyViewHolder holder, final int position) {
// 动态设置图片的宽度,不太理想
// ViewGroup.LayoutParams lp = holder.imageView.getLayoutParams();
// lp.width = 100;
// holder.imageView.setLayoutParams(lp);
holder.imageView.setImageResource(resIds.get(position));
}
@Override
public int getItemCount() {
return resIds.size();
}
private OnItemClickListener mOnItemClickListener;
private OnItemLongClickListener mOnItemLongClickListener;
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
mOnItemClickListener = onItemClickListener;
}
public void setOnItemLongClickListener(OnItemLongClickListener onItemLongClickListener) {
mOnItemLongClickListener = onItemLongClickListener;
}
interface OnItemClickListener {
void onClick(RecyclerView.ViewHolder VH, int position);
}
interface OnItemLongClickListener {
void onLongClick(RecyclerView.ViewHolder VH, int position);
}
class MyViewHolder extends RecyclerView.ViewHolder {
// TextView tv;
ImageView imageView;
public MyViewHolder(View itemView) {
super(itemView);
// tv = (TextView) itemView.findViewById(R.id.id_num);
imageView = (ImageView) itemView.findViewById(R.id.iv);
}
}
}
6、RecyclerView设置item之间的间距需要继承RecyclerView.ItemDecoration
public class GridItemDecoration extends RecyclerView.ItemDecoration {
Paint mVerPaint, mHorPaint;
Builder mBuilder;
public GridItemDecoration(Builder builder) {
init(builder);
}
void init(Builder builder) {
this.mBuilder = builder;
mVerPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mVerPaint.setStyle(Paint.Style.FILL);
mVerPaint.setColor(builder.verColor);
mHorPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mHorPaint.setStyle(Paint.Style.FILL);
mHorPaint.setColor(builder.horColor);
}
private void drawHorizontal(Canvas c, RecyclerView parent) {
int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
if (mBuilder.isExistHeadView && i == 0)
continue;
View child = parent.getChildAt(i);
RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
final int left = child.getLeft() - params.leftMargin;
final int right = child.getRight() + params.rightMargin
+ mBuilder.dividerVerSize;
final int top = child.getBottom() + params.bottomMargin;
final int bottom = top + mBuilder.dividerHorSize;
c.drawRect(left, top, right, bottom, mHorPaint);
}
}
private void drawVertical(Canvas c, RecyclerView parent) {
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
if (mBuilder.isExistHeadView && i == 0)
continue;
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
.getLayoutParams();
final int top = child.getTop() - params.topMargin;
final int bottom = child.getBottom() + params.bottomMargin;
final int left = child.getRight() + params.rightMargin;
final int right = left + mBuilder.dividerVerSize;
c.drawRect(left, top, right, bottom, mVerPaint);
}
}
private int getSpanCount(RecyclerView parent) {
// 列数
int spanCount = -1;
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
if (layoutManager instanceof GridLayoutManager) {
spanCount = ((GridLayoutManager) layoutManager).getSpanCount();
} else if (layoutManager instanceof StaggeredGridLayoutManager) {
spanCount = ((StaggeredGridLayoutManager) layoutManager)
.getSpanCount();
}
return spanCount;
}
private boolean isLastRaw(RecyclerView parent, int pos, int spanCount,
int childCount) {
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
if (layoutManager instanceof GridLayoutManager) {
childCount = childCount - childCount % spanCount;
if (pos >= childCount)
return true;
} else if (layoutManager instanceof StaggeredGridLayoutManager) {
int orientation = ((StaggeredGridLayoutManager) layoutManager)
.getOrientation();
// StaggeredGridLayoutManager 且纵向滚动
if (orientation == StaggeredGridLayoutManager.VERTICAL) {
childCount = childCount - childCount % spanCount;
if (pos >= childCount)
return true;
} else
// StaggeredGridLayoutManager 且横向滚动
{
if ((pos + 1) % spanCount == 0) {
return true;
}
}
}
return false;
}
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDraw(c, parent, state);
drawHorizontal(c, parent);
drawVertical(c, parent);
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
int spanCount = getSpanCount(parent);
int childCount = parent.getAdapter().getItemCount();
int itemPosition = ((RecyclerView.LayoutParams) view.getLayoutParams()).getViewLayoutPosition();
if (mBuilder.isExistHeadView)
itemPosition -= 1;
if (itemPosition < 0)
return;
int column = itemPosition % spanCount;
int bottom = 0;
int left = column * mBuilder.dividerVerSize / spanCount;
int right = mBuilder.dividerVerSize - (column + 1) * mBuilder.dividerVerSize / spanCount;
if (!(isLastRaw(parent, itemPosition, spanCount, childCount) && !mBuilder.isShowLastDivider))
bottom = mBuilder.dividerHorSize;
outRect.set(left, 0, right, bottom);
marginOffsets(outRect, spanCount, itemPosition);
}
private void marginOffsets(Rect outRect, int spanCount, int itemPosition) {
if (mBuilder.marginRight == 0 && mBuilder.marginLeft == 0)
return;
int itemShrink = (mBuilder.marginLeft + mBuilder.marginRight) / spanCount;
outRect.left += (mBuilder.marginLeft - (itemPosition % spanCount) * itemShrink);
outRect.right += ((itemPosition % spanCount) + 1) * itemShrink - mBuilder.marginLeft;
}
public static class Builder {
private Context c;
int horColor;
int verColor;
int dividerHorSize;
int dividerVerSize;
int marginLeft, marginRight;
boolean isShowLastDivider = false;
boolean isExistHeadView = false;
public Builder(Context c) {
this.c = c;
}
/**
* 设置divider的颜色
*
* @param color
* @return
*/
public Builder color(@ColorRes int color) {
this.horColor = c.getResources().getColor(color);
this.verColor = c.getResources().getColor(color);
return this;
}
/**
* 单独设置横向divider的颜色
*
* @param horColor
* @return
*/
public Builder horColor(@ColorRes int horColor) {
this.horColor = c.getResources().getColor(horColor);
return this;
}
/**
* 单独设置纵向divider的颜色
*
* @param verColor
* @return
*/
public Builder verColor(@ColorRes int verColor) {
this.verColor = c.getResources().getColor(verColor);
return this;
}
/**
* 设置divider的宽度
*
* @param size
* @return
*/
public Builder size(int size) {
this.dividerHorSize = size;
this.dividerVerSize = size;
return this;
}
/**
* 设置横向divider的宽度
*
* @param horSize
* @return
*/
public Builder horSize(int horSize) {
this.dividerHorSize = horSize;
return this;
}
/**
* 设置纵向divider的宽度
*
* @param verSize
* @return
*/
public Builder verSize(int verSize) {
this.dividerVerSize = verSize;
return this;
}
/**
* 设置剔除HeadView的RecyclerView左右两边的外间距
*
* @param marginLeft
* @param marginRight
* @return
*/
public Builder margin(int marginLeft, int marginRight) {
this.marginLeft = marginLeft;
this.marginRight = marginRight;
return this;
}
/**
* 最后一行divider是否需要显示
*
* @param isShow
* @return
*/
public Builder showLastDivider(boolean isShow) {
this.isShowLastDivider = isShow;
return this;
}
/**
* 是否包含HeadView
*
* @param isExistHead
* @return
*/
public Builder isExistHead(boolean isExistHead) {
this.isExistHeadView = isExistHead;
return this;
}
public GridItemDecoration build() {
return new GridItemDecoration(this);
}
}
}
// 使用方法
// GridItemDecoration.Builder builder = new GridItemDecoration.Builder(this);
// builder.dividerVerSize = 3;
// builder.dividerHorSize = 3;
// builder.color(R.color.colorPrimaryDark);
// mRecyclerView.addItemDecoration(new GridItemDecoration(builder));
对类引用来源表示感谢!
https://blog.csdn.net/Mark__Liu/article/details/72927035
GridSpacingItemDecorationSW这个也是分割线的一种写法。
public class GridSpacingItemDecorationSW extends RecyclerView.ItemDecoration {
private int spanCount;
private int spacing;
private boolean includeEdge;
public GridSpacingItemDecorationSW(int spanCount, int spacing, boolean includeEdge) {
this.spanCount = spanCount;
this.spacing = spacing;
this.includeEdge = includeEdge;
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
int position = parent.getChildAdapterPosition(view); // item position
int column = position % spanCount; // item column
if (includeEdge) {
outRect.left = spacing - column * spacing / spanCount; // spacing - column * ((1f / spanCount) * spacing)
outRect.right = (column + 1) * spacing / spanCount; // (column + 1) * ((1f / spanCount) * spacing)
if (position < spanCount) { // top edge
outRect.top = spacing;
}
outRect.bottom = spacing; // item bottom
} else {
outRect.left = column * spacing / spanCount; // column * ((1f / spanCount) * spacing)
outRect.right = spacing - (column + 1) * spacing / spanCount; // spacing - (column + 1) * ((1f / spanCount) * spacing)
if (position >= spanCount) {
outRect.top = spacing; // item top
}
}
}
}
用法 recyclerView.addItemDecoration(new GridSpacingItemDecorationSW(1, 12, false));
还有一个分割线的类也可以学习一下,简洁一些。
public class GridSpacingItemDecoration extends RecyclerView.ItemDecoration {
private int spanCount;
private int spacing;
private boolean includeEdge;
public GridSpacingItemDecoration(int spanCount, int spacing, boolean includeEdge) {
this.spanCount = spanCount;
this.spacing = spacing;
this.includeEdge = includeEdge;
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
int position = parent.getChildAdapterPosition(view); // item position
int column = position % spanCount; // item column
if (includeEdge) {
outRect.left = spacing - column * spacing / spanCount; // spacing - column * ((1f / spanCount) * spacing)
outRect.right = (column + 1) * spacing / spanCount; // (column + 1) * ((1f / spanCount) * spacing)
if (position < spanCount) { // top edge
outRect.top = spacing;
}
outRect.bottom = spacing; // item bottom
} else {
outRect.left = column * spacing / spanCount; // column * ((1f / spanCount) * spacing)
outRect.right = spacing - (column + 1) * spacing / spanCount; // spacing - (column + 1) * ((1f / spanCount) * spacing)
if (position >= spanCount) {
outRect.top = spacing; // item top
}
}
}
}
7、Activity的布局相同
<?xml version="1.0" encoding="utf-8"?>
<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"
tools:context="com.example.qqq.recyclerviewtest.MainActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/id_recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="#ffff0000"
android:dividerHeight="10dp" />
</RelativeLayout>
&emspLinearLayoutManager和GridLayoutManager用的布局
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#e10219">
<TextView
android:id="@+id/id_num"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_gravity="center"
android:gravity="center"
android:text="1" />
</FrameLayout>
StaggeredGridLayoutManager用的布局,图片的高度不固定,宽度建议设置为定值,由于图片的大小不一致,建议使用android:scaleType="centerCrop"
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/iv"
android:scaleType="centerCrop"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</FrameLayout>