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

前言

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

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

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

两列时间轴 单列时间轴-左侧标题 单列时间轴-顶部标题
WeekPlanDTL
NoteInfoSTL
StepSTL
DateInfoDTL
DateInfoSTL
SocialMediaSTL

目录

一、介绍

为什么说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》

感谢你的阅读~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容