Spinner Gravity or Extra Top Padding?

Roger Garstang

Well-Known Member
Licensed User
Longtime User
Ok, been fighting this text size stuff in a couple different threads now, and now I have a new issue. I modified my View Manager Class so the Spinner/Combobox is created like below and added a new GetCharSize sub to get the Text Size. I replaced all the code in the other Label and Edit Text view creation subs to use the new GetCharSize too and so far they work fine. The Spinner is giving me some issues though.

The main code to be concerned with is in the "If ScaleViews = True Then ' Scale View to Size required for Font" block. Unlike my Edit Text, Spinners seem to apply the 9 Patch, but not the padding. I manually set the padding after assigning the 9 Patch which keeps the text from going over the arrow at the end and appears to be correct for the bottom. The text is too far down though like it has bottom gravity, but actually pushes it outside the bounds of the bottom padding so chars are cut off. Even when I set top padding to 0 like (6dip, 0, 44dip, 5dip) it is better, but still cuts off descenders like on a g or j.

So, is there some type of parent control this sits in that has padding or a way to set gravity to top or centered vertically to get this to display right?

B4X:
' Left/Top: Position to place view, -1 to Place in Current Flow Position, -2 to Place in Next Flow Position.
' Width/Height: Width/Height of View. If ScaleViews is True it will adjust to fit font Height (Set Width= 1 to Scale width to ViewChar). < 1 to Fit to Full Width/Height.
' Name: Name given to the control for reference or use in a Select Case Block.
' ActionSub: Name of Sub to call when Item Selected- Sub YourSub(Position As Int, Value As Object). {Matches the ItemClick for Spinner}
' ActionSubModule: Activity/Module that Sub is in.  (Usually [Me] can be used if Sub is in Activity Module the View resides in).
' ViewChar: Set to desired number of chars visible.
Public Sub AddComboBox(Left As Int, Top As Int, Width As Int, Height As Int, Name As String, Prompt As String, TextSize As Float, ActionSub As String, ActionSubModule As Object, ViewChar As Int) As Rect
Dim myControl As Spinner
Dim ref As Reflector
Dim viewRect As Rect
Dim newActionSub As MyActionSub

   newActionSub.Initialize
   myControl.Initialize("Combobox")
   newActionSub.ActionSub = ActionSub
   newActionSub.ActionSubModule = ActionSubModule
   myControl.Tag = newActionSub
   myControl.Prompt = Prompt
   myControl.TextSize = TextSize
   
   If Top = -2 Then
      Top = NextY
   Else If Top = -1 Then
      Top = CurY
   End If
   If Left = -2 Then
      Left = NextX
   Else If Left = -1 Then
      Left = CurX
   End If
   
   If Width < 1 Then Width = ParentWidth - Padding - Left
   If Height < 1 Then Height = Parent.Height - Padding - Top
   
   If OverrideFontScale = True Then myControl.TextSize = myControl.TextSize / FontScale
   
   If ScaleViews = True Then ' Scale View to Size required for Font
      Dim charRect As Rect
      charRect = GetCharSize(Typeface.DEFAULT, myControl.TextSize, "")
      If Height < charRect.Bottom + 11dip Then Height = charRect.Bottom + 11dip
      If ViewChar > 0 AND Width < 2 Then ' Calculate Min Width
         Width = Min(charRect.Right * ViewChar + 50dip, ParentWidth - Padding - Left)
      Else
         Width = Min(Width, ParentWidth - Padding - Left)
      End If
   End If
   
   Parent.AddView(myControl, Left, Top, Width, Height)
   SetNinePatchDrawable(myControl, "comboboxenabled")
   ref.Target = myControl
   ref.RunMethod4("setPadding", Array As Object(6dip, 6dip, 44dip, 5dip), Array As String("java.lang.int", "java.lang.int", "java.lang.int", "java.lang.int"))
   
   CurX = Left
   NextX = Left + myControl.Width + Padding
   CurY = Top
   NextY = Top + myControl.Height + Padding
   If NextY > Parent.Height Then Parent.Height = NextY
   
   MyViews.Add(myControl)
   If Name.Length > 0 Then NameMap.Put(Name, myControl)
   
   viewRect.Initialize(Left, Top, Left + myControl.Width, Top + myControl.Height)
   Return viewRect
End Sub

' Get the Max Width and Height of a Char or of SampleText if given
Public Sub GetCharSize(ViewTypeface As Typeface, ViewFontsize As Float, SampleText As String) As Rect
Dim testCanvas As Canvas
Dim strUtil As StringUtils
Dim testString As String
Dim CharFrame As Rect

   ScaleLabel.Typeface = ViewTypeface
   ScaleLabel.TextSize = ViewFontsize
   testCanvas.Initialize(ScaleLabel)
   CharFrame.Initialize(0,0,0,0)
   If SampleText.Length = 0 Then testString = CharFilter_Alpha & CharFilter_Numeric & "`~!@#$%^&*()_+=-[]\\{}|;':,./<>?" & QUOTE Else testString = SampleText
   ScaleLabel.Width = testCanvas.MeasureStringWidth(testString, ScaleLabel.Typeface, ScaleLabel.TextSize) + 2dip
   CharFrame.Bottom = strUtil.MeasureMultilineTextHeight(ScaleLabel, testString)
   If SampleText.Length > 0 Then
      CharFrame.Right = ScaleLabel.Width
   Else
      For x = 0 To testString.Length - 1
         CharFrame.Right = Max(CharFrame.Right, testCanvas.MeasureStringWidth(testString.CharAt(x), ScaleLabel.Typeface, ScaleLabel.TextSize))
      Next
   End If
   Return CharFrame
End Sub
 

Roger Garstang

Well-Known Member
Licensed User
Longtime User
Not the items that popup modal with the faded background, the view itself that just shows the current selection and the dropdown arrow on the right.

I updated the complete Class at http://www.b4x.com/forum/additional-libraries-classes-official-updates/19687-class-view-manager.html

One thing interesting to note is I only pass Typeface and Text Size to the new function. A Spinner doesn't have a way of getting Typeface, so I pass Typeface.DEFAULT. I was thinking this wouldn't be a problem, but in my application I have a Username and Password Edit View that even though both set the width(Char width in my class, not width of the view) to be 20 Chars the Password is smaller (like setting InputType somehow changes Typeface too) and it knows the Dots are smaller than regular chars. I'm wondering now if the spinner has more linespacing or something I need to get that isn't being accounted for with just passing Typeface.DEFAULT. Is there a way of getting the Spinner's Typeface?
 
Last edited:
Upvote 0

Roger Garstang

Well-Known Member
Licensed User
Longtime User
Found some threads online talking about using R.layout.textview instead for a spinner control to have more capabilities for fonts. What exactly would that do? I know Labels and Edit Views derive from that, so would a spinner look like an Edit View or Label or would it just have that as like a parent to give more options and still draw like a spinner? I have a 9 Patch, so no big deal if it draws funky. If it doesn't do anything but make things work better it would be good to have it in the core though.
 
Upvote 0

Roger Garstang

Well-Known Member
Licensed User
Longtime User
Well I have found something that seems to work acceptable for the time being or if/when something better is possible. I noticed it seemed to push the font down where about half of it was cut off. Often times when having issues between the Canvas and StringUtil functions giving differing results it was about half the font size difference too, so I decided to add the font size as additional padding. This seems to give it a pretty accurate padding. I tested with font sizes 8-108 and it appeared ok. Any size less than the teens or more than 70 don't look good in the item popup anyway, so I think I can make it work.
 
Upvote 0
Top