Skip to content

Commit 981f8d9

Browse files
feat(ui): Add increment/decrement buttons to slider dialog
This commit enhances the slider dialog by adding circular plus and minus buttons on either side of the SeekBar. These buttons allow for fine-grained, step-by-step adjustment of the selected value. The changes include: - The creation of `ic_plus.xml` and `ic_minus.xml` vector drawables for the new buttons. - A refactor in `DialogManager` to introduce a `commitValue` function, centralizing the logic for updating the value. - The addition of the plus and minus buttons to the slider's layout, enabling users to increment or decrement the value with a click.
1 parent 803c844 commit 981f8d9

File tree

3 files changed

+105
-18
lines changed

3 files changed

+105
-18
lines changed

app/src/main/java/com/github/droidworksstudio/mlauncher/ui/components/DialogManager.kt

Lines changed: 87 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,12 @@ import android.widget.AbsListView
1717
import android.widget.ArrayAdapter
1818
import android.widget.CheckBox
1919
import android.widget.EditText
20+
import android.widget.ImageView
2021
import android.widget.LinearLayout
2122
import android.widget.ListView
2223
import android.widget.SeekBar
2324
import android.widget.TextView
25+
import androidx.appcompat.widget.AppCompatImageButton
2426
import androidx.core.content.ContextCompat
2527
import androidx.core.graphics.toColorInt
2628
import com.github.creativecodecat.components.views.FontBottomSheetDialogLocked
@@ -255,13 +257,13 @@ class DialogManager(val context: Context, val activity: Activity) {
255257
HapticFeedbackService.EffectType.CLICK
256258
)
257259

258-
// Determine if float mode is needed
260+
// Determine float mode
259261
val isFloat = minValue is Float || maxValue is Float || currentValue is Float
260-
261262
val scaleFactor = if (isFloat) steps else 1
263+
262264
val scaledMin = (minValue.toFloat() * scaleFactor).toInt()
263265
val scaledMax = (maxValue.toFloat() * scaleFactor).toInt()
264-
val scaledCurrent = (currentValue.toFloat() * scaleFactor).toInt()
266+
var scaledCurrent = (currentValue.toFloat() * scaleFactor).toInt()
265267

266268
// Outer layout
267269
val container = LinearLayout(context).apply {
@@ -283,36 +285,38 @@ class DialogManager(val context: Context, val activity: Activity) {
283285

284286
// Value display
285287
val valueText = TextView(context).apply {
286-
text = currentValue.toString()
288+
text = if (isFloat) currentValue.toFloat().toString() else currentValue.toInt().toString()
287289
textSize = 16f
288290
gravity = Gravity.CENTER
289291
setPadding(0, 0, 0, 16)
290292
}
291293

294+
fun commitValue() {
295+
val value = if (isFloat) {
296+
scaledCurrent.toFloat() / scaleFactor
297+
} else {
298+
scaledCurrent
299+
}
300+
valueText.text = value.toString()
301+
onValueSelected(value)
302+
}
303+
292304
// SeekBar
293305
val seekBar = SeekBar(context).apply {
294306
min = scaledMin
295307
max = scaledMax
296308
progress = scaledCurrent
309+
layoutParams = LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT, 1f)
297310
setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
298311
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
299-
val value = if (isFloat) {
300-
(progress.toFloat() / scaleFactor)
301-
} else {
302-
progress
303-
}
312+
scaledCurrent = progress
313+
val value = if (isFloat) scaledCurrent.toFloat() / scaleFactor else scaledCurrent
304314
valueText.text = value.toString()
305315
}
306316

307317
override fun onStartTrackingTouch(seekBar: SeekBar?) {}
308-
309318
override fun onStopTrackingTouch(seekBar: SeekBar?) {
310-
val value = if (isFloat) {
311-
(seekBar?.progress?.toFloat() ?: 0f) / scaleFactor
312-
} else {
313-
seekBar?.progress ?: 0
314-
}
315-
onValueSelected(value)
319+
commitValue()
316320
HapticFeedbackService.trigger(
317321
context,
318322
HapticFeedbackService.EffectType.SELECT
@@ -321,11 +325,76 @@ class DialogManager(val context: Context, val activity: Activity) {
321325
})
322326
}
323327

324-
// Build and show layout
328+
fun createCircleButton(
329+
context: Context,
330+
iconRes: Int
331+
): AppCompatImageButton {
332+
333+
val sizeDp = 20
334+
val sizePx = (sizeDp * context.resources.displayMetrics.density).toInt()
335+
val paddingDp = 2
336+
val paddingPx = (paddingDp * context.resources.displayMetrics.density).toInt()
337+
338+
return AppCompatImageButton(context).apply {
339+
setImageResource(iconRes)
340+
scaleType = ImageView.ScaleType.CENTER_INSIDE
341+
342+
layoutParams = LinearLayout.LayoutParams(sizePx, sizePx).apply {
343+
marginStart = 4
344+
marginEnd = 4
345+
}
346+
347+
background = GradientDrawable().apply {
348+
shape = GradientDrawable.OVAL
349+
setColor(ContextCompat.getColor(context, R.color.buttonTextPrimary))
350+
}
351+
352+
// 👇 space around the icon
353+
setPadding(paddingPx, paddingPx, paddingPx, paddingPx)
354+
355+
// 👇 required for tiny buttons
356+
minimumWidth = 0
357+
minimumHeight = 0
358+
}
359+
}
360+
361+
// Usage
362+
val minusButton = createCircleButton(context, R.drawable.ic_minus).apply {
363+
setOnClickListener {
364+
if (scaledCurrent > scaledMin) {
365+
scaledCurrent--
366+
seekBar.progress = scaledCurrent
367+
commitValue()
368+
}
369+
}
370+
}
371+
372+
val plusButton = createCircleButton(context, R.drawable.ic_plus).apply {
373+
setOnClickListener {
374+
if (scaledCurrent < scaledMax) {
375+
scaledCurrent++
376+
seekBar.progress = scaledCurrent
377+
commitValue()
378+
}
379+
}
380+
}
381+
382+
383+
// Horizontal layout for buttons + slider
384+
val sliderLayout = LinearLayout(context).apply {
385+
orientation = LinearLayout.HORIZONTAL
386+
gravity = Gravity.CENTER_VERTICAL
387+
addView(minusButton)
388+
addView(seekBar)
389+
addView(plusButton)
390+
}
391+
392+
// Build layout
325393
container.addView(titleText)
326394
container.addView(valueText)
327-
container.addView(seekBar)
395+
container.addView(sliderLayout)
328396

397+
// Show bottom sheet
329398
sliderBottomSheet = FontBottomSheetDialogLocked(context).apply {
330399
setContentView(container)
331400
show()
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
2+
android:width="24dp"
3+
android:height="24dp"
4+
android:viewportWidth="24"
5+
android:viewportHeight="24">
6+
<path
7+
android:fillColor="@android:color/white"
8+
android:pathData="M19,13H5V11H19V13Z" />
9+
</vector>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
2+
android:width="24dp"
3+
android:height="24dp"
4+
android:viewportWidth="24"
5+
android:viewportHeight="24">
6+
<path
7+
android:fillColor="@android:color/white"
8+
android:pathData="M19,13H13V19H11V13H5V11H11V5H13V11H19V13Z"/>
9+
</vector>

0 commit comments

Comments
 (0)