美文网首页RecyclerViewAndroid读书点点
花式实现时间轴,样式由你来定!

花式实现时间轴,样式由你来定!

作者: 九心_ | 来源:发表于2019-10-08 10:46 被阅读0次

    前言

    因为公司业务经常会涉及到流程,所以使用类似时间轴的控件是不可避免的。又因为公司一直是使用的平板,所以单列时间轴不够美观,一直使用双列的时间轴TimeLine,这是一个借助2列的瀑布流布局实现的RecyclerView完成的时间轴,不过呢,使用瀑布流带来的烦恼是:

    • 位置不好控制:时间轴的每个点的距离不能够均匀分布(不过这也是瀑布流的优点,充分利用空间)
    • 选择单一:如果你的项目既有单列时间轴,又想集成双列时间轴,这种情况下就需要集成两个第三方库
    • 样式单一:多数时间轴库的样式选择过于单一,不能够自己定制

    为了解决以上的痛点,我提供了一种仍基于RecyclerView的新解决方案,该方案已被我集成在Orient-Ui中,以下是我基于此方案自定义实现的几个例子:

    Timeline

    目录

    一、介绍

    为什么说Orient-Ui中的TimeLine灵活呢?因为该方案具有如下特点:

    • 主体样式包括单列时间轴双列时间轴:单列时间轴使用的RecyclerView中的LinearLayoutManager(线性布局),双列时间轴则使用的Orient-Ui中的DoubleSideLayoutManager(两侧布局)
    • 内容样式可控性强:可以轻松控制时间轴的点绘制方式、时间轴中的标题位置和内容、以及时间轴中的时间线等
    • 样式高度的自定义:需要自己在给定的区域内绘制时间标题时间点,这也是该方案灵活的原因

    上述的特点的描述可能不是特别清晰,我们借助两张图加以说明:

    图片 图片
    双列时间轴 单列时间轴

    左右两边分别代表着双列时间轴单列时间轴,其中dot areatitle area是需要实现绘制的区域,其他的例如标题放在RecyclerView子视图的上侧还是还是左侧、标题的颜色、时间点采用的是资源文件绘制还是自绘制、时间线的风格及占用大小等需要创建的时候进行设置。

    二、使用

    我会以上述图片为例,分别介绍单例时间轴双列时间轴。不过在此之前,你需要在build.gradle添加依赖:

    implementation 'com.orient:Orient-Ui:1.0.0'
    

    1. 单列时间轴

    第一步 继承SingleTimeLineDecoration
    我们需要实现抽象方法SingleTimeLineDecoration#onDrawTitleItem,以及针对当前时间点的风格选择复写合适的方法,如果时间点采用的是FLAG_DOT_DRAW(绘制风格),需要复写SingleTimeLineDecoration#onDrawDotItem方法,如果时间点采用的是FLAG_DOT_RES(绘制资源文件),则需要复写SingleTimeLineDecoration#onDrawDotResItem方法:

    public class StepSTL extends SingleTimeLineDecoration {
    
        private Paint mRectPaint;
    
        public StepSTL(SingleTimeLineDecoration.Config config) {
            super(config);
    
            mRectPaint = new Paint();
            mRectPaint.setMaskFilter(new BlurMaskFilter(10, BlurMaskFilter.Blur.SOLID));
            mDotPaint.setMaskFilter(new BlurMaskFilter(6, BlurMaskFilter.Blur.SOLID));
        }
    
        @Override
        protected void onDrawTitleItem(Canvas canvas, int left, int top, int right, int bottom, int pos) {
            ITimeItem item = timeItems.get(pos);
    
            int rectWidth = UIUtils.dip2px(120);
            int height = bottom - top;
            int paddingLeft = UIUtils.dip2px(10);
            mRectPaint.setColor(item.getColor());
            canvas.drawRoundRect(left+paddingLeft,top,left+rectWidth,bottom,UIUtils.dip2px(6),UIUtils.dip2px(6),mRectPaint);
    
    
            String title = item.getTitle();
            if(TextUtils.isEmpty(title))
                return;
            Rect mRect = new Rect();
    
            mTextPaint.getTextBounds(title,0,title.length(),mRect);
            int x = left + (rectWidth - mRect.width())/2;
            //int x = left + UIUtils.dip2px(20);
            int y = bottom - (height - mRect.height())/2;
            canvas.drawText(title,x,y,mTextPaint);
        }
    
        @Override
        protected void onDrawDotItem(Canvas canvas, int cx, int cy, int radius, int pos) {
            ITimeItem item = timeItems.get(pos);
            mDotPaint.setColor(item.getColor());
            canvas.drawCircle(cx,cy,UIUtils.dip2px(6),mDotPaint);
        }
    }
    

    第二步 创建数据
    创建数据类型的时候需要实现ITimeItem接口:

    public class TimeItem implements ITimeItem {
        private String name;
        private String title;
        private String detail;
        private int color;
        private int res;
        // 构造方法省略
        // ... 省略get 和 set 方法
        // 得到当前的标题
        @Override
        public String getTitle() {
            return title;
        }
        // 时间点的颜色
        @Override
        public int getColor() {
            return color;
        }
        // 时间点的资源文件
        // 如果采用的是绘制资源文件
        @Override
        public int getResource() {
            return res;
        }
        // ... 
    }
    

    第三步 初始化RecyclerView
    构建RecyclerView对象,并设置布局方式为LinearLayoutManager以及初始化适配器,这是使用RecyclerView的必备知识,相信你早就烂熟于心了。

    第四步 创建时间轴

    // 初始化数据 
    // 仅需要知道该行代码作用即可
    List<TimeItem> timeItems = TimeItem.initStepInfo();
    // 适配器更新数据 
    // 适配器已经被我封装过
    mAdapter.addAllData(timeItems);
    // 构建时间轴
    TimeLine decoration = new SingleTimeLineDecoration.Builder(getContext(), timeItems) // 添加数据
                    // 标题颜色 和 标题文本的大小为20sp
                    .setTitle(Color.parseColor("#ffffff"), 20)  
                    // 标题位置设置为子视图上边,所占高度为40dp
                    .setTitleStyle(SingleTimeLineDecoration.FLAG_TITLE_TYPE_TOP, 40) 
                    // 时间线风格 绘制时间线区域的宽度(非时间线宽度)为50dp
                    .setLine(SingleTimeLineDecoration.FLAG_LINE_DIVIDE, 50, Color.parseColor("#8d9ca9")) 
                    // 时间点的样式 此处为自绘制
                    .setDot(SingleTimeLineDecoration.FLAG_DOT_DRAW)
                    // 相同的标题隐藏
                    .setSameTitleHide()
                    // 设置实现的时间轴
                    .build(StepSTL.class);
    mRecyclerView.addItemDecoration(decoration);
    

    这步完成之后就可以正常显示了,效果就是上述的活动步骤的那张图:


    单例时间轴

    第五步 更新、删除、添加
    如果需要对数据进行增删查改,那么在进行这些操作之后,你需要对TimeLine中的数据进行更新操作,它同样支持增删改

    函数 解释
    addItems 增加数据
    replace 替换数据
    remove 清除数据

    2. 双列时间轴

    双列时间轴与单列时间轴的区别还是很大的,我会一一说明。
    第一步 继承DoubleTimeLineDecoration
    这里你需要注意的是当前绘制标题是在两列布局中的左列还是右列,需要处理的方法基本同SingleTimeLineDecoration

    第二步 创建数据
    SingleTimeLineDecoration

    第三步 初始化RecyclerView
    这里再用线性布局显然是行不通的,需要改为我写的DoubleSideLayoutManager(两侧布局)

    mRecyclerView.setLayoutManager(new DoubleSideLayoutManager(DoubleSideLayoutManager.START_LEFT));
    

    其他同SingleTimeLineDecoration

    第四步 创建时间轴
    设置方法同SingleTimeLineDecoration。不过需要注意的是两列时间轴不支持

    • 将标题放置在子视图上侧
    • 相同标题隐藏
    • FLAG_LINE_DIVIDE风格的时间线

    第五步 更新、删除、添加
    SingleTimeLineDecoration

    以上就是单列时间轴和双列时间轴的配置了。

    三、更多信息

    经过上面了解,我相信你已经认识到,TimeLine能做的不仅仅是一个时间轴,与流程、步骤相关的它一样可以胜任。不过需要指出的是,TimeLine做的只是为你提供时间轴的布局逻辑,具体时间点和标题的绘制仍需你自己实现,更多的绘制方案以及配置信息还需查看项目地址:
    https://github.com/mCyp/Orient-Ui

    如果你对DoubleSideLayoutManager(两侧布局)感兴趣,可以查看:

    《抽丝剥茧RecyclerView - LayoutManager》

    感谢你的阅读~

    相关文章

      网友评论

        本文标题:花式实现时间轴,样式由你来定!

        本文链接:https://www.haomeiwen.com/subject/oogkpctx.html