关于瀑布流:
瀑布流,又称瀑布流式布局。是比较流行的一种网站页面布局,视觉表现为参差不齐的多栏布局,随着页面滚动条向下滚动,这种布局还会不断加载数据块并附加至当前尾部。最早采用此布局的网站是Pinterest,逐渐在国内流行开来。国内大多数清新站基本为这类风格
前面已经讲了基础知识,现在来实现一个瀑布流的显示。
基础文章:android—UI—RecyclerViewd的基本使用(1)
参考文章:这里写链接内容
一.包引入
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:24.2.0'
//包引入
compile 'com.android.support:recyclerview-v7:+'
}
二.布局文件
主界面引入RecyclerView:
<?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"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.administrator.newtestpubu.MainActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler"
android:layout_width="match_parent"
android:layout_height="match_parent"></android.support.v7.widget.RecyclerView>
</RelativeLayout>
RecyclerView的item布局文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@color/white">
<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>
这里添加一个ImageView和TextView
适配器类MasonryAdapter:
继承RecyclerView.Adapter<MasonryAdapter.MasonryView>,并重写里面的方法:
private List<Product> products;
public MasonryAdapter(List<Product> list) {
products = list;
}
@Override
public MasonryView onCreateViewHolder(ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.masonry_item, viewGroup, false);
return new MasonryView(view);
}
@Override
public void onBindViewHolder(MasonryView masonryView, int position) {
masonryView.imageView.setImageResource(products.get(position).getImg());
masonryView.textView.setText(products.get(position).getTitle());
}
@Override
public int getItemCount() {
return products.size();
}
public static class MasonryView extends RecyclerView.ViewHolder {
ImageView imageView;
TextView textView;
public MasonryView(View itemView) {
super(itemView);
imageView = (ImageView) itemView.findViewById(R.id.masonry_item_img);
textView = (TextView) itemView.findViewById(R.id.masonry_item_title);
}
}
三个方法:
1. onCreateViewHolder()` 方法用于找到子item的布局文件,并返回视图。
2. onBindViewHolder()用于数据绑定,从列表里面获取数据,注意其中一个参数
MasonryView masonryView是需要自定义的。 继承
RecyclerView.ViewHolder` 用于找到item里面的布局控件。
public static class MasonryView extends RecyclerView.ViewHolder {
ImageView imageView;
TextView textView;
public MasonryView(View itemView) {
super(itemView);
imageView = (ImageView) itemView.findViewById(R.id.masonry_item_img);
textView = (TextView) itemView.findViewById(R.id.masonry_item_title);
}
}
3.getItemCount
返回条目总数。
自定义类Product:
这个不解释,就是一个类,包括了所需的变量。
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;
}
}
使用RecyclerView:
在主Activity里面使用RecyclerView:
1.定义Product List 并做数据初始化,添加数据。
2.找到RecyclerView控件
3.设置LayoutManager,设置布局为 流式布局StaggeredGridLayoutManager
,宽度为2.
4.绑定数据Adaper。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = (RecyclerView) findViewById(R.id.recycler);
//设置layoutManager
recyclerView.setLayoutManager(new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL));
//设置adapter
initData();
Log.d("xxxx", productList.toString());
MasonryAdapter adapter = new MasonryAdapter(productList);
recyclerView.setAdapter(adapter);
}
public void initData() {
productList = new ArrayList<Product>();
productList.add(new Product(R.drawable.ic_1, "美女1"));
productList.add(new Product(R.drawable.ic_2, "美女1"));
productList.add(new Product(R.drawable.ic_3, "美女1"));
productList.add(new Product(R.drawable.ic_1, "美女1"));
productList.add(new Product(R.drawable.ic_2, "美女1"));
productList.add(new Product(R.drawable.ic_3, "美女1"));
}
效果:
效果还不错:
添加分割栏:
大家都知道ItemDecoration
用于给每个item添加间隔的。
写一个SpacesItemDecoration
类继承 RecyclerView.ItemDecoration
public class SpacesItemDecoration extends RecyclerView.ItemDecoration {
private int space;
public SpacesItemDecoration(int space) {
this.space = space;
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
outRect.left = space;
outRect.right = space;
outRect.bottom = space;
if (parent.getChildAdapterPosition(view) == 0) {
outRect.top = space;
}
}
}
间隔默认是透明的
这是原作者写的,继承后只重写了getItemOffsets
一个方法,通过导入space的数值设置边框的大小,并判断是否是顶部的。
Activity引用:
添加在onCreate()里面:
//设置item之间的间隔
SpacesItemDecoration decoration = new SpacesItemDecoration(100);
recyclerView.addItemDecoration(decoration);
为了查看明显,设置的间隔比较大。
是不是图片变小了,是因为间隔的原因。
添加特效边框:
来自鸿洋的博客。
public class DividerGridItemDecoration extends RecyclerView.ItemDecoration {
private static final int[] ATTRS = new int[]{android.R.attr.listDivider};
private Drawable mDivider;
public DividerGridItemDecoration(Context context) {
final TypedArray a = context.obtainStyledAttributes(ATTRS);
mDivider = a.getDrawable(0);
a.recycle();
}
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
//横线有效
drawHorizontal(c, parent);
//竖线无效
drawVertical(c, parent);
}
public void drawHorizontal(Canvas c, RecyclerView parent) {
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.getLeft() - params.leftMargin;
final int right = child.getRight() + params.rightMargin
+ mDivider.getIntrinsicWidth();
final int top = child.getBottom() + params.bottomMargin;
final int bottom = top + mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
public void drawVertical(Canvas c, RecyclerView parent) {
final int childCount = parent.getChildCount();
// 在每一个子控件的右侧画线
for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
int right = child.getRight() - child.getPaddingRight();
int left = right - mDivider.getIntrinsicWidth();
final int top = child.getTop() + child.getPaddingTop();
final int bottom = child.getTop() + child.getHeight() - child.getPaddingBottom();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
// @Override
// public void getItemOffsets(Rect outRect, int itemPosition,
// RecyclerView parent) {
// int spanCount = getSpanCount(parent);
// int childCount = parent.getAdapter().getItemCount();
// if (isLastRaw(parent, itemPosition, spanCount, childCount))// 如果是最后一行,则不需要绘制底部
// {
// outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
// } else if (isLastColum(parent, itemPosition, spanCount, childCount))// 如果是最后一列,则不需要绘制右边
// {
// outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
// } else {
// outRect.set(0, 0, mDivider.getIntrinsicWidth(),
// mDivider.getIntrinsicHeight());
// }
// }
// Item之间的留白
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
outRect.set(0, 0, mDivider.getIntrinsicWidth(), mDivider.getIntrinsicHeight());
}
}
这里使用了系统的styles 所以可以在文件里修改样式。详见基础文章。
这里只显示了底下的边框。左右边框没有画出来。没有解决。
PS 问题解决---->shape布局文件 添加宽度即可
<size android:height="4dp" android:width="3dp"/>
添加删除动画
见基础文章
点击事件和长按事件
见基础文章