欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android自定义控件实现时间轴

程序员文章站 2022-06-25 20:34:04
本文实例为大家分享了android自定义控件实现时间轴的具体代码,供大家参考,具体内容如下由于项目中有需求,就简单的封装一个,先记录一下,有时间上传到github。1、先增加自定义属性:<...

本文实例为大家分享了android自定义控件实现时间轴的具体代码,供大家参考,具体内容如下

由于项目中有需求,就简单的封装一个,先记录一下,有时间上传到github。

1、先增加自定义属性:

<?xml version="1.0" encoding="utf-8"?>
<resources>
 
    <declare-styleable name="global_timelinelayout">
        <!--时间轴左偏移值-->
        <attr name="global_line_margin_left" format="dimension" />
        <!--时间轴上偏移值-->
        <attr name="global_line_margin_top" format="dimension" />
        <!--线宽-->
        <attr name="global_line_stroke_width" format="dimension" />
        <!--线的颜色-->
        <attr name="global_line_color" format="color" />
        <!--点的大小-->
        <attr name="global_point_inner_size" format="dimension" />
        <attr name="global_point_out_size" format="dimension" />
        <!--点的上偏移值-->
        <attr name="global_point_margin_top" format="dimension" />
        <!--点的颜色-->
        <attr name="global_point_inner_color" format="color" />
        <attr name="global_point_out_color" format="color" />
        <!--图标-->
        <attr name="global_icon_src" format="reference" />
        <!--虚线-->
        <attr name="global_dash_gap" format="dimension" />
        <attr name="global_dash_width" format="dimension" />
    </declare-styleable>
</resources>

2、自定义时间轴类:

/**
     * 时间轴控件
 * <p>the following snippet shows how to include a linear layout in your layout xml file:</p>
 *
 * <com.taoche.mars.commonres.widget.timelinelayout
    android:id="@+id/tl_02"
    android:layout_width="40dp"
    android:layout_height="match_parent"
    app:global_line_margin_left="10dp"
    app:global_line_margin_top="0dp"
    app:global_point_margin_top="10dp"
    app:global_point_inner_color="#377cff"
    app:global_point_out_color="#ffe8f0ff"
    app:global_point_out_size="8dp"
    app:global_point_inner_size="4dp"
    app:global_dash_width="8dp"
    app:global_dash_gap="2dp"
    app:global_line_color="#c9dcff">
    </com.taoche.mars.commonres.widget.timelinelayout>
 *
 * <p>the following snippet shows how to java file:</p>
 *  timelinelayout.setpointmargintop(10)
    timelinelayout.setlinemargintop(10)
    timelinelayout.setpointmargintop(40)
    timelinelayout.setinterrupt(true)
 */
class timelinearlayout @jvmoverloads constructor(context: context, attrs: attributeset? = null,
                                               defstyleattr: int = 0) : linearlayout(context, attrs, defstyleattr) {
    private var mcontext: context? = null
 
    private var mlinemarginleft: int = 10
    private var mlinemargintop: int = 0
    private var mpointmargintop: int = 0
    private var mlinestrokewidth: int = 2
    private var mlinecolor: int = 0
    //内圆半径
    private var mpointinnersize: int = 8
    //外圆半径
    private var mpointoutsize: int = 18
    //内圆颜色
    private var mpointinnercolor: int = 0
    //外圆颜色
    private var mpointoutcolor: int = 0
    //虚线宽
    private var mdashwidth: int = 0
    //虚线空白宽
    private var mdashgap: int = 0
    //是否中断
    private var minterrupt: boolean = false
    private var micon: bitmap? = null
    //线的画笔
    private var mlinepaint: paint? = null
    //点的画笔
    private var mpointpaint: paint? = null
 
    //第一个点的位置
    private var mfirstx = 0
    private var mfirsty = 0
 
    //最后一个图标的位置
    private var mlastx = 0
    private var mlasty = 0
 
    init {
        setlayertype(view.layer_type_software, null) //开启硬件加速
        val ta = context.obtainstyledattributes(attrs, r.styleable.global_timelinelayout)
        mlinemarginleft = ta.getdimensionpixeloffset(r.styleable.global_timelinelayout_global_line_margin_left, 10)
        mlinemargintop = ta.getdimensionpixeloffset(r.styleable.global_timelinelayout_global_line_margin_top, 0)
        mpointmargintop = ta.getdimensionpixeloffset(r.styleable.global_timelinelayout_global_point_margin_top, 0)
        mlinestrokewidth = ta.getdimensionpixeloffset(r.styleable.global_timelinelayout_global_line_stroke_width, 2)
        mlinecolor = ta.getcolor(r.styleable.global_timelinelayout_global_line_color, -0xc22e5b)
        mpointinnersize = ta.getdimensionpixelsize(r.styleable.global_timelinelayout_global_point_inner_size, 8)
        mpointoutsize = ta.getdimensionpixelsize(r.styleable.global_timelinelayout_global_point_out_size, 18)
        mpointinnercolor = ta.getcolor(r.styleable.global_timelinelayout_global_point_inner_color, -0xc22e5b)
        mpointoutcolor = ta.getcolor(r.styleable.global_timelinelayout_global_point_out_color, -0x170f01)
        mdashgap = ta.getdimensionpixeloffset(r.styleable.global_timelinelayout_global_dash_gap, 0)
        mdashwidth = ta.getdimensionpixeloffset(r.styleable.global_timelinelayout_global_dash_width, 0)
        val iconres = ta.getresourceid(r.styleable.global_timelinelayout_global_icon_src, view.no_id)
        if (iconres > view.no_id) {
            val drawable = contextcompat.getdrawable(context,iconres) as? bitmapdrawable
            if (drawable != null) {
                micon = drawable.bitmap
            }
        }
        ta.recycle()
        setwillnotdraw(false)
        initview(context)
    }
 
    fun setlinemargintop(linemargintop:int){
        this.mlinemargintop = linemargintop
    }
 
    fun setpointmargintop(pointmargintop:int){
        this.mpointmargintop = pointmargintop
    }
 
    fun setinterrupt(interrupt:boolean){
        this.minterrupt = interrupt
    }
 
    private fun initview(context: context) {
        mcontext = context
        mlinepaint = paint()
        mlinepaint?.apply {
            isantialias = true
            isdither = true
            color = mlinecolor
            strokewidth = mlinestrokewidth.tofloat()
            style = paint.style.fill_and_stroke
            //虚线设置
            if (mdashgap > 0 && mdashwidth > 0) {
                //mlinepaint.setpatheffect(new dashpatheffect(new float[]{20,5}, 20));
                patheffect = dashpatheffect(floatarrayof(mdashwidth.tofloat(), mdashgap.tofloat()), mdashwidth.tofloat())
            }
        }
 
        mpointpaint = paint()
        mpointpaint?.apply {
            isantialias = true
            isdither = true
            color = mpointinnercolor
            style = paint.style.fill
        }
    }
 
    override fun ondraw(canvas: canvas) {
        super.ondraw(canvas)
        drawtimeline(canvas)
    }
 
    private fun drawtimeline(canvas: canvas) {
        drawbetweenline(canvas)
        drawfirstpoint(canvas)
        drawlasticon(canvas)
    }
 
    private fun drawfirstpoint(canvas: canvas) {
        val top = top
        mfirstx = paddingleft + mlinemarginleft + max(mpointoutsize, mpointinnersize)
        mfirsty = top + paddingtop + mpointmargintop + max(mpointoutsize, mpointinnersize)
 
        //画圆外环
        mpointpaint?.color = mpointoutcolor
        canvas.drawcircle(mfirstx.tofloat(), mfirsty.tofloat(), mpointoutsize.tofloat(), mpointpaint)
        //画圆内环
        mpointpaint?.color = mpointinnercolor
        canvas.drawcircle(mfirstx.tofloat(), mfirsty.tofloat(), mpointinnersize.tofloat(), mpointpaint)
    }
 
    private fun drawlasticon(canvas: canvas) {
        /*if (child != null) {
            int top = child.gettop();
            mlastx = mlinemarginleft;
            mlasty = top + child.getpaddingtop() + mlinemargintop;
            //画图
            canvas.drawbitmap(micon, mlastx - (micon.getwidth() >> 1), mlasty, null);
        }*/
        val top = top
        mlastx = mlinemarginleft + paddingleft
        mlasty = top + paddingtop + mlinemargintop
 
        //画图
        if (micon != null) {
            canvas.drawbitmap(micon, mlastx - (micon!!.width shr 1).tofloat(), height - micon!!.height.tofloat(), null)
        }
    }
 
    private fun drawbetweenline(canvas: canvas) {
        val top = top
        mfirstx = paddingleft + mlinemarginleft + max(mpointoutsize, mpointinnersize)
        mfirsty = top + paddingtop + mlinemargintop
        mlastx = paddingleft + mlinemarginleft + max(mpointoutsize, mpointinnersize)
        mlasty = if(!minterrupt) {top + paddingtop + mlinemargintop + height} else mpointmargintop
 
        //从开始的点到最后的图标之间,画一条线
        canvas.drawline(mfirstx.tofloat(), mfirsty.tofloat(), mlastx.tofloat(), mlasty.tofloat(), mlinepaint)
        //画圆
        //val y = top + paddingtop + mlinemargintop + mpointinnersize
        //canvas.drawcircle(mfirstx, y, mpointsize, mpointpaint);
    }
 
    override fun onmeasure(widthmeasurespec: int, heightmeasurespec: int) {
        super.onmeasure(widthmeasurespec, heightmeasurespec)
        val mode = measurespec.getmode(widthmeasurespec)
        var measuredwidth = measurespec.getsize(widthmeasurespec)
        val measuredheight = measurespec.getsize(heightmeasurespec)
        if (mode == measurespec.at_most) {
            measuredwidth = paddingleft + mlinemarginleft + max(mpointoutsize, mpointinnersize) * 2
        }
        setmeasureddimension(measuredwidth, measuredheight)
    }
}

布局中可以直接引用,如下:

<com.example.demo1224.timelinelayout
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                app:line_margin_left="25dp"
                app:line_margin_top="0dp"
                app:point_margin_top="10dp"
                app:point_inner_color="#377cff"
                app:point_out_color="#ffe8f0ff"
                app:point_out_size="8dp"
                app:point_inner_size="4dp"
                app:dash_width="8dp"
                app:dash_gap="2dp"
                app:line_color="#c9dcff"
                android:orientation="vertical"
                android:background="@android:color/white">
            </com.example.demo1224.timelinelayout>

也可以在代码里面动态设置相关属性(相关属性注释,在自定义属性时有说明):

timelinelayout.setpointmargintop(10)
    timelinelayout.setlinemargintop(10)
    timelinelayout.setpointmargintop(40)
    timelinelayout.setinterrupt(true)

仅供大家参考!

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

相关标签: Android 时间轴