RecyclerView 使用全体验
来源:互联网 发布:json和javascript 编辑:程序博客网 时间:2024/05/17 09:11
RecyclerView是谷歌support-V7包下新增的控件,用来替代ListView的使用,在RecyclerView标准化了ViewHolder类似于ListView中convertView用来做视图缓存
体验流程:
- 设置布局管理器(layoutManager)以控制Item的布局方式 <垂直水平ListView,垂直水平GridView,瀑布流>
- 设置Item的间隔样式
- 设置Item删除和添加的动画
- 实现Item的点击和长按事件
app/build.gradle
implementation 'com.android.support:appcompat-v7:25.3.1'implementation 'com.android.support:recyclerview-v7:25.3.1'
package com.example.testnewas.activity;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.support.v7.widget.DefaultItemAnimator;import android.support.v7.widget.GridLayoutManager;import android.support.v7.widget.LinearLayoutManager;import android.support.v7.widget.RecyclerView;import android.support.v7.widget.StaggeredGridLayoutManager;import android.view.View;import android.widget.TextView;import android.widget.Toast;import com.example.testnewas.R;import com.example.testnewas.adapters.Radapter;import com.example.testnewas.views.DividerGridItemDecoration;import com.example.testnewas.views.MyDividerItemDecoration;import java.util.ArrayList;public class RActivity extends AppCompatActivity implements View.OnClickListener{ private RecyclerView recyclerView; private Radapter adapter; private RecyclerView.LayoutManager layoutManager; private TextView addItem; private TextView deleteItem; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_r); initConfig(); initView(); } private void initView() { recyclerView = (RecyclerView) findViewById(R.id.my_recycle_view); recyclerView.setAdapter(adapter); //设置布局管理器以控制Item的布局方式,横向、竖向以及瀑布流方式。 recyclerView.setLayoutManager(layoutManager); //间隔线样式// recyclerView.addItemDecoration(new MyDividerItemDecoration(this, MyDividerItemDecoration.VERTICAL_LIST)); recyclerView.addItemDecoration(new DividerGridItemDecoration(this)); //默认的Item删除和添加的动画 recyclerView.setItemAnimator(new DefaultItemAnimator()); addItem = (TextView) findViewById(R.id.add_item); deleteItem = (TextView) findViewById(R.id.delete_item); addItem.setOnClickListener(this); deleteItem.setOnClickListener(this); } private void initConfig() { adapter = new Radapter(initData()); //Item点击事件 adapter.setOnItemClickListener(new Radapter.OnItemClickListener() { @Override public void onClick(int position) { Toast.makeText(RActivity.this, "click " + position + " item", Toast.LENGTH_SHORT).show(); } @Override public void onLongClick(int position) { Toast.makeText(RActivity.this, "long click " + position + " item", Toast.LENGTH_SHORT).show();
//长按删除当前item
adapter.deleteItem(position); } }); //垂直水平线性列表ListView// layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false); //垂直滚动GridView(每行4)// layoutManager = new GridLayoutManager(this, 4); //水平滚动GridView(每列4)// layoutManager = new StaggeredGridLayoutManager(4, StaggeredGridLayoutManager.HORIZONTAL); //瀑布流 layoutManager = new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL); } //模拟数据 private ArrayList<String> initData() { ArrayList<String> data = new ArrayList<>(); String str = "item-"; for (int i = 0; i< 30; i++) { data.add(str + i); } return data; } @Override public void onClick(View view) { switch (view.getId()) { case R.id.add_item: adapter.addItem(1); break; case R.id.delete_item: adapter.deleteItem(1); break; } }}
activity_recyclerview.xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.example.testnewas.activity.RActivity"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:id="@+id/add_item" android:layout_width="match_parent" android:layout_height="50dp" android:gravity="center" android:background="#fff000" android:text="添加item"/> <TextView android:id="@+id/delete_item" android:layout_width="match_parent" android:layout_height="50dp" android:gravity="center" android:background="#cccccc" android:text="删除item"/> </LinearLayout> <android.support.v7.widget.RecyclerView android:id="@+id/my_recycle_view" android:layout_width="match_parent" android:layout_height="match_parent" android:scrollbars="vertical"> </android.support.v7.widget.RecyclerView></LinearLayout>
RecyclerViewAdapter.java
package com.example.testnewas.adapters;import android.support.v7.widget.RecyclerView;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.TextView;import com.example.testnewas.R;import java.util.ArrayList;import java.util.List;/** * Created by ylh on 2017/11/7 0007. */public class Radapter extends RecyclerView.Adapter<Radapter.ViewHodler> { private ArrayList<String> mData; private OnItemClickListener onItemClickListener; private ArrayList<Integer> heights; /** * 设置回调监听 * @param onItemClickListener */ public void setOnItemClickListener(OnItemClickListener onItemClickListener) { this.onItemClickListener = onItemClickListener; } public Radapter(ArrayList<String> mData) { this.mData = mData; getRandomHeight(this.mData); } public void updateData(ArrayList<String> mData) { this.mData = mData; notifyDataSetChanged(); } @Override public ViewHodler onCreateViewHolder(ViewGroup parent, int viewType) { //实例化展示的view View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_rv_item, parent, false); //实例化viewhodler ViewHodler viewHodler = new ViewHodler(view); return viewHodler; } @Override public void onBindViewHolder(ViewHodler holder, final int position) { /** *瀑布流实现 */ // 得到item的LayoutParams布局参数 ViewGroup.LayoutParams params= holder.itemView.getLayoutParams(); //把随机的高度赋予item布局 params.height = heights.get(position); // 把params设置给item布局 holder.itemView.setLayoutParams(params); //绑定数据 holder.mTv.setText(mData.get(position)); if (onItemClickListener != null) { holder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { onItemClickListener.onClick(position); } }); holder.itemView.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View view) { onItemClickListener.onLongClick(position); //表示此事件已经消费,不会触发单击事件 return true; } }); } } //得到随机item的高度 private void getRandomHeight(List<String> datas) { heights = new ArrayList<Integer>(); for (int i = 0; i < datas.size(); i++) { heights.add((int) (200+Math.random()*100)); } } @Override public int getItemCount() { return mData == null?0:mData.size(); } public void addItem(int position) { if (mData == null) { mData = new ArrayList<>(); } mData.add(position, "new Item"); //注意,这里更新数据集不是用adapter.notifyDataSetChanged()而是 //notifyItemInserted(position)与notifyItemRemoved(position) 否则没有动画效果。 notifyItemInserted(position); getRandomHeight(mData); } public void deleteItem(int position) { if (mData == null || mData.isEmpty()) { return; } mData.remove(position); notifyItemRemoved(position); getRandomHeight(mData); } public interface OnItemClickListener { void onClick(int position); void onLongClick(int position); } public static class ViewHodler extends RecyclerView.ViewHolder{ TextView mTv; public ViewHodler(View itemView) { super(itemView); mTv = (TextView) itemView.findViewById(R.id.item_tv); } }}
view_rv_item.xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="100dp" android:orientation="vertical"> <TextView android:id="@+id/item_tv" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:background="#fccfcc" android:layout_margin="5dp" android:text="item"/></LinearLayout>
MyDividerItemDecoration.java
package com.example.testnewas.views;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Canvas;import android.graphics.Rect;import android.graphics.drawable.Drawable;import android.support.v4.view.ViewCompat;import android.support.v7.widget.LinearLayoutManager;import android.support.v7.widget.RecyclerView;import android.view.View;/** * Created by ylh on 2017/11/7 0007. * * RecyclerView的间隔样式 */public class MyDividerItemDecoration extends RecyclerView.ItemDecoration { private static final int[] ATTRS = new int[]{ android.R.attr.listDivider }; public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL; public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL; /** * 用于绘制间隔样式 */ private Drawable mDivider; /** * 列表的方向,水平/竖直 */ private int mOrientation; public MyDividerItemDecoration(Context context, int orientation) { // 获取默认主题的属性 final TypedArray a = context.obtainStyledAttributes(ATTRS); mDivider = a.getDrawable(0); a.recycle(); setOrientation(orientation); } @Override public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { // 绘制间隔 if (mOrientation == VERTICAL_LIST) { drawVertical(c, parent); } else { drawHorizontal(c, parent); } } @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { if (mOrientation == VERTICAL_LIST) { outRect.set(0, 0, 0, mDivider.getIntrinsicHeight()); } else { outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0); } } private void setOrientation(int orientation) { if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) { throw new IllegalArgumentException("invalid orientation"); } mOrientation = orientation; } /** * 绘制间隔 */ private void drawVertical(Canvas c, RecyclerView parent) { final int left = parent.getPaddingLeft(); final int right = parent.getWidth() - parent.getPaddingRight(); final 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 top = child.getBottom() + params.bottomMargin + Math.round(ViewCompat.getTranslationY(child)); final int bottom = top + mDivider.getIntrinsicHeight(); mDivider.setBounds(left, top, right, bottom); mDivider.draw(c); } } /** * 绘制间隔 */ private void drawHorizontal(Canvas c, RecyclerView parent) { final int top = parent.getPaddingTop(); final int bottom = parent.getHeight() - parent.getPaddingBottom(); final 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.getRight() + params.rightMargin + Math.round(ViewCompat.getTranslationX(child)); final int right = left + mDivider.getIntrinsicHeight(); mDivider.setBounds(left, top, right, bottom); mDivider.draw(c); } }}
DividerGridItemDecoration.java
package com.example.testnewas.views;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Canvas;import android.graphics.Rect;import android.graphics.drawable.Drawable;import android.support.v7.widget.GridLayoutManager;import android.support.v7.widget.RecyclerView;import android.support.v7.widget.StaggeredGridLayoutManager;import android.view.View;/** * @author zhy * * RecyclerView-GridView的间隔样式 */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); } 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; } 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); 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 + mDivider.getIntrinsicWidth(); mDivider.setBounds(left, top, right, bottom); mDivider.draw(c); } } private boolean isLastColum(RecyclerView parent, int pos, int spanCount, int childCount) { RecyclerView.LayoutManager layoutManager = parent.getLayoutManager(); if (layoutManager instanceof GridLayoutManager) { if ((pos + 1) % spanCount == 0) // 如果是最后一列,则不需要绘制右边 { return true; } } else if (layoutManager instanceof StaggeredGridLayoutManager) { int orientation = ((StaggeredGridLayoutManager) layoutManager) .getOrientation(); if (orientation == StaggeredGridLayoutManager.VERTICAL ) { if ((pos + 1) % spanCount == 0) // 如果是最后一列,则不需要绘制右边 { return true; } } else { childCount = childCount - childCount % spanCount; if (pos >= childCount) // 如果是最后一列,则不需要绘制右边 return true; } } return false; } 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 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()); } }}
自定义间隔样式
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <!-- Customize your theme here. --> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> <item name="android:listDivider">@drawable/divider</item > </style>
divider.xml
<?xml version="1.0" encoding="utf-8"?><shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" > <!-- 填充的颜色 --> <solid android:color ="#ff0000"/> <!-- 线条大小 --> <size android:height ="1dp" android:width ="1dp"/></shape>
自定义的各种动画效果,github上已经有很多类似的项目了,这里我们直接引用下:RecyclerViewItemAnimators,大家自己下载查看。
提供了SlideInOutLeftItemAnimator,SlideInOutRightItemAnimator,
SlideInOutTopItemAnimator,SlideInOutBottomItemAnimator等动画效果。
瀑布流效果.png
阅读全文
0 0
- RecyclerView 使用全体验
- RecyclerView使用初体验
- Recyclerview使用体验(一)
- RecyclerView的使用全攻略
- Android RecyclerView 使用全解
- RecyclerView使用案例二之初体验
- Android RecyclerView 使用完全解析 体验艺术般的控件
- Android RecyclerView 使用完全解析 体验艺术般的控件
- Android5 RecyclerView 使用完全解析 体验艺术般的控件
- Android RecyclerView 使用完全解析 体验艺术般的控件
- Android RecyclerView 使用完全解析 体验艺术般的控件
- Android RecyclerView 使用完全解析 体验艺术般的控件
- Android RecyclerView 使用完全解析 体验艺术般的控件
- Android RecyclerView 使用完全解析 体验艺术般的控件
- Android RecyclerView 使用完全解析 体验艺术般的控件
- Android RecyclerView使用完全解析 体验艺术般的控件
- Android RecyclerView 使用完全解析 体验艺术般的控件
- Android RecyclerView 使用完全解析 体验艺术般的控件
- rtsp客户端做的事情(testRTSPClient)
- 史上最全的maven的pom.xml文件详解
- Krpano学习:在javascript中动态添加/删除/修改热点(向后端写入)
- 八皇后(c/python)
- vsftp 安装配置使用记录
- RecyclerView 使用全体验
- 出口商贸易融资工具:出口信保融资
- 如何删除掉电脑中svn保存的账户密码
- SVN的搭建
- aspx .net ajax应用范例
- 源码编译安装go,ERROR: Cannot find /root/go1.4/bin/go
- 十个值得一试的开源深度学习框架
- 如何使用Spring Boot从0到1搭建一个Java后台(三)
- 近期离线赛总结