Android自定义控件实现时间轴
程序员文章站
2022-03-05 23:28:19
本文实例为大家分享了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)
仅供大家参考!
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: Go语言中的UTF-8实现