@@ -17,10 +17,12 @@ import android.widget.AbsListView
1717import android.widget.ArrayAdapter
1818import android.widget.CheckBox
1919import android.widget.EditText
20+ import android.widget.ImageView
2021import android.widget.LinearLayout
2122import android.widget.ListView
2223import android.widget.SeekBar
2324import android.widget.TextView
25+ import androidx.appcompat.widget.AppCompatImageButton
2426import androidx.core.content.ContextCompat
2527import androidx.core.graphics.toColorInt
2628import 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()
0 commit comments