根据美国CNBC新闻网站报道,美国最大期权交易市场芝加哥期权交易所宣布将在12月10日在旗下的期货交易平台Cboe Futures Exchange推出比特币期货产品,正式对将在12月18日推出此项交易的芝加哥商业交易所宣战。而地处纽约的纳斯达克交易所也即将在2018年上半年“参战”并推出比特币交易。
本篇文章来自 FuKaiqiang_2016 的投稿。主要介绍了RecyclerView常用功能解析,希望对大家有所帮助! FuKaiqiang_2016 的博客地址: http://blog.csdn.net/fkq_2016
普通的上下滑动和左右滑动 Grid效果上下滑动和左右滑动 瀑布流的上下滑动和左右滑动 添加分割线 去除最后一个item的分割线 添加点击事件 增加和删除item 添加动画 多布局 下拉刷新和上拉加载 添加头布局和脚布局 拖拽排序和侧滑删除 分页加载、上拉加载、添加脚布局DEMO
RecyclerView.Adapter :创建子项item布局和绑定数据 RecyclerView.ViewHolder :生成子项item的布局 RecyclerView.LayoutManager :设置子项item的排列方式 RecyclerView.ItemDecoration : 设置子项item的分割线 RecyclerView.ItemAnimator : 设置子项item的动画
compile 'com.android.support:recyclerview-v7:26.0.0-alpha1'
LinearLayout xmlns:android='http://schemas./apk/res/android' android:layout_width='match_parent' android:layout_height='match_parent'> android.support.v7.widget.RecyclerView android:id='@+id/main_recyclerview' android:layout_width='match_parent' android:layout_height='match_parent'> android.support.v7.widget.RecyclerView> LinearLayout>
public class MainActivity extends AppCompatActivity { private RecyclerView mMain_recyclerview; private List mList; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); initView(); initData(); initAdapter(); } //初始化控件 private void initView() { setContentView(R.layout.activity_main); mMain_recyclerview = (RecyclerView) findViewById(R.id.main_recyclerview); } //初始化数据 private void initData() { mList = new ArrayList<>(); for (int i = 0; i <>10; i++) { mList.add('纵向和横向滑动'); mList.add('纵向和横向瀑布流'); mList.add('添加头布局和脚布局'); mList.add('下拉刷新和上拉加载'); mList.add('多布局页面'); mList.add('滑动删除'); mList.add('点击事件'); mList.add('添加空布局'); mList.add('添加分割线'); } } //初始化Adapter private void initAdapter() { //设置布局管理器 mMain_recyclerview.setLayoutManager(new LinearLayoutManager(this)); //初始化和设置Adapter MainAdapter mainAdapter = new MainAdapter(mList); mMain_recyclerview.setAdapter(mainAdapter); }}
public class MainAdapter extends RecyclerView.AdapterMainAdapter.ViewHolder> { private List mList; public MainAdapter(List list) { mList = list; } //创建子项item的布局 @Override public MainAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.main_item, parent, false); return new ViewHolder(view); } //给控件设置数据 @Override public void onBindViewHolder(MainAdapter.ViewHolder holder, int position) { holder.tv_main.setText(mList.get(position)); } //子项item的数量 @Override public int getItemCount() { return mList.size(); } //初始化子项控件 static class ViewHolder extends RecyclerView.ViewHolder { TextView tv_main; public ViewHolder(View itemView) { super(itemView); this.tv_main = itemView.findViewById(R.id.tv_main); } }}
//ListView形式上下滑动: mMain_recyclerview.setLayoutManager(new LinearLayoutManager(this)); //左右滑动: LinearLayoutManager magager = new LinearLayoutManager(this);magager.setOrientation(LinearLayoutManager.HORIZONTAL); //Grid形式上下滑动: GridLayoutManager layoutManager = new GridLayoutManager(this,4); //Grid形式左右滑动: GridLayoutManager layoutManager = new GridLayoutManager(this, 4);layoutManager.setOrientation(GridLayoutManager.HORIZONTAL); //瀑布流形式上下滑动: StaggeredGridLayoutManager layoutManager = newStaggeredGridLayoutManager(4, StaggeredGridLayoutManager.VERTICAL); //瀑布流形式左右滑动: StaggeredGridLayoutManager layoutManager = newStaggeredGridLayoutManager(4, StaggeredGridLayoutManager.HORIZONTAL);
mMain_recyclerview.addItemDecoration(new MyDividerItemDecoration(this, MyDividerItemDecoration.VERTICAL_LIST));
ondraw:绘制 getItemOffsets:绘制的区域
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 int mOrientation; private Drawable mDivider; private int mDividerHeight = 2; //默认是2px private Paint mPaint; //绘制默认分割线 public MyDividerItemDecoration(Context context, int orientation) { final TypedArray a = context.obtainStyledAttributes(ATTRS); mDivider = a.getDrawable(0); //系统属性中获取 a.recycle(); setOrientation(orientation); } /** * 自定义分割线 * * @param context * @param orientation 列表方向 * @param drawableId 分割线图片 */ public MyDividerItemDecoration(Context context, int orientation, int drawableId) { this(context, orientation); mDivider = ContextCompat.getDrawable(context, drawableId); mDividerHeight = mDivider.getIntrinsicHeight(); } /** * 自定义分割线 * * @param context * @param orientation 列表方向 * @param dividerHeight 分割线高度 * @param dividerColor 分割线颜色 */ public MyDividerItemDecoration(Context context, int orientation, int dividerHeight, int dividerColor) { this(context, orientation); mDividerHeight = dividerHeight; mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mPaint.setColor(dividerColor); mPaint.setStyle(Paint.Style.FILL); } private void setOrientation(int orientation) { if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) { throw new IllegalArgumentException('invalid orientaion'); } mOrientation = orientation; } @Override //在RecyclerView的onDraw中执行 public void onDraw(Canvas c, RecyclerView parent) { if (mOrientation == VERTICAL_LIST) { drawVertical(c, parent); } else { drawHorizontal(c, parent); } } 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 <>1; i++) { final View child = parent.getChildAt(i); final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams(); final int left = child.getRight() + params.rightMargin; final int right = left + mDivider.getIntrinsicHeight(); mDivider.setBounds(left, top, right, bottom); mDivider.draw(c); } } 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 <>1; i++) { final View child = parent.getChildAt(i); RecyclerView v = new RecyclerView(parent.getContext()); final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams(); final int top = child.getBottom() + params.bottomMargin; final int bottom = top + mDivider.getIntrinsicHeight(); mDivider.setBounds(left, top, right, bottom); mDivider.draw(c); } } @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { if (mOrientation == VERTICAL_LIST) { outRect.set(0, 0, 0, mDividerHeight); } else { outRect.set(0, 0, mDividerHeight, 0); } }}
mRecyclerView.addItemDecoration(new DividerGridItemDecoration(this));
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()); } }}
RecyclerView去除最后一个item的分割线
public class PortraitAdapter extends RecyclerView.AdapterPortraitAdapter.ViewHolder> { private List mFruitList; private boolean flag = true; public PortraitAdapter(List fruitList) { mFruitList = fruitList; } static class ViewHolder extends RecyclerView.ViewHolder { ImageView fruitImage; TextView fruitName; LinearLayout ll_portraitscape; public ViewHolder(View view) { super(view); fruitImage = (ImageView) view.findViewById(R.id.fruit_image); fruitName = (TextView) view.findViewById(R.id.fruit_name); ll_portraitscape = (LinearLayout) view.findViewById(R.id.ll_portraitscape); } } @Override public ViewHolder onCreateViewHolder(final ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_portrait, parent, false); final ViewHolder holder = new ViewHolder(view); holder.ll_portraitscape.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { new AlertDialog.Builder(v.getContext()) .setTitle('确认删除吗') .setNegativeButton('取消',null) .setPositiveButton('确定', new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { if (flag == true){ removeData(holder.getAdapterPosition()); flag=false; }else{ addData(holder.getAdapterPosition()); flag=true; } } }).show(); return false; } }); holder.fruitImage.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Toast.makeText(parent.getContext(),'我是图片短点击',Toast.LENGTH_SHORT).show(); } }); return holder; } @Override public void onBindViewHolder(final ViewHolder holder, int position) { Fruit fruit = mFruitList.get(position); holder.fruitImage.setImageResource(fruit.getImageId()); holder.fruitName.setText(fruit.getName()); } @Override public int getItemCount() { return mFruitList.size(); } public void addData(int position) { mFruitList.add(position, new Fruit('Apple', R.drawable.apple_pic)); notifyItemInserted(position); } public void removeData(int position) { mFruitList.remove(position); notifyItemRemoved(position); }}
只需要在onCreateViewHolder中处理即可,可以很轻松实现子项中任意控件或布局的点击事件。
public void addData(int position) { mFruitList.add(position, new Fruit('Apple', R.drawable.apple_pic)); notifyItemInserted(position);} public void removeData(int position) { mFruitList.remove(position); notifyItemRemoved(position);}
holder.ll_portraitscape.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { new AlertDialog.Builder(v.getContext()) .setTitle('确认删除吗') .setNegativeButton('取消',null) .setPositiveButton('确定', new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { if (flag == true){ removeData(holder.getAdapterPosition()); flag=false; }else{ addData(holder.getAdapterPosition()); flag=true; } } }).show(); return false; }});
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
private int mLastPosition;//放在成员变量的位置上 if (viewHolder.getAdapterPosition() > mLastPosition) { ObjectAnimator scaleX = ObjectAnimator.ofFloat(viewHolder.itemView, 'scaleX', 0.5f, 1f); scaleX.start(); mLastPosition = viewHolder.getLayoutPosition();}
说明:实现的方式有很多种,这里介绍一种,就是在RecyclerView的onBindViewHolder中利用属性动画就可以实现非常华丽的效果。
@Override public int getItemViewType(int position) { if (mNewsBeanList.get(position).getThumbnail_pic_s03() == null) { return IMAGE_ONLY_ONE; } else { return IMAGE_TWOORTHREE; }}
说明:判断下布局的不同,返回不同的值,不同的值就代表了不多的布局。
@Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { if (viewType == IMAGE_TWOORTHREE) { View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.news_imagethree_item, viewGroup, false); ImageThreeViewHolder viewHolder = new ImageThreeViewHolder(view); return viewHolder; } else { View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.news_imageonly_item, viewGroup, false); ImageOnlyOneViewHolder viewHolder = new ImageOnlyOneViewHolder(view); return viewHolder; }}
static class ImageThreeViewHolder extends RecyclerView.ViewHolder { private TextView mTv_title; private ImageView mIv_image01; private ImageView mIv_image02; private ImageView mIv_image03; private TextView mTv_company; private TextView mTv_time; private View mItemView; public ImageThreeViewHolder(View itemView) { super(itemView); mItemView = itemView; mTv_title = itemView.findViewById(R.id.tv_title); mIv_image01 = itemView.findViewById(R.id.iv_image01); mIv_image02 = itemView.findViewById(R.id.iv_image02); mIv_image03 = itemView.findViewById(R.id.iv_image03); mTv_company = itemView.findViewById(R.id.tv_company); mTv_time = itemView.findViewById(R.id.tv_time); }} static class ImageOnlyOneViewHolder extends RecyclerView.ViewHolder { private View mItemView; private TextView mTv_title; private TextView mTv_company; private TextView mTv_time; private ImageView mIv_image01; public ImageOnlyOneViewHolder(View itemView) { super(itemView); mItemView = itemView; mTv_title = itemView.findViewById(R.id.tv_title); mTv_company = itemView.findViewById(R.id.tv_company); mTv_time = itemView.findViewById(R.id.tv_time); mIv_image01 = itemView.findViewById(R.id.iv_image01); }}
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) { if (viewHolder instanceof ImageThreeViewHolder) { ((ImageThreeViewHolder) viewHolder).mTv_title.setText(mNewsBeanList.get(position).getTitle()); ((ImageThreeViewHolder) viewHolder).mTv_company.setText(mNewsBeanList.get(position).getAuthor_name()); ((ImageThreeViewHolder) viewHolder).mTv_time.setText(mNewsBeanList.get(position).getDate()); Glide.with(mContext).load(mNewsBeanList.get(position).getThumbnail_pic_s()).into(((ImageThreeViewHolder) viewHolder).mIv_image01); Glide.with(mContext).load(mNewsBeanList.get(position).getThumbnail_pic_s02()).into(((ImageThreeViewHolder) viewHolder).mIv_image02); Glide.with(mContext).load(mNewsBeanList.get(position).getThumbnail_pic_s03()).into(((ImageThreeViewHolder) viewHolder).mIv_image03); } else if (viewHolder instanceof ImageOnlyOneViewHolder) { ((ImageOnlyOneViewHolder) viewHolder).mTv_title.setText(mNewsBeanList.get(position).getTitle()); ((ImageOnlyOneViewHolder) viewHolder).mTv_company.setText(mNewsBeanList.get(position).getAuthor_name()); ((ImageOnlyOneViewHolder) viewHolder).mTv_time.setText(mNewsBeanList.get(position).getDate()); Glide.with(mContext).load(mNewsBeanList.get(position).getThumbnail_pic_s()).into(((ImageOnlyOneViewHolder) viewHolder).mIv_image01); }}
@Override private void initRefresh() { srRefresh.setColorSchemeResources(R.color.colorPrimary); srRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { refreshFruits(); } });}
private void refreshFruits() { new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } runOnUiThread(new Runnable() { @Override public void run() { initFruits(); adapter.notifyDataSetChanged(); srRefresh.setRefreshing(false); } }); } }).start();}
private void initFruits() { fruitList.clear(); for (int i = 0; i <>50; i++) { Random random = new Random(); int index = random.nextInt(fruits.length); fruitList.add(fruits[index]); }}
说明:SwipeRefreshLayout设置一个监听器:setOnRefreshListener,onRefresh方法中进行数据更新的操作。
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); if (newState == RecyclerView.SCROLL_STATE_IDLE) { if (adapter.isFadeTips() == false && lastVisibleItem + 1 == adapter.getItemCount()) { mHandler.postDelayed(new Runnable() { @Override public void run() { updateRecyclerView(adapter.getRealLastPosition(), adapter.getRealLastPosition() + PAGE_COUNT); } }, 500); } if (adapter.isFadeTips() == true && lastVisibleItem + 2 == adapter.getItemCount()) { mHandler.postDelayed(new Runnable() { @Override public void run() { updateRecyclerView(adapter.getRealLastPosition(), adapter.getRealLastPosition() + PAGE_COUNT); } }, 500); } } } @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); lastVisibleItem = mLayoutManager.findLastVisibleItemPosition(); } });
说明:recyclerView添加滑动监听器addOnScrollListener,在onScrollStateChanged方法中处理加载的动作。
private void initBind() { //为RecycleView绑定触摸事件 ItemTouchHelper helper = new ItemTouchHelper(new ItemTouchHelper.Callback() { @Override public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { //侧滑删除 int swipeFlags = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT; //首先回调的方法 返回int表示是否监听该方向 int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT; //拖拽 return makeMovementFlags(dragFlags, swipeFlags); } @Override public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) { //滑动事件 Collections.swap(list, viewHolder.getAdapterPosition(), target.getAdapterPosition()); adapter.notifyItemMoved(viewHolder.getAdapterPosition(), target.getAdapterPosition()); return false; } @Override public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { //侧滑事件 list.remove(viewHolder.getAdapterPosition()); adapter.notifyItemRemoved(viewHolder.getAdapterPosition()); } @Override public boolean isLongPressDragEnabled() { //是否可拖拽 return true; } }); helper.attachToRecyclerView(recyclerView);}
private final int PAGE_COUNT = 10;adapter = new MyAdapter(getDatas(0, PAGE_COUNT), this, getDatas(0, PAGE_COUNT).size() > 0 ? true : false);
private List getDatas(final int firstIndex, final int lastIndex) { List resList = new ArrayList<>(); for (int i = firstIndex; i < lastindex;="" i++)="" {="" ="" ="" =""> if (i < list.size())="" {="" ="" ="" ="" ="" ="" reslist.add(list.get(i));="" ="" ="" ="" }="" ="" }="" ="">return resList;} private void updateRecyclerView(int fromIndex, int toIndex) { List newDatas = getDatas(fromIndex, toIndex); if (newDatas.size() > 0) { adapter.updateList(newDatas, true); } else { adapter.updateList(null, false); }}
demo的源码地址: https://github.com/OnlyYouMyLove/PullToLoadData-RecyclerView
|