使用RecyclerView实现瀑布流
2016-07-20 本文已影响384人
李俊的博客
实例:使用RecyclerView实现瀑布流
效果
效果图添加依赖
// RecyclerView
compile 'com.android.support:recyclerview-v7:+'
使用RecyclerView
activity_main.xml
<LinearLayout
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:orientation="vertical"
tools:context="jun.mytest.MainActivity">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"/>
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
对RecyclerView进行相关设置
1、LayoutManager:管理RecyclerView的结构
2、Adapter:处理每个Item的显示
3、ItemDecoration:添加每个Item的装饰
4、ItemAnimator:负责添加、移除、重排序时的动画效果
MainActivity.java
public class MainActivity extends AppCompatActivity {
private Toolbar toolbar;
private RecyclerView mRecyclerView;
private List<String> mDatas;
private MyAdapter mAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
// 初始化Toolbar
initToolbar();
// 初始化Data
initData();
// 初始化RecyclerView
initRecyclerView();
}
/**
* 初始化Toolbar
*/
private void initToolbar() {
toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.inflateMenu(R.menu.menu_main);
toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
// 在位置1添加和移除
switch (item.getItemId()) {
case R.id.action_add:
mAdapter.addData(1, "New");
break;
case R.id.action_delete:
mAdapter.removeData(1);
break;
}
return true;
}
});
}
/**
* 初始化RecyclerView
*/
private void initRecyclerView() {
mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
mRecyclerView.setHasFixedSize(true); // 设置固定大小
// 设置为错列网格布局实现瀑布流
mRecyclerView.setLayoutManager(
new StaggeredGridLayoutManager(
4, StaggeredGridLayoutManager.VERTICAL));
// 设置适配器
mAdapter = new MyAdapter(mDatas);
mRecyclerView.setAdapter(mAdapter);
// 添加装饰
mRecyclerView.addItemDecoration(new MyItemDecoration(this));
// 设置为默认动画
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
}
/**
* 初始化Data
*/
private void initData() {
mDatas = new ArrayList<>();
for (int i = 0; i < 100; i++) {
String data = "No. " + i;
mDatas.add(data);
}
}
}
Toast封装类
ToastUtil.java
public class ToastUtil {
private static Toast mToast;
public static void showToast(Context context, String str, int duration) {
if (mToast == null)
mToast = Toast.makeText(context, str, duration);
else
mToast.setText(str);
mToast.show();
}
}
RecyclerView的适配器
RecyclerView的Item布局
item_recycler_view.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#9d55b8">
<TextView
android:id="@+id/tv_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"/>
</FrameLayout>
MyAdapter.java
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
private List<String> mDatas;
private List<Integer> mHeights;
private Context mContext;
public MyAdapter(List<String> mDatas) {
this.mDatas = mDatas;
mHeights = new ArrayList<>();
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
mContext = parent.getContext();
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_recycler_view, parent, false);
return new MyViewHolder(itemView);
}
@Override
public void onBindViewHolder(final MyViewHolder holder, final int position) {
/*int layoutPosition = holder.getLayoutPosition();*/
// 获取数据
String data = mDatas.get(position);
// 将标签的高度设置成随机模拟瀑布流效果
if (mHeights.size() <= position) {
mHeights.add((int) (30 + Math.random() * 200));
}
ViewGroup.LayoutParams layoutParams = holder.mTvLabel.getLayoutParams();
layoutParams.height = mHeights.get(position);
holder.mTvLabel.setLayoutParams(layoutParams);
// 设置标签
holder.mTvLabel.setText(data);
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ToastUtil.showToast(mContext, "Item: " + position, Toast.LENGTH_SHORT);
}
});
}
@Override
public int getItemCount() {
return mDatas.size();
}
// 添加数据
public void addData(int position, String data) {
mDatas.add(position, data);
// 通知已添加
notifyItemInserted(position);
}
// 移除数据
public void removeData(int position) {
mDatas.remove(position);
// 通知已移除
notifyItemRemoved(position);
}
class MyViewHolder extends RecyclerView.ViewHolder {
private TextView mTvLabel; // 标签
public MyViewHolder(View itemView) {
super(itemView);
mTvLabel = (TextView) itemView.findViewById(R.id.tv_label);
}
}
}
RecyclerView的Item装饰
MyItemDecoration.java
public class MyItemDecoration extends RecyclerView.ItemDecoration {
private static final int[] ATTRS = new int[]{android.R.attr.listDivider};
private Drawable mDivider;
public MyItemDecoration(Context context) {
final TypedArray array = context.obtainStyledAttributes(ATTRS);
mDivider = array.getDrawable(0);
array.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) {
final int childCount = parent.getChildCount();
// 在每一个子控件的底部画线
for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
final int left = child.getLeft() + child.getPaddingLeft();
final int right = child.getWidth() + child.getLeft()
- child.getPaddingRight();
final int top = child.getBottom() - mDivider.getIntrinsicHeight()
- child.getPaddingBottom();
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);
}
}
// Item之间的留白
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent
, RecyclerView.State state) {
outRect.set(0, 0, mDivider.getIntrinsicWidth(), mDivider.getIntrinsicHeight());
}
}
Toolbar的Menu
res/menu/menu_main.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/action_add"
android:title="Add"/>
<item
android:id="@+id/action_delete"
android:title="Delete"/>
</menu>