changeset 2720:9ce1649b0fbd

Android: Fix vertical sliders/scrollbars by creating a DWSlider class to encapsulate the SeekBar... then override the measurements and adjust the width. The width on the SeekBar needs to be set to the height after rotation... Since that is not the actually correct width, we need to wrap it in a frame.
author bsmith@81767d24-ef19-dc11-ae90-00e081727c95
date Thu, 09 Dec 2021 01:57:52 +0000
parents 6754e8f70142
children c0be28906839
files android/DWindows.kt android/dw.cpp
diffstat 2 files changed, 88 insertions(+), 37 deletions(-) [+]
line wrap: on
line diff
--- a/android/DWindows.kt	Wed Dec 08 12:54:25 2021 +0000
+++ b/android/DWindows.kt	Thu Dec 09 01:57:52 2021 +0000
@@ -65,8 +65,7 @@
 import android.util.Base64
 import kotlin.math.*
 import android.content.ContentUris
-
-
+import androidx.appcompat.widget.AppCompatSeekBar
 
 
 // Color Wheel section
@@ -943,6 +942,32 @@
     external fun eventHandlerHTMLChanged(obj1: View, message: Int, URI: String, status: Int)
 }
 
+class DWSlider
+@JvmOverloads constructor(context: Context): FrameLayout(context) {
+    val slider: SeekBar = SeekBar(context)
+
+    init {
+        slider.layoutParams = LayoutParams(LayoutParams.MATCH_PARENT,
+                LayoutParams.WRAP_CONTENT, Gravity.CENTER)
+        addView(slider)
+    }
+
+    @Synchronized
+    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
+        if(slider.rotation == 90F || slider.rotation == 270F) {
+            val layoutHeight = MeasureSpec.getSize(heightMeasureSpec)
+            // set slider width to layout heigth
+            slider.layoutParams.width = layoutHeight
+        }
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
+        if(slider.rotation == 90F || slider.rotation == 270F) {
+            // update layout width to the rotated height of the slider
+            // otherwise the layout remains quadratic
+            setMeasuredDimension(slider.measuredHeight, measuredHeight)
+        }
+    }
+}
+
 class DWSpinButton(context: Context) : AppCompatEditText(context), OnTouchListener {
     var value: Long = 0
     var minimum: Long = 0
@@ -3552,23 +3577,23 @@
         }
     }
 
-    fun scrollBarNew(vertical: Int, cid: Int): SeekBar?
+    fun scrollBarNew(vertical: Int, cid: Int): DWSlider?
     {
-        var slider: SeekBar? = null
+        var scrollbar: DWSlider? = null
 
         waitOnUiThread {
             val dataArrayMap = SimpleArrayMap<String, Long>()
 
-            slider = SeekBar(this)
-            slider!!.tag = dataArrayMap
-            slider!!.id = cid
-            slider!!.max = 1
-            slider!!.progressTintList = null
-            slider!!.progressBackgroundTintList = null
+            scrollbar = DWSlider(this)
+            scrollbar!!.tag = dataArrayMap
+            scrollbar!!.id = cid
+            scrollbar!!.slider.max = 1
+            scrollbar!!.slider.progressTintList = null
+            scrollbar!!.slider.progressBackgroundTintList = null
             if (vertical != 0) {
-                slider!!.rotation = 90F
+                scrollbar!!.slider.rotation = 90F
             }
-            slider!!.setOnSeekBarChangeListener(object : OnSeekBarChangeListener {
+            scrollbar!!.slider.setOnSeekBarChangeListener(object : OnSeekBarChangeListener {
                 override fun onStopTrackingTouch(seekBar: SeekBar) {
                 }
 
@@ -3576,28 +3601,28 @@
                 }
 
                 override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
-                    eventHandlerInt(slider as View, DWEvent.VALUE_CHANGED, slider!!.progress, 0, 0, 0)
+                    eventHandlerInt(scrollbar as View, DWEvent.VALUE_CHANGED, scrollbar!!.slider.progress, 0, 0, 0)
                 }
             })
         }
-        return slider
-    }
-
-    fun sliderNew(vertical: Int, increments: Int, cid: Int): SeekBar?
+        return scrollbar
+    }
+
+    fun sliderNew(vertical: Int, increments: Int, cid: Int): DWSlider?
     {
-        var slider: SeekBar? = null
+        var slider: DWSlider? = null
 
         waitOnUiThread {
             val dataArrayMap = SimpleArrayMap<String, Long>()
 
-            slider = SeekBar(this)
+            slider = DWSlider(this)
             slider!!.tag = dataArrayMap
             slider!!.id = cid
-            slider!!.max = increments
+            slider!!.slider.max = increments
             if (vertical != 0) {
-                slider!!.rotation = 90F
+                slider!!.slider.rotation = 90F
             }
-            slider!!.setOnSeekBarChangeListener(object : OnSeekBarChangeListener {
+            slider!!.slider.setOnSeekBarChangeListener(object : OnSeekBarChangeListener {
                 override fun onStopTrackingTouch(seekBar: SeekBar) {
                 }
 
@@ -3605,7 +3630,7 @@
                 }
 
                 override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
-                    eventHandlerInt(slider as View, DWEvent.VALUE_CHANGED, slider!!.progress, 0, 0, 0)
+                    eventHandlerInt(slider as View, DWEvent.VALUE_CHANGED, slider!!.slider.progress, 0, 0, 0)
                 }
             })
         }
@@ -3627,27 +3652,51 @@
         return percent
     }
 
-    fun percentGetPos(percent: ProgressBar): Int
+    fun percentGetPos(percent: View): Int
     {
         var retval = 0
 
         waitOnUiThread {
-            retval = percent.progress
+            var progress: ProgressBar
+
+            if(percent is ProgressBar) {
+                progress = percent as ProgressBar
+            } else {
+                val slider = percent as DWSlider
+                progress = slider.slider
+            }
+            retval = progress.progress
         }
         return retval
     }
 
-    fun percentSetPos(percent: ProgressBar, position: Int)
+    fun percentSetPos(percent: View, position: Int)
     {
         waitOnUiThread {
-            percent.progress = position
-        }
-    }
-
-    fun percentSetRange(percent: ProgressBar, range: Int)
+            var progress: ProgressBar
+
+            if(percent is ProgressBar) {
+                progress = percent as ProgressBar
+            } else {
+                val slider = percent as DWSlider
+                progress = slider.slider
+            }
+            progress.progress = position
+        }
+    }
+
+    fun percentSetRange(percent: View, range: Int)
     {
         waitOnUiThread {
-            percent.max = range
+            var progress: ProgressBar
+
+            if(percent is ProgressBar) {
+                progress = percent as ProgressBar
+            } else {
+                val slider = percent as DWSlider
+                progress = slider.slider
+            }
+            progress.max = range
         }
     }
 
--- a/android/dw.cpp	Wed Dec 08 12:54:25 2021 +0000
+++ b/android/dw.cpp	Thu Dec 09 01:57:52 2021 +0000
@@ -1929,7 +1929,8 @@
         // First get the class that contains the method you need to call
         jclass clazz = _dw_find_class(env, DW_CLASS_NAME);
         // Get the method that you want to call
-        jmethodID sliderNew = env->GetMethodID(clazz, "sliderNew", "(III)Landroid/widget/SeekBar;");
+        jmethodID sliderNew = env->GetMethodID(clazz, "sliderNew",
+                                               "(III)Lorg/dbsoft/dwindows/DWSlider;");
         // Call the method on the object
         jobject result = _dw_jni_check_result(env, env->CallObjectMethod(_dw_obj, sliderNew, vertical, increments, (jint)cid), _DW_REFERENCE_WEAK);
         return result;
@@ -1955,7 +1956,7 @@
         jclass clazz = _dw_find_class(env, DW_CLASS_NAME);
         // Get the method that you want to call
         jmethodID percentGetPos = env->GetMethodID(clazz, "percentGetPos",
-                                                   "(Landroid/widget/ProgressBar;)I");
+                                                   "(Landroid/view/View;)I");
         // Call the method on the object
         retval = env->CallIntMethod(_dw_obj, percentGetPos, handle);
         if(_dw_jni_check_exception(env))
@@ -1992,7 +1993,8 @@
         // First get the class that contains the method you need to call
         jclass clazz = _dw_find_class(env, DW_CLASS_NAME);
         // Get the method that you want to call
-        jmethodID scrollBarNew = env->GetMethodID(clazz, "scrollBarNew", "(II)Landroid/widget/SeekBar;");
+        jmethodID scrollBarNew = env->GetMethodID(clazz, "scrollBarNew",
+                                                  "(II)Lorg/dbsoft/dwindows/DWSlider;");
         // Call the method on the object
         jobject result = _dw_jni_check_result(env, env->CallObjectMethod(_dw_obj, scrollBarNew, vertical, (jint)cid), _DW_REFERENCE_WEAK);
         return result;
@@ -2040,7 +2042,7 @@
         jclass clazz = _dw_find_class(env, DW_CLASS_NAME);
         // Get the method that you want to call
         jmethodID percentSetRange = env->GetMethodID(clazz, "percentSetRange",
-                                                     "(Landroid/widget/ProgressBar;I)V");
+                                                     "(Landroid/view/View;I)V");
         // Call the method on the object
         env->CallVoidMethod(_dw_obj, percentSetRange, handle, (jint)range);
         _dw_jni_check_exception(env);
@@ -2088,7 +2090,7 @@
         jclass clazz = _dw_find_class(env, DW_CLASS_NAME);
         // Get the method that you want to call
         jmethodID percentSetPos = env->GetMethodID(clazz, "percentSetPos",
-                                                   "(Landroid/widget/ProgressBar;I)V");
+                                                   "(Landroid/view/View;I)V");
         // Call the method on the object
         env->CallVoidMethod(_dw_obj, percentSetPos, handle, (jint)position);
         _dw_jni_check_exception(env);