關於瀑布流:
瀑布流,又稱瀑布流式佈局。是比較流行的一種網站頁面佈局,視覺表現爲參差不齊的多欄佈局,隨着頁面滾動條向下滾動,這種佈局還會不斷加載數據塊並附加至當前尾部。最早採用此佈局的網站是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"/>
添加刪除動畫
見基礎文章
點擊事件和長按事件
見基礎文章