Android Question Determine height of all text (csbuilder text) in edittext

RB Smissaert

Well-Known Member
Licensed User
I have a panel with an edittext and below that a table class list, see the attached image.
What I would like to do is have the top of the table just below the last line of text in the edittext, so
I have maximum sight of the table. I can think of various ways to approach this, but maybe somebody
has done this already and show the code that they found works well. Bear in mind that the text is CSBuilder text.

RBS
 

Attachments

  • Drugs in diabetics.png
    Drugs in diabetics.png
    228 KB · Views: 232

RB Smissaert

Well-Known Member
Licensed User
Have you tried StringUtils.MeasureMultilineTextHeight?

Not sure this can work 100% fine. I get somewhat unpredictable results with sometimes the calculated height for
edittext being a bit too small and sometimes a bit too big. Problem is that there is no clear pattern to see here.

This is my current code that sofar works best, but not perfect.

B4X:
Sub ShowSQLEditAndTable
 Dim iTextHeight As Int
 edtSQL.Visible = True
 iTextHeight = sUtils.MeasureMultilineTextHeight(edtSQL, edtSQL.Text)
 General.RunLog("ShowSQLEditAndTable, iTextHeight: " & iTextHeight)
 'this makes the edtSQL too large
 'edtSQL.Height = ((iTextHeight + edtSQL.Padding(1) + edtSQL.Padding(3)) * 100dip) / 100
 edtSQL.Height = iTextHeight + edtSQL.Padding(1) + edtSQL.Padding(3) + 70 'why need this 70?
 If tblSQLResult.NumberOfRows > 0 Then
  lblSQLResult.Visible = True
  tblSQLResult.Visible = True
  lblSQLResult.Top = iSQLEditTop + edtSQL.Height
  tblSQLResult.Top = lblSQLResult.Top + lblSQLResult.Height + 20
  tblSQLResult.Height = pnlSQLEditor.Height - (lblSQLResult.Top + lblSQLResult.Height)
  tblSQLResult.RefreshTable
 Else
  tblSQLResult.Visible = False
  If lblSQLResult.Text.Length > 0 Then
   lblSQLResult.Visible = True
   lblSQLResult.Top = iSQLEditTop + edtSQL.Height
  Else
   lblSQLResult.Visible = False
  End If
 End If
 iSQLPanelType = eSQLPanelType.iSQLAndTable
End Sub

Any suggestions how to improve on this?

RBS
 
Upvote 0

Semen Matusovskiy

Well-Known Member
Licensed User
iTextHeight = sUtils.MeasureMultilineTextHeight(edtSQL, edtSQL.Text)

This explains your wrong results (you loose spans).
Use original CSBuilder

Try to create empty project and to add following code:
B4X:
Sub Globals   
    Dim EditText1 As EditText
    Dim cs As CSBuilder
    Dim su As StringUtils
End Sub

Sub Activity_Create(FirstTime As Boolean)
    EditText1.Initialize ("")
    Activity.AddView (EditText1, 0, 0, 100%x, 20%y)
    cs.Initialize.Color (Colors.Red).Size (50).Append ("Hello ").Pop.Append("World!").PopAll
    EditText1.Text = cs   
    Log (su.MeasureMultilineTextHeight (EditText1, EditText1.Text) / 1dip) ' outputs 31.5 (obviously wrong)
    Log (su.MeasureMultilineTextHeight (EditText1, cs) / 1dip)             ' outputs 87.5 (more realistic, unlike a lot)   
End Sub
 
Last edited:
Upvote 0

RB Smissaert

Well-Known Member
Licensed User
This explains your wrong results (you loose spans).
Use original CSBuilder

Try to create empty project and to add following code:
B4X:
Sub Globals  
    Dim EditText1 As EditText
    Dim cs As CSBuilder
    Dim su As StringUtils
End Sub

Sub Activity_Create(FirstTime As Boolean)
    EditText1.Initialize ("")
    Activity.AddView (EditText1, 0, 0, 100%x, 20%y)
    cs.Initialize.Color (Colors.Red).Size (50).Append ("Hello ").Pop.Append("World!").PopAll
    EditText1.Text = cs  
    Log (su.MeasureMultilineTextHeight (EditText1, EditText1.Text) / 1dip) ' outputs 31.5 (obviously wrong)
    Log (su.MeasureMultilineTextHeight (EditText1, cs) / 1dip)             ' outputs 87.5 (more realistic, unlike a lot)  
End Sub

I tried your suggestion, but get values that are way too low. I made the CSB string a private variable and this is my code:

B4X:
Sub ShowSQLEditAndTable
 'Log (su.MeasureMultilineTextHeight (EditText1, cs) / 1dip
 Dim iTextHeight As Int
 edtSQL.Visible = True
 iTextHeight = sUtils.MeasureMultilineTextHeight(edtSQL, csSQL) / 1dip
 General.RunLog("ShowSQLEditAndTable, iTextHeight: " & iTextHeight)
 'this makes the edtSQL too large
 'edtSQL.Height = ((iTextHeight + edtSQL.Padding(1) + edtSQL.Padding(3)) * 100dip) / 100
 edtSQL.Height = iTextHeight + (edtSQL.Padding(1) + edtSQL.Padding(3)) '+ 250 'why need this 70?
 If tblSQLResult.NumberOfRows > 0 Then
  lblSQLResult.Visible = True
  tblSQLResult.Visible = True
  lblSQLResult.Top = iSQLEditTop + edtSQL.Height
  tblSQLResult.Top = lblSQLResult.Top + lblSQLResult.Height
  'need the -10 here to see the bottom border of the last row
  tblSQLResult.Height = (pnlSQLEditor.Height - (lblSQLResult.Top + lblSQLResult.Height)) - 10
  tblSQLResult.RefreshTable
 Else
  tblSQLResult.Visible = False
  If lblSQLResult.Text.Length > 0 Then
   lblSQLResult.Visible = True
   lblSQLResult.Top = iSQLEditTop + edtSQL.Height
  Else
   lblSQLResult.Visible = False
  End If
 End If
 iSQLPanelType = eSQLPanelType.iSQLAndTable
End Sub

RBS
 
Upvote 0

Semen Matusovskiy

Well-Known Member
Licensed User
I divided per 1 dip to have compatible results only. When the size of font is 50dip, MeasureMultilineTextHeight obviously should show more than 50 dips.

edittext.height uses pixels, you don't need to divide.
 
Upvote 0

RB Smissaert

Well-Known Member
Licensed User
I divided per 1 dip to have compatible results only. When the size of font is 50dip, MeasureMultilineTextHeight obviously should show more than 50 dips.

edittext.height uses pixels, you don't need to divide.

Not sure what is going on here. If I get the text height from the CSB, I always get the same value, 71.

This is in the EditText:

B4X:
Sub edtSQL_TextChanged(Old As String, New As String)
 Dim cs As CSBuilder
 Dim lSQLEditInterval As Long
 Dim lCursorPos As Long
 Dim bOldNoSQLFormattingAtAll As Boolean
 Dim iTextHeight As Int
 If New.Length = 0 Then
  Return
 End If
 General.RunLog("edtSQL_TextChanged 1")
 If bNoSQLFormattingAtAll Then
  Return
 End If
 'to avoid re-entry circular loop
 '-------------------------------
 If lSQLEditTime > 0 Then
  lSQLEditInterval = DateTime.Now - lSQLEditTime
  If lSQLEditInterval < 30 Then
   Return
  End If
 End If
 lSQLEditTime = DateTime.Now
 lCursorPos = edtSQL.SelectionStart
 cs = FormatSQL(New)
 iTextHeight = sUtils.MeasureMultilineTextHeight(edtSQL, edtSQL.Text)
 General.RunLog("edtSQL_TextChanged, iTextHeight(from text): " & iTextHeight)
 iTextHeight = sUtils.MeasureMultilineTextHeight(edtSQL, cs)
 General.RunLog("edtSQL_TextChanged, iTextHeight(from CSB): " & iTextHeight)


RBS
 
Upvote 0

Semen Matusovskiy

Well-Known Member
Licensed User
When I changed font size in CSBuild the results were different.
Can you place your CSBuild in "ordinary" format, something like "cs.Initialize.Color (Colors.Red).Size (50).Append ("Hello ").Pop.Append("World!").PopAll" ?
Then we can compare results. BTW, did you set SingleLine = False for EditText ?
 
Upvote 0

RB Smissaert

Well-Known Member
Licensed User
When I changed font size in CSBuild the results were different.
Can you place your CSBuild in "ordinary" format, something like "cs.Initialize.Color (Colors.Red).Size (50).Append ("Hello ").Pop.Append("World!").PopAll" ?
Then we can compare results. BTW, did you set SingleLine = False for EditText ?

Yes, SingleLine = False

If I put your ordinary CSB in (do this comes instead of cs = FormatSQL(New))
Then still get the same result, 71 for the CSB and 200 for the plain text.

RBS
 
Upvote 0

Semen Matusovskiy

Well-Known Member
Licensed User
I tried to set the same text for EditText and Label. Calculations looks correct, but there is obvious troubles with Gravity, first of all for EditText.
 

Attachments

  • test.zip
    9 KB · Views: 96
Upvote 0

RB Smissaert

Well-Known Member
Licensed User
Any idea why I always get the same value 71?

RBS

All solved nicely now:

B4X:
Sub ShowSQLEditAndTable
 
 Dim strSQLText As String

 edtSQL.Visible = True
 
 strSQLText = edtSQL.text
 bAlwaysDoSQLFormatting = True
 edtSQL.Text = TrimSQL(strSQLText) 'might as well trim here
 bAlwaysDoSQLFormatting = False
 
 'iSQLEditTextHeight is set in the edtSQL_TextChanged event with:
 'iSQLEditTextHeight = sUtils.MeasureMultilineTextHeight(edtSQL, cs)
 '------------------------------------------------------------------
 edtSQL.Height = iSQLEditTextHeight + edtSQL.Padding(1) + edtSQL.Padding(3) + 10
 
 If tblSQLResult.NumberOfRows > 0 Then
  lblSQLResult.Visible = True
  tblSQLResult.Visible = True
  lblSQLResult.Top = iSQLEditTop + edtSQL.Height
  tblSQLResult.Top = lblSQLResult.Top + lblSQLResult.Height
  'need the -10 here to see the bottom border of the last row
  tblSQLResult.Height = (pnlSQLEditor.Height - (lblSQLResult.Top + lblSQLResult.Height)) - 10
  tblSQLResult.RefreshTable
 Else
  tblSQLResult.Visible = False
  If lblSQLResult.Text.Length > 0 Then
   lblSQLResult.Visible = True
   lblSQLResult.Top = iSQLEditTop + edtSQL.Height
  Else
   lblSQLResult.Visible = False
  End If
 End If
 
 iSQLPanelType = eSQLPanelType.iSQLAndTable
 
End Sub


RBS
 
Upvote 0
Top