实现进度条,实时距离百分比

本文介绍了如何使用ConstraintLayout在移动应用中实现类似地铁或公交站点的实时距离指示,通过计算和偏移视图位置来显示当前位置与下一站的距离,以及使用资源标识符动态获取字符串ID以减少XML编写工作。
摘要由CSDN通过智能技术生成

类似于地铁,公交站点播报,当前站到下一站的距离实时变化

实现样式(已经走过的站点 颜色可以改变,偷懒没搞)

A->B 中间走了10% 那么这一段就显示 10%

方案实现:

采用ConstraintLayout布局

关键代码

上一站点的 viewId
cupPointImageLp.leftToRight = getBasicPointId(context, 0)
下一站点的 ViewId
cupPointImageLp.rightToLeft = getBasicPointId(context, 1)

// 两个站点的距离比
cupPointImageLp.horizontalBias = 0.9f

完整代码

// root 承载的 View
fun setData(context: Context, root: ConstraintLayout) {
    // 基础线
    val basicLine = View(context)
    basicLine.id = getBasicLineId()
    // 圆角设置
    ViewRoundedUtil.allRounded(basicLine, 3F.dp(), basicColor)
    val basicLp = LayoutParams(MATCH_PARENT, 4F.dp().toInt())
    basicLp.leftToLeft = LayoutParams.PARENT_ID
    basicLp.rightToRight = LayoutParams.PARENT_ID
    basicLp.topToTop = getCupId()
    basicLp.bottomToBottom = getCupId()
    basicLp.leftMargin = 16F.dp().toInt()
    basicLp.rightMargin = 16F.dp().toInt()
    basicLine.layoutParams = basicLp
    root.addView(basicLine)
    val scheduleLine = View(context)
    val scheduleLineLp = LayoutParams(0, 4.dp())
    scheduleLineLp.leftToLeft = getBasicLineId()
    scheduleLineLp.topToTop = getBasicLineId()
    scheduleLineLp.bottomToBottom = getBasicLineId()
    scheduleLineLp.rightToRight = getCupPointId()
    scheduleLine.layoutParams = scheduleLineLp
    root.addView(scheduleLine)
    // list 为数据
    for (i in list.indices) {
        val item = list[i]
        val name = TextView(context)
        // 字段仅为代表
        name.text = item.name
        name.id = getNameId(context, i)
        name.textSize = 12F
        name.setTextColor(Color.parseColor("#333333"))
        val nameLp = LayoutParams(WRAP_CONTENT, WRAP_CONTENT)
        val basicPoint = View(context)
        basicPoint.id = getBasicPointId(context, i)
        val basicPointLp = LayoutParams(6.dp(), 6.dp())
        // 圆角设置
        ViewRoundedUtil.allRounded(basicPoint, 3F.dp(), basicColor)
        when (i) {
            0 -> {
                basicPointLp.leftToLeft = getBasicLineId()
                basicPointLp.rightToLeft = getBasicPointId(context, 1)
                basicPointLp.horizontalChainStyle = LayoutParams.CHAIN_SPREAD_INSIDE
                nameLp.leftToLeft = getBasicPointId(context, 0)
            }
            list.size - 1 -> {
                basicPointLp.rightToRight = getBasicLineId()
                basicPointLp.leftToRight = getBasicPointId(context, i - 1)
                nameLp.rightToRight = getBasicPointId(context, i)
            }
            else -> {
                basicPointLp.leftToRight = getBasicPointId(context, i - 1)
                basicPointLp.rightToLeft = getBasicPointId(context, i + 1)
                nameLp.leftToLeft = getBasicPointId(context, i)
                nameLp.rightToRight = getBasicPointId(context, i)
            }
        }
        nameLp.bottomToBottom = LayoutParams.PARENT_ID
        name.layoutParams = nameLp
        root.addView(name)
        basicPointLp.topToTop = getBasicLineId()
        basicPointLp.bottomToBottom = getBasicLineId()
        basicPoint.layoutParams = basicPointLp
        root.addView(basicPoint)
    }
    // 当前进度的位置,可能在当前位置展示图片等,使用这个为占位
    val thisPoint = View(context)
    thisPoint.id = getThisPointId()
    val thisPointImageLp = LayoutParams(1.dp(), 1.dp())
    thisPoint.layoutParams = thisPointImageLp
    thisPointImageLp.leftToRight = getBasicPointId(context, 0)
    thisPointImageLp.rightToLeft = getBasicPointId(context, 1)
    thisPointImageLp.topToTop = getBasicLineId()
    thisPointImageLp.bottomToBottom = getBasicLineId()
    // 比例
    thisPointImageLp.horizontalBias = 0.9f
    root.addView(thisPoint)
    // 进度点位展示的图片 在占位上
    val thisImage = ImageView(context)
    thisImage.id = getCupId()
    thisImage.setBackgroundResource(defaultPointImage)
    val thisImageLp = LayoutParams(24F.dp().toInt(), 24F.dp().toInt())
    thisImageLp.layoutParams = thisImageLp
    thisImageLp.visibility = View.INVISIBLE
    thisImageLp.leftToLeft = getCupPointId()
    thisImageLp.rightToRight = getCupPointId()
    thisImageLp.topToTop = LayoutParams.PARENT_ID
    root.addView(thisImage)
    // 圆角
    ViewRoundedUtil.allRounded(scheduleLine, 3F.dp(), 
}

文中采用的 id 为 StringID 有其他方法的 可以替换 有更高明的方法的话 请指教

private fun getThisId() = R.string.this_image
private fun getthisPointId() = R.string.this_point
private fun getBasicLineId() = R.string.basic_line
/**
 * 暂时是 10 个等级 如果增加了 需要在 string 里增加对应的
 */
private fun getNameId(context: Context, position: Int) = context.resources.getIdentifier(
    "name_${position}",
    "string",
    context.packageName
)
/**
 * 暂时是 10 个等级 如果增加了 需要在 string 里增加对应的
 */
private fun getBasicPointId(context: Context, position: Int) = context.resources.getIdentifier(
    "basic_point_${position}",
    "string",
    context.packageName
)



xml  写死的 点位可能会少 
<string name="name_0">name_id_0</string>
<string name="name_1">name_id_1</string>
<string name="name_2">name_id_2</string>
<string name="name_3">name_id_3</string>
<string name="name_4">name_id_4</string>
<string name="name_5">name_id_5</string>
<string name="name_6">name_id_6</string>
<string name="name_7">name_id_7</string>
<string name="name_8">name_id_8</string>
<string name="name_9">name_id_9</string>
<string name="basic_point_0">basic_point_0</string>
<string name="basic_point_1">basic_point_1</string>
<string name="basic_point_2">basic_point_2</string>
<string name="basic_point_3">basic_point_3</string>
<string name="basic_point_4">basic_point_4</string>
<string name="basic_point_5">basic_point_5</string>
<string name="basic_point_6">basic_point_6</string>
<string name="basic_point_7">basic_point_7</string>
<string name="basic_point_8">basic_point_8</string>
<string name="basic_point_9">basic_point_9</string>
<string name="this_image">this_image</string>
<string name="this_point">this_point</string>
<string name="basic_line">basic_line</string>

备注:

设置圆角的方法 请看上一篇博客不使用 xml 实现圆角

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值