# SS Auto dir

```plaintext
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="line">

    <stroke
        android:width="2dp"
        android:color="#000000"
        android:dashWidth="6dp"
        android:dashGap="4dp" />
</shape>

import android.graphics.DashPathEffect
import android.graphics.Paint
import android.graphics.drawable.ShapeDrawable
import android.graphics.drawable.shapes.RectShape
import android.view.View
import androidx.core.content.ContextCompat

fun View.setSolidLine(
    color: Int,
    thickness: Float = 4f
) {
    val shape = ShapeDrawable(RectShape()).apply {
        paint.color = color
        paint.style = Paint.Style.STROKE
        paint.strokeWidth = thickness
    }
    background = shape
}

fun View.setDottedLine(
    color: Int,
    thickness: Float = 4f,
    dashWidth: Float = 15f,
    dashGap: Float = 10f
) {
    val shape = ShapeDrawable(RectShape()).apply {
        paint.color = color
        paint.style = Paint.Style.STROKE
        paint.strokeWidth = thickness
        paint.pathEffect = DashPathEffect(floatArrayOf(dashWidth, dashGap), 0f)
    }
    background = shape
}

// Solid line
myView.setSolidLine(
    color = ContextCompat.getColor(this, android.R.color.black),
    thickness = 6f
)

// Dotted line
myView.setDottedLine(
    color = ContextCompat.getColor(this, android.R.color.holo_red_dark),
    thickness = 6f,
    dashWidth = 20f,
    dashGap = 10f
)

private fun updateMarker(
    context: Context,
    sb: SeekBar,
    rlMarker: View,
    message: String,
) {
    val tvProgress = rlMarker.findViewById<View>(R.id.tvProgress) as TextView
    val vArrow: View = rlMarker.findViewById(R.id.vArrow)

    val width = (sb.width - sb.paddingLeft - sb.paddingRight)

    val isRTL = TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()) == View.LAYOUT_DIRECTION_RTL

    val thumbPos = if (isRTL) {
        // RTL → calculate from right
        sb.width - sb.paddingRight -
                (width * sb.progress / sb.max) -
                Math.round(convertDpToPixel(10f, context))
    } else {
        // LTR (default)
        sb.paddingLeft +
                (width * sb.progress / sb.max) +
                Math.round(convertDpToPixel(10f, context))
    }

    tvProgress.text = message
    tvProgress.post {
        val display =
            (context.getSystemService(Context.WINDOW_SERVICE) as WindowManager).defaultDisplay
        val deviceDisplay = Point()
        display.getSize(deviceDisplay)

        if (isRTL) {
            // vArrow follows thumb in RTL
            vArrow.x = (thumbPos - sb.thumbOffset).toFloat()

            // tvProgress RTL alignment
            if ((thumbPos + tvProgress.width / 2 + sb.paddingRight > deviceDisplay.x)) {
                // tvProgress is beyond right bound
                tvProgress.x = vArrow.x - 20
            } else if ((thumbPos - tvProgress.width / 2 - sb.paddingLeft < 0)) {
                // tvProgress is beyond left bound
                tvProgress.x = vArrow.x - tvProgress.width + 20 + vArrow.width
            } else {
                // in between
                tvProgress.x = thumbPos - tvProgress.width / 2f
            }
        } else {
            // ===== Existing English (LTR) logic =====
            vArrow.x = (thumbPos - sb.thumbOffset).toFloat()

            if ((thumbPos - tvProgress.width / 2 - sb.paddingLeft < 0)) {
                tvProgress.x = vArrow.x - 20
            } else if ((thumbPos + tvProgress.width / 2 + sb.paddingRight > deviceDisplay.x)) {
                tvProgress.x = vArrow.x - tvProgress.width + 20 + vArrow.width
            } else {
                tvProgress.x = thumbPos - tvProgress.width / 2f
            }
        }
    }
}
```

```plaintext
tvProgress.text = message
tvProgress.post {
    val display = (context.getSystemService(Context.WINDOW_SERVICE) as WindowManager).defaultDisplay
    val deviceDisplay = Point()
    display.getSize(deviceDisplay)
    val screenWidth = deviceDisplay.x.toFloat()

    // Keep arrow exactly under thumb, but clamp it so the arrow view stays inside screen
    val rawArrowX = (thumbPos - sb.thumbOffset).toFloat()
    val arrowX = rawArrowX.coerceIn(0f, screenWidth - vArrow.width.toFloat())
    vArrow.x = arrowX

    // Desired center position for tvProgress (centered above thumb)
    val desiredTvX = thumbPos - tvProgress.width / 2f

    // Define safe bounds for tvProgress so it never goes off-screen.
    // Using seekbar paddings so tooltip doesn't overlap seekbar gutters.
    val minTvX = sb.paddingLeft.toFloat()
    val maxTvX = screenWidth - sb.paddingRight - tvProgress.width.toFloat()

    // If tooltip is wider than screen, just pin at 0
    val finalTvX = if (tvProgress.width >= screenWidth) {
        0f
    } else {
        desiredTvX.coerceIn(minTvX, maxTvX)
    }

    tvProgress.x = finalTvX
}

----

tvProgress.text = message
tvProgress.post {
    val display = (context.getSystemService(Context.WINDOW_SERVICE) as WindowManager).defaultDisplay
    val deviceDisplay = Point()
    display.getSize(deviceDisplay)
    val screenWidth = deviceDisplay.x.toFloat()

    // Get the thumb bounds (accurate position of thumb)
    val thumbBounds = sb.thumb.bounds
    val thumbCenterX = sb.x + sb.paddingLeft + thumbBounds.exactCenterX()

    // Arrow should be centered exactly below thumb
    val rawArrowX = thumbCenterX - vArrow.width / 2f
    val arrowX = rawArrowX.coerceIn(0f, screenWidth - vArrow.width.toFloat())
    vArrow.x = arrowX

    // Tooltip (tvProgress) should be centered above thumb
    val desiredTvX = thumbCenterX - tvProgress.width / 2f

    val minTvX = sb.paddingLeft.toFloat()
    val maxTvX = screenWidth - sb.paddingRight - tvProgress.width.toFloat()

    val finalTvX = if (tvProgress.width >= screenWidth) {
        0f
    } else {
        desiredTvX.coerceIn(minTvX, maxTvX)
    }

    tvProgress.x = finalTvX
}

LTR ----------------

tvProgress.text = message
tvProgress.post {
    val display = (context.getSystemService(Context.WINDOW_SERVICE) as WindowManager).defaultDisplay
    val deviceDisplay = Point()
    display.getSize(deviceDisplay)
    val screenWidth = deviceDisplay.x.toFloat()

    // Get the thumb's exact center on screen
    val thumbBounds = sb.thumb.bounds
    val thumbCenterX = sb.x + sb.paddingLeft + thumbBounds.exactCenterX()

    // Arrow: place its center exactly under thumb
    val rawArrowX = thumbCenterX - vArrow.width / 2f
    val arrowX = rawArrowX.coerceIn(0f, screenWidth - vArrow.width.toFloat())
    vArrow.x = arrowX

    // Tooltip: center above thumb
    val desiredTvX = thumbCenterX - tvProgress.width / 2f

    val minTvX = sb.paddingLeft.toFloat()
    val maxTvX = screenWidth - sb.paddingRight - tvProgress.width.toFloat()

    val finalTvX = if (tvProgress.width >= screenWidth) {
        0f
    } else {
        desiredTvX.coerceIn(minTvX, maxTvX)
    }

    tvProgress.x = finalTvX
}

LTR-1------------------------------------

tvProgress.text = message
tvProgress.post {
    val display = (context.getSystemService(Context.WINDOW_SERVICE) as WindowManager).defaultDisplay
    val deviceDisplay = Point()
    display.getSize(deviceDisplay)
    val screenWidth = deviceDisplay.x.toFloat()

    // Thumb's exact center (absolute screen X)
    val thumbBounds = sb.thumb.bounds
    val thumbCenterX = sb.x + sb.paddingLeft + thumbBounds.exactCenterX()

    // --- Arrow ---
    val rawArrowX = thumbCenterX - vArrow.width / 2f
    val arrowX = rawArrowX.coerceIn(0f, screenWidth - vArrow.width.toFloat())
    vArrow.x = arrowX

    // --- Tooltip ---
    // try to center above thumb
    val desiredTvX = thumbCenterX - tvProgress.width / 2f

    // safe boundaries so tooltip never escapes
    val minTvX = 0f
    val maxTvX = screenWidth - tvProgress.width.toFloat()

    val finalTvX = desiredTvX.coerceIn(minTvX, maxTvX)
    tvProgress.x = finalTvX
}

LTR-2------------------------

tvProgress.text = message
tvProgress.post {
    val display = (context.getSystemService(Context.WINDOW_SERVICE) as WindowManager).defaultDisplay
    val deviceDisplay = Point()
    display.getSize(deviceDisplay)
    val screenWidth = deviceDisplay.x.toFloat()

    // Thumb center X
    val thumbBounds = sb.thumb.bounds
    val thumbCenterX = sb.x + sb.paddingLeft + thumbBounds.exactCenterX()

    // --- Tooltip (tvProgress) ---
    val desiredTvX = thumbCenterX - tvProgress.width / 2f
    val minTvX = 0f
    val maxTvX = screenWidth - tvProgress.width.toFloat()
    val finalTvX = desiredTvX.coerceIn(minTvX, maxTvX)
    tvProgress.x = finalTvX

    // --- Arrow (vArrow) ---
    // Arrow should ideally be centered under thumb,
    // but if tvProgress is clamped, adjust arrow to stay inside tooltip
    var arrowX = thumbCenterX - vArrow.width / 2f

    if (arrowX < finalTvX) {
        // Clamp arrow inside left edge of tooltip
        arrowX = finalTvX
    } else if (arrowX + vArrow.width > finalTvX + tvProgress.width) {
        // Clamp arrow inside right edge of tooltip
        arrowX = finalTvX + tvProgress.width - vArrow.width
    }

    vArrow.x = arrowX
}
```

```plaintext
object LocaleHelper {
    fun wrap(context: Context, language: String): Context {
        val locale = Locale(language)
        Locale.setDefault(locale)

        val config = Configuration(context.resources.configuration)
        config.setLocale(locale)

        return context.createConfigurationContext(config)
    }
}

override fun onAttach(context: Context) {
    super.onAttach(LocaleHelper.wrap(context, "en"))
}
```

```plaintext
import android.graphics.*
import android.graphics.drawable.Drawable

class LineDrawable(
    private val color: Int,
    private val thickness: Float,
    private val dashWidth: Float? = null,
    private val dashGap: Float? = null
) : Drawable() {

    private val paint = Paint().apply {
        isAntiAlias = true
        style = Paint.Style.STROKE
        strokeWidth = thickness
        this.color = this@LineDrawable.color
        if (dashWidth != null && dashGap != null) {
            pathEffect = DashPathEffect(floatArrayOf(dashWidth, dashGap), 0f)
        }
    }

    override fun draw(canvas: Canvas) {
        val centerY = bounds.exactCenterY()
        canvas.drawLine(bounds.left.toFloat(), centerY, bounds.right.toFloat(), centerY, paint)
    }

    override fun setAlpha(alpha: Int) { paint.alpha = alpha }
    override fun setColorFilter(colorFilter: ColorFilter?) { paint.colorFilter = colorFilter }
    override fun getOpacity(): Int = PixelFormat.TRANSLUCENT
}
```
