上文讲到了RecyclerView的简单使用,知道RecycleView是怎么使用的了,那么这一节将基于上一届的内容继续改进,在ListView中很轻松就能实现的间隔线,在RecycleView中也需要自己去实现,那么这一篇文章就来实现间隔线的添加,当然也包括边框线

添加说明

间隔线添加在线性布局中,边框线添加在网格布局中

在RecycleView中,存在抽象类ItemDecoration,我们需要实现这个类,然后就可以愉快的画线了

实现这个类,需要完成两个方法,一个是onDraw(),用于回调的绘制方法,一个是getItemOffsets(),用于得到Item的偏移量

实现间隔线

由于线性布局涉及到水平和竖直,所以这里也要做出相应的判断

  1. public class MyDividerItemDecoration extends RecyclerView.ItemDecoration {
  2. private int orientation = LinearLayoutManager.VERTICAL;
  3. private Drawable divider;
  4. private final int[] attrs = new int[]{android.R.attr.listDivider};
  5. public MyDividerItemDecoration(Context context, int orientation) {
  6. TypedArray typedArray = context.obtainStyledAttributes(attrs);
  7. divider = typedArray.getDrawable(0);
  8. typedArray.recycle();
  9. setOrientation(orientation);
  10. }
  11. public void setOrientation(int orientation) {
  12. if (orientation != LinearLayoutManager.VERTICAL
  13. && orientation != LinearLayoutManager.HORIZONTAL) {
  14. throw new IllegalArgumentException("unsupport type");
  15. }
  16. this.orientation = orientation;
  17. }
  18. @Override
  19. public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
  20. if (orientation == LinearLayoutManager.VERTICAL) {
  21. outRect.set(0, 0, 0, divider.getIntrinsicHeight());
  22. } else {
  23. outRect.set(0, 0, divider.getIntrinsicWidth(), 0);
  24. }
  25. }
  26. //RecyclerView回调绘制方法
  27. @Override
  28. public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
  29. if (orientation == LinearLayoutManager.VERTICAL) {
  30. drawVertical(c, parent);
  31. } else {
  32. drawHorizontal(c, parent);
  33. }
  34. super.onDraw(c, parent, state);
  35. }
  36. private void drawHorizontal(Canvas c, RecyclerView parent) {
  37. int top = parent.getPaddingTop();
  38. int bottom = parent.getHeight() - parent.getPaddingBottom();
  39. int childCount = parent.getChildCount();
  40. for (int i = 0; i < childCount; i++) {
  41. View child = parent.getChildAt(i);
  42. RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
  43. int left = child.getRight() + params.rightMargin + Math.round(ViewCompat.getTranslationX(child));
  44. int right = left + divider.getIntrinsicHeight();
  45. divider.setBounds(left, top, right, bottom);
  46. divider.draw(c);
  47. }
  48. }
  49. private void drawVertical(Canvas c, RecyclerView parent) {
  50. int left = parent.getPaddingLeft();
  51. int right = parent.getWidth() - parent.getPaddingRight();
  52. int childCount = parent.getChildCount();
  53. for (int i = 0; i < childCount; i++) {
  54. View child = parent.getChildAt(i);
  55. RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
  56. int top = child.getBottom() + params.bottomMargin + Math.round(ViewCompat.getTranslationY(child));
  57. int bottom = top + divider.getIntrinsicHeight();
  58. divider.setBounds(left, top, right, bottom);
  59. divider.draw(c);
  60. }
  61. }
  62. }

在线性布局中调用

  1. public class LineActivity extends AppCompatActivity {
  2. private RecyclerView recyclerView;
  3. private MyRecyclerViewAdapter adapter;
  4. private List<String> list;
  5. private MyDividerItemDecoration decor;
  6. @Override
  7. protected void onCreate(@Nullable Bundle savedInstanceState) {
  8. super.onCreate(savedInstanceState);
  9. setContentView(R.layout.activity_line);
  10. recyclerView = (RecyclerView) findViewById(R.id.line_recyclerview);
  11. list = DataUtils.initData(100);
  12. adapter = new MyRecyclerViewAdapter(list);
  13. //设置点击监听
  14. adapter.setOnItemClickListener(new MyRecyclerViewAdapter.OnItemClickListener() {
  15. @Override
  16. public void onItemClick(View view, int position) {
  17. Toast.makeText(LineActivity.this, "点击 item " + position, Toast.LENGTH_SHORT).show();
  18. }
  19. });
  20. //设置样式,默认垂直
  21. recyclerView.setLayoutManager(new LinearLayoutManager(this));
  22. //水平布局
  23. //recyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, true));
  24. //绘制间隔线
  25. if(decor != null){
  26. recyclerView.removeItemDecoration(decor);
  27. }
  28. decor = new MyDividerItemDecoration(this,LinearLayoutManager.VERTICAL);
  29. recyclerView.addItemDecoration(decor);
  30. recyclerView.setAdapter(adapter);
  31. }
  32. }

实现效果如下图

实现边框线

实现边框线和实现间隔线的思路一致,间隔线是绘制一侧,而边框线是绘制两侧,这是为了防止线条重合,造成整体不美观

首先依旧是要实现ItemDecoration

  1. public class AroundItemDividerDecoration extends RecyclerView.ItemDecoration {
  2. private Drawable divider;
  3. private final int[] attrs = new int[]{android.R.attr.listDivider};
  4. public AroundItemDividerDecoration(Context context) {
  5. divider = context.getResources().getDrawable(R.drawable.item_divider);
  6. }
  7. @Override
  8. public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) {
  9. int right = divider.getIntrinsicWidth();
  10. int bottom = divider.getIntrinsicHeight();
  11. if (isLastColum(itemPosition, parent)) {
  12. right = 0;
  13. }
  14. if (isLastRow(itemPosition, parent)) {
  15. bottom = 0;
  16. }
  17. outRect.set(0, 0, right, bottom);
  18. }
  19. private boolean isLastRow(int itemPosition, RecyclerView parent) {
  20. int spanCount = getSpanCount(parent);
  21. if (spanCount == -1) {
  22. return false;
  23. }
  24. int childCount = parent.getAdapter().getItemCount();
  25. int lastRowCount = childCount % spanCount;
  26. if (lastRowCount == 0 || lastRowCount < spanCount) {
  27. return true;
  28. }
  29. return false;
  30. }
  31. private boolean isLastColum(int itemPosition, RecyclerView parent) {
  32. int spanCount = getSpanCount(parent);
  33. if (spanCount == -1) {
  34. return false;
  35. }
  36. if ((itemPosition + 1) % spanCount == 0) {
  37. return true;
  38. }
  39. return false;
  40. }
  41. private int getSpanCount(RecyclerView parent) {
  42. RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
  43. if (layoutManager instanceof GridLayoutManager) {
  44. GridLayoutManager grid = (GridLayoutManager) parent.getLayoutManager();
  45. int spanCount = grid.getSpanCount();
  46. return spanCount;
  47. }
  48. return -1;
  49. }
  50. @Override
  51. public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
  52. drawVertical(c, parent);
  53. drawHorizontal(c, parent);
  54. }
  55. private void drawHorizontal(Canvas c, RecyclerView parent) {
  56. int childCount = parent.getChildCount();
  57. for (int i = 0; i < childCount; i++) {
  58. View child = parent.getChildAt(i);
  59. RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
  60. int left = child.getLeft() - params.leftMargin;
  61. int right = child.getRight() + params.rightMargin;
  62. int top = child.getBottom() + params.bottomMargin;
  63. int bottom = top + divider.getIntrinsicHeight();
  64. divider.setBounds(left, top, right, bottom);
  65. divider.draw(c);
  66. }
  67. }
  68. private void drawVertical(Canvas c, RecyclerView parent) {
  69. int childCount = parent.getChildCount();
  70. for (int i = 0; i < childCount; i++) {
  71. View child = parent.getChildAt(i);
  72. RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
  73. int left = child.getRight() + params.rightMargin;
  74. int right = left + divider.getIntrinsicWidth();
  75. int top = child.getTop() - params.topMargin;
  76. int bottom = child.getBottom() + params.bottomMargin;
  77. divider.setBounds(left, top, right, bottom);
  78. divider.draw(c);
  79. }
  80. }
  81. }

这里使用的是一个自定义的分割线

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <shape xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:shape="rectangle">
  4. <size
  5. android:width="2dp"
  6. android:height="2dp" />
  7. <solid android:color="#00ff00" />
  8. </shape>

最后在网格布局中调用

  1. public class GridActivity extends AppCompatActivity {
  2. private RecyclerView recyclerView;
  3. private MyRecyclerViewAdapter adapter;
  4. private List<String> list;
  5. private AroundItemDividerDecoration decor;
  6. @Override
  7. protected void onCreate(@Nullable Bundle savedInstanceState) {
  8. super.onCreate(savedInstanceState);
  9. setContentView(R.layout.activity_grid);
  10. recyclerView = (RecyclerView) findViewById(R.id.grid_recyclerview);
  11. list = DataUtils.initData(100);
  12. adapter = new MyRecyclerViewAdapter(list);
  13. //设置样式
  14. recyclerView.setLayoutManager(new GridLayoutManager(this, 3));
  15. recyclerView.setAdapter(adapter);
  16. if(decor != null){
  17. recyclerView.removeItemDecoration(decor);
  18. }
  19. decor = new AroundItemDividerDecoration(this);
  20. recyclerView.addItemDecoration(decor);
  21. }
  22. }

实现效果如下图所示

补充:添加Item

要添加Item,只要知道位置便可,在RecycleView中,数据刷新的方式更加高效,添加了很多局部刷新的方法

在适配器中添加如下方法,便可实现数据添加,删除类似

  1. public void addData(int postion) {
  2. list.add(postion, "addItem" + postion);
  3. notifyItemInserted(postion);
  4. }

然后在activity中调用,为了使画面不那么突兀,添加动画效果

  1. public class LineActivity extends AppCompatActivity {
  2. private RecyclerView recyclerView;
  3. private MyRecyclerViewAdapter adapter;
  4. private List<String> list;
  5. private MyDividerItemDecoration decor;
  6. @Override
  7. protected void onCreate(@Nullable Bundle savedInstanceState) {
  8. super.onCreate(savedInstanceState);
  9. setContentView(R.layout.activity_line);
  10. recyclerView = (RecyclerView) findViewById(R.id.line_recyclerview);
  11. list = DataUtils.initData(100);
  12. adapter = new MyRecyclerViewAdapter(list);
  13. //设置点击监听
  14. adapter.setOnItemClickListener(new MyRecyclerViewAdapter.OnItemClickListener() {
  15. @Override
  16. public void onItemClick(View view, int position) {
  17. Toast.makeText(LineActivity.this, "点击 item " + position, Toast.LENGTH_SHORT).show();
  18. }
  19. });
  20. //设置样式,默认垂直
  21. recyclerView.setLayoutManager(new LinearLayoutManager(this));
  22. //水平布局
  23. //recyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, true));
  24. //设置Item动画
  25. recyclerView.setItemAnimator(new DefaultItemAnimator());
  26. //绘制间隔线
  27. if(decor != null){
  28. recyclerView.removeItemDecoration(decor);
  29. }
  30. decor = new MyDividerItemDecoration(this,LinearLayoutManager.VERTICAL);
  31. adapter.notifyDataSetChanged();
  32. recyclerView.addItemDecoration(decor);
  33. recyclerView.setAdapter(adapter);
  34. }
  35. public void addItem(View view) {
  36. adapter.addData(2);
  37. }
  38. }

实现效果如下



源代码:链接:https://pan.baidu.com/s/13wDP14_cTlrul-YJHgavgg 密码:7vr0

高级UI-RecyclerView间隔线添加的更多相关文章

  1. Android 高级UI设计笔记20:RecyclerView 的详解之RecyclerView添加Item点击事件

    1. 引言: RecyclerView侧重的是布局的灵活性,虽说可以替代ListView但是连基本的点击事件都没有,这篇文章就来详细讲解如何为RecyclerView的item添加点击事件,顺便复习一 ...

  2. Android 高级UI设计笔记07:RecyclerView 的详解

    1. 使用RecyclerView       在 Android 应用程序中列表是一个非常重要的控件,适用场合非常多,如新闻列表.应用列表.消息列表等等,但是从Android 一出生到现在并没有非常 ...

  3. C#使用 DirectX SDK 9做视频播放器 并在视频画线添加文字 VMR9

    视频图像处理系列 索引 VS2013下测试通过. 在百度中搜索关键字“DirectX SDk”,或者进入微软官网https://www.microsoft.com/en-us/download/det ...

  4. firefox 扩展开发笔记(三):高级ui交互编程

    firefox 扩展开发笔记(三):高级ui交互编程 前言 前两篇链接 1:firefox 扩展开发笔记(一):jpm 使用实践以及调试 2:firefox 扩展开发笔记(二):进阶开发之移动设备模拟 ...

  5. 安卓高级3 RecyclerView 和cardView使用案例

    cardView: 添加依赖:在Studio搜索cardview即可 在V7包中 或者直接在gradle中添加 compile 'com.android.support:cardview-v7:24. ...

  6. RecyclerView.ItemDecoration 间隔线

    内容已更新到:https://www.cnblogs.com/baiqiantao/p/19762fb101659e8f4c1cea53e7acb446.html 目录一个通用分割线ItemDecor ...

  7. Android 高级编程 RecyclerView 控件的使用

    RecyclerView 是Android 新添加的一个用来取代ListView的控件,它的灵活性与可替代性比listview更好. 看一下继承关系: ava.lang.Object    ↳ and ...

  8. iOS开发——高级UI&带你玩转UITableView

    带你玩装UITableView 在实际iOS开发中UITableView是使用最多,也是最重要的一个控件,如果你不会用它,那别说什么大神了,菜鸟都不如. 其实关于UItableView事非常简单的,实 ...

  9. 高级UI晋升之View渲染机制(二)

    更多Android高级架构进阶视频学习请点击:https://space.bilibili.com/474380680 优化性能一般从渲染,运算与内存,电量三个方面进行,今天开始说聊一聊Android ...

随机推荐

  1. [USACO]骑马修栅栏 Riding the Fences

    题目链接 题目简述:欧拉回路,字典序最小.没什么好说的. 解题思路:插入边的时候,使用multiset来保证遍历出出答案的字典序最小. 算法模板:for(枚举边) 删边(无向图删两次) 遍历到那个点 ...

  2. 获取登录用户ip

    public static String getIpAddr(HttpServletRequest request) { String ipAddress = null; try { ipAddres ...

  3. MySQL服务优化参数设置参考

    l 通用类: key_buffer_size 含义:用于索引块的缓冲区大小,增加它可得到更好处理的索引(对所有读和多重写). 影响:对于MyISAM表的影响不是很大,MyISAM会使用系统的缓存来存储 ...

  4. 洛谷 P3955 图书管理员 题解

    每日一题 day12 打卡 Analysis 模拟+快速幂 先把图书的编码存起来排序,保证第一个找到的就是最小的.如果要求一个数后x位,就将这个数模10的x次方,同理,我们可以通过这个规律来判断后缀. ...

  5. MondoDB介绍 Python与MongoDB用法,安装PyMongo

    http://blog.csdn.net/t_ells/article/details/50265889 MongoDB最新版本下载在官网的DownLoad菜单下:http://www.mongodb ...

  6. vue上传大文件控件

    文件上传是 Web 开发肯定会碰到的问题,而文件夹上传则更加难缠.网上关于文件夹上传的资料多集中在前端,缺少对于后端的关注,然后讲某个后端框架文件上传的文章又不会涉及文件夹.今天研究了一下这个问题,在 ...

  7. 如何在微信小程序中国引入fontawesome字体图标

    fontawesome官网地址:http://fontawesome.dashgame.com/ 一. 二. 下载之后的字体图标 找到 文件中的如下图.ttf文件 三. 在https://transf ...

  8. T-MAX——项目需求分析

    这个作业属于哪个课程 2019秋福大软件工程实践Z班 这个作业要求在哪里 团队作业第二次-需求规格说明书 团队名称 T-MAX 这个作业的目标 撰写项目需求规格说明书,介绍团队分工 作业正文 T-MA ...

  9. matlab图像灰度调整——imadjust函数的使用

    在MATLAB中,通过函数imadjust()进行图像灰度的调整,该函数调用格式如下: J=imadjust( I )  对图像I进行灰度调整 J=imadjust( I,[low_in;high_i ...

  10. python 设计模式之备忘录模式

    1.为什么用备忘录模式 假设大战僵尸游戏共10关,越是往后关卡越难,越难就越是费时间费钱费精力. 开始大战僵尸,玩了好久好久终于玩到了第9关,真是不容易. 这个时候开始玩第9关了,哇,好难啊,真不幸, ...