What is the best way to create a view in android that looks like a progress bar but the progress can be scatered depending on where you want it to be

huangapple go评论85阅读模式
英文:

What is the best way to create a view in android that looks like a progress bar but the progress can be scatered depending on where you want it to be

问题

我有一个返回这种类型数据的 API:

"timeRanges": [
{
"start": 25201,
"end": 32399
},
{
"start": 68401,
"end": 82799
},
{
"start": 111601,
"end": 118799
},

这些数据表示以秒为单位的时间间隔,我需要以这种方式表示:

[![点击这里查看图片描述](https://i.stack.imgur.com/cbgAU.png)](https://i.stack.imgur.com/cbgAU.png)

我的问题是:如何创建这个视图,并使每个绿线可点击

我尝试过使用 RangeSlider,但它不支持添加多个范围

我还尝试过使用水平堆叠条形图,但结果不符合我的需求
英文:

I have an api that returns this type of data :

"timeRanges": [
                {
                    "start": 25201,
                    "end": 32399
                },
                {
                    "start": 68401,
                    "end": 82799
                },
                {
                    "start": 111601,
                    "end": 118799
                },

this data represent time intervals in seconds and i need to represent it in this way:

What is the best way to create a view in android that looks like a progress bar but the progress can be scatered depending on where you want it to be

My question is: how can i create that view and make each green line clickable

i tried to use RangeSlider but it doesn't support adding multiple ranges

and i tried to use horizontal stacked bar graph but the results wasn't like what i need

答案1

得分: 0

我写了一个自定义视图,绘制了条形和其中的范围

英文:

i wrote a custom view that draws the bar and the ranges inside it

package com.example.material3app

import android.content.Context
import android.graphics.*
import android.graphics.drawable.Drawable
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import androidx.core.content.ContextCompat


/**
 * Created by Khmaies Hassen on 15,March,2023
 */
class BarView(context: Context, attrs: AttributeSet?) : View(context, attrs) {
    private val paint = Paint()
    private var barHeight = 20
    private var valueFrom = 0
    private var valueTo = 100
    private val ranges = mutableListOf<Range>()
    private var backgroundColor = Color.WHITE
    private var cornerRadius = 10f
    private var selectedRange: Range? = null
    private var onRangeSelectedListener: OnRangeSelectedListener? = null
    private var trackDrawable : Drawable? = null

    init {
        paint.style = Paint.Style.FILL

        if (trackDrawable == null) {
            trackDrawable = ContextCompat.getDrawable(
                getContext(),
                R.drawable.multislider_track_material
            )
        }
    }

    fun setBarHeight(height: Int) {
        barHeight = height
    }

    fun getRanges(): List<Range> {
        return ranges
    }
    fun setValueFrom(value: Int) {
        valueFrom = value
    }

    fun setValueTo(value: Int) {
        valueTo = value
    }

    fun addRange(start: Int, end: Int, color: Int) {
        ranges.add(Range(start, end, color))
    }

    override fun setBackgroundColor(color: Int) {
        backgroundColor = color
    }

    fun setTrackBackground(track: Drawable?) {
        trackDrawable = track
    }

    fun setCornerRadius(radius: Float) {
        cornerRadius = radius
    }

    fun setOnRangeSelectedListener(listener: OnRangeSelectedListener) {
        onRangeSelectedListener = listener
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        val width = MeasureSpec.getSize(widthMeasureSpec)
        val height =  barHeight.toFloat().toInt()
        setMeasuredDimension(width, height)
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)

// Draw the track
        trackDrawable?.let {
            it.setBounds( 0, 0, width, height)
            it.draw(canvas)
        }

        for (range in ranges) {
            paint.color = range.color

            // Calculate range left and right coordinates, clamping them to the view bounds
            val rangeLeft = ((range.start - valueFrom).toFloat() / (valueTo - valueFrom) * width).clamp(0f, width.toFloat())
            val rangeRight = ((range.end - valueFrom).toFloat() / (valueTo - valueFrom) * width).clamp(0f, width.toFloat())

            // Draw rounded rectangle for range
            range.rangeRect.set(rangeLeft, 0f, rangeRight, height.toFloat())
            canvas.drawRoundRect(range.rangeRect, cornerRadius, cornerRadius, paint)
        }

    }

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        trackDrawable?.setBounds(0, 0, w, h)
    }

    override fun setBackground(background: Drawable?) {
        super.setBackground(background)
        trackDrawable = background
    }

    override fun onTouchEvent(event: MotionEvent): Boolean {
        when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                for (range in ranges) {
                    if(range.rangeRect.contains(event.x,event.y)) {
                        onRangeSelectedListener?.onRangeSelected(range.start, range.end)
                        selectedRange = range
                        invalidate()
                        return true
                    }
                }
            }
        }
        return super.onTouchEvent(event)
    }

    inner class Range(val start: Int, val end: Int, val color: Int) {
        val rangeRect = RectF()
    }

    interface OnRangeSelectedListener {
        fun onRangeSelected(start: Int, end: Int)
    }
}

fun Float.clamp(minValue: Float, maxValue: Float): Float {
    return when {
        this < minValue -> minValue
        this > maxValue -> maxValue
        else -> this
    }
}

huangapple
  • 本文由 发表于 2023年3月15日 20:37:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/75744814.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定