Aperture: Add VerticalSlider widget
This will be used for exposure level adjustment.
Change-Id: Icf30cab3c8a2d7d38d40b2a70bdfbc753af13549
diff --git a/app/src/main/java/org/lineageos/aperture/ui/VerticalSlider.kt b/app/src/main/java/org/lineageos/aperture/ui/VerticalSlider.kt
new file mode 100644
index 0000000..d1dfa4e
--- /dev/null
+++ b/app/src/main/java/org/lineageos/aperture/ui/VerticalSlider.kt
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2022 The LineageOS Project
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package org.lineageos.aperture.ui
+
+import android.annotation.SuppressLint
+import android.content.Context
+import android.graphics.Canvas
+import android.graphics.Color
+import android.graphics.Paint
+import android.graphics.PorterDuff
+import android.graphics.PorterDuffXfermode
+import android.graphics.Rect
+import android.graphics.RectF
+import android.util.AttributeSet
+import android.util.Range
+import android.view.MotionEvent
+import android.view.View
+import org.lineageos.aperture.R
+import org.lineageos.aperture.mapToRange
+import org.lineageos.aperture.px
+
+class VerticalSlider @JvmOverloads constructor(
+ context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
+) : View(context, attrs, defStyleAttr) {
+ private val trackPaint = Paint().apply {
+ style = Paint.Style.FILL
+ xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC)
+ setShadowLayer(1f, 0f, 0f, Color.BLACK)
+ }
+
+ private val thumbPaint = Paint().apply {
+ style = Paint.Style.FILL
+ xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC)
+ setShadowLayer(3f, 0f, 0f, Color.BLACK)
+ }
+
+ private val thumbTextPaint = Paint()
+
+ var progress = 0.5f
+ set(value) {
+ field = value.coerceIn(0f, 1f)
+ invalidate()
+ }
+ var onProgressChangedByUser: ((value: Float) -> Unit)? = null
+
+ var textFormatter: (value: Float) -> String = {
+ "%.01f".format(it)
+ }
+
+ var steps = 0
+
+ init {
+ context.obtainStyledAttributes(attrs, R.styleable.VerticalSlider, 0, 0).apply {
+ try {
+ trackPaint.color = getColor(R.styleable.VerticalSlider_trackColor, Color.WHITE)
+ thumbPaint.color = getColor(R.styleable.VerticalSlider_thumbColor, Color.BLACK)
+ thumbTextPaint.color =
+ getColor(R.styleable.VerticalSlider_thumbTextColor, Color.WHITE)
+ thumbTextPaint.textSize =
+ getDimension(R.styleable.VerticalSlider_thumbTextSize, 10.px.toFloat())
+ } finally {
+ recycle()
+ }
+ }
+ }
+
+ override fun onDraw(canvas: Canvas?) {
+ super.onDraw(canvas!!)
+
+ drawTrack(canvas)
+ drawThumb(canvas)
+ }
+
+ @SuppressLint("ClickableViewAccessibility")
+ override fun onTouchEvent(event: MotionEvent?): Boolean {
+ super.onTouchEvent(event)
+
+ if (!isEnabled) {
+ return false
+ }
+
+ when (event?.action) {
+ MotionEvent.ACTION_DOWN,
+ MotionEvent.ACTION_MOVE,
+ MotionEvent.ACTION_UP -> {
+ progress = (height - event.y.coerceIn(0f, height.toFloat())) / height
+ onProgressChangedByUser?.invoke(progress)
+ }
+ }
+
+ return true
+ }
+
+ private fun track(): RectF {
+ val trackWidth = width / 5
+
+ val left = (width - trackWidth) / 2f
+ val right = left + trackWidth
+
+ val top = width / 2f
+ val bottom = height - top
+
+ return RectF(left, top, right, bottom)
+ }
+
+ private fun drawTrack(canvas: Canvas) {
+ val track = track()
+ val trackRadius = track.width() * 0.75f
+
+ // Draw round rect
+ canvas.drawRoundRect(track, trackRadius, trackRadius, trackPaint)
+ }
+
+ private fun drawThumb(canvas: Canvas) {
+ val track = track()
+ val trackHeight = track.height()
+
+ // Draw circle
+ val cx = width / 2f
+ val cy = if (steps > 0) {
+ val progress = Int.mapToRange(Range(0, steps), progress).toFloat() / steps
+ (trackHeight - (trackHeight * progress)) + track.top
+ } else {
+ (trackHeight - (trackHeight * progress)) + track.top
+ }
+ canvas.drawCircle(cx, cy, width / 2.15f, thumbPaint)
+
+ // Draw text
+ val text = textFormatter(progress)
+ val textBounds = Rect().apply {
+ thumbTextPaint.getTextBounds(text, 0, text.length, this)
+ }
+ canvas.drawText(
+ text, (width - textBounds.width()) / 2f, cy + (textBounds.height() / 2), thumbTextPaint
+ )
+ }
+}
diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml
new file mode 100644
index 0000000..ca271a6
--- /dev/null
+++ b/app/src/main/res/values/attrs.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <declare-styleable name="VerticalSlider">
+ <attr name="trackColor" format="color" />
+ <attr name="thumbColor" format="color" />
+ <attr name="thumbTextColor" format="color" />
+ <attr name="thumbTextSize" format="dimension" />
+ </declare-styleable>
+</resources>