How can I read a particular line in a multi-line label? There are no linebreaks, so the lines are set by the label.
RBS
RBS
It is possible with BBLabel.
I would have chosen BBLabel or BBCodeView if I needed to make such measurements. Measuring text is not a small problem.Didn't know about BBLabel and I think it would add unjustified complexity to solve a small problem
For Each line As BCTextLine In BBCodeView1.Paragraph.TextLines
Dim sb As StringBuilder
sb.Initialize
For Each un As BCUnbreakableText In line.Unbreakables
For i = 0 To un.NotFullTextChars.Length - 1
sb.Append(un.NotFullTextChars.Buffer(un.NotFullTextChars.StartIndex + i))
Next
Next
Log(sb.ToString)
Next
I would have chosen BBLabel or BBCodeView if I needed to make such measurements. Measuring text is not a small problem.
Here is the relevant code for anyone who is interested:
Note that some characters will be missing if there are unbreakable words with multiple styles. Only the text of the first style in each word will appear.B4X:For Each line As BCTextLine In BBCodeView1.Paragraph.TextLines Dim sb As StringBuilder sb.Initialize For Each un As BCUnbreakableText In line.Unbreakables For i = 0 To un.NotFullTextChars.Length - 1 sb.Append(un.NotFullTextChars.Buffer(un.NotFullTextChars.StartIndex + i)) Next Next Log(sb.ToString) Next
OK, thanks.
Not sure I will have use for it other than with this rare case of char 9632, but will have a look into using BBLabel.
RBS
'Selects the text between the two indexes.
Sub SetSelection(edt As EditText, StartIndex As Int, EndIndex As Int)
Dim jo = edt As JavaObject
jo.RunMethod("setSelection", Array As Object(StartIndex, EndIndex))
End Sub
'gets the x and y coordinates of the cursor in an EditText view
Sub GetEditTextXYCursor(edt As EditText) As Int()
Dim joEditText As JavaObject
Dim joLayout As JavaObject
Dim PaddingLeft As Int
Dim PaddingTop As Int
Dim ScrollY As Int
Dim Pos As Int
Dim Line As Int
Dim LineBaseline As Int
Dim xy(2) As Int
joEditText = edt
PaddingLeft = joEditText.RunMethod("getPaddingLeft", Null)
PaddingTop = joEditText.RunMethod("getPaddingTop", Null)
ScrollY = joEditText.RunMethod("getScrollY", Null)
Pos = joEditText.RunMethod("getSelectionStart", Null)
joLayout = joEditText.RunMethod("getLayout", Null)
Line = joLayout.RunMethod("getLineForOffset", Array As Object(Pos)) 'line number
LineBaseline = joLayout.RunMethod("getLineBaseline", Array As Object(Line))
xy(0) = joLayout.RunMethod("getPrimaryHorizontal", Array As Object(Pos)) + PaddingLeft
xy(1) = LineBaseline + PaddingTop - ScrollY 'base line
Return xy
End Sub
Sub GetEditTextLines(edt As EditText, strText As String, oCS As CSBuilder) As String()
Dim i As Int
Dim xy() As Int
Dim iYOld As Int
Dim lstLineStarts As List
If oCS.IsInitialized Then
strText = oCS.ToString
End If
lstLineStarts.Initialize
For i = 0 To strText.Length
SetSelection(edt, i, i)
xy = GetEditTextXYCursor(edt)
If xy(1) > iYOld Then
lstLineStarts.Add(i)
Log("GetEditTextLines, i: " & i)
End If
iYOld = xy(1)
Next
Dim arrLines(lstLineStarts.Size) As String
arrLines(0) = strText.SubString2(0, lstLineStarts.Get(1))
Log(0 & " _ " & arrLines(0))
For i = 1 To lstLineStarts.Size - 1
If i < lstLineStarts.Size - 1 Then
arrLines(i) = strText.SubString2(lstLineStarts.Get(i), lstLineStarts.Get(i + 1))
Else
arrLines(i) = strText.SubString2(lstLineStarts.Get(i), strText.Length)
End If
Log(i & " _ " & arrLines(i))
Next
Return(arrLines)
End Sub
Public Sub MeasureMultilineTextHeightLBL(oParent As Activity, lbl As Label, strText As String, oCSB As CSBuilder) As Int
Dim Left, Top, Right, Bottom As Int
Dim edtDummy As EditText
Dim lstLinePos As List
Dim Ht As Int
Dim jo = lbl As JavaObject
'get padding
Left = jo.RunMethod("getPaddingLeft", Null)
Top = jo.RunMethod("getPaddingTop", Null)
Right = jo.RunMethod("getPaddingRight", Null)
Bottom = jo.RunMethod("getPaddingBottom", Null)
'setup temp edittext, same parameters, but twice the height
edtDummy.Initialize("")
oParent.AddView(edtDummy, 0, lbl.Height * -2dip, lbl.Width, lbl.Height * 2)
edtDummy.TextSize = lbl.TextSize
edtDummy.Typeface = lbl.Typeface
edtDummy.Padding = Array As Int(Left,Top,Right,Bottom)
If oCSB.IsInitialized Then
edtDummy.Text = oCSB
Else
edtDummy.Text = strText
End If
DoEvents 'ignore warning, this is needed
lstLinePos = GetEditTextLinePositions(edtDummy, strText, oCSB)
edtDummy.RemoveView
Ht = lstLinePos.Get(lstLinePos.Size - 1) + Bottom
Return Ht
End Sub
Sub GetEditTextLinePositions(edt As EditText, strText As String, oCS As CSBuilder) As List
Dim i As Int
Dim xy() As Int
Dim iYOld As Int
Dim lstLines As List
If oCS.IsInitialized Then
strText = oCS.ToString
End If
lstLines.Initialize
For i = 0 To strText.Length
SetSelection(edt, i, i)
xy = GetXYCursor(edt)
If i = 0 Then
iYOld = xy(3)
End If
If xy(1) > iYOld Or i = strText.Length Then
lstLines.Add(xy(3))
iYOld = xy(3)
End If
Next
Return(lstLines)
End Sub
'Posted by Klaus'
Sub GetXYCursor(edt As EditText) As Int() 'ignore warning
Dim joEditText As JavaObject
Dim joLayout As JavaObject
Dim PaddingLeft As Int
Dim PaddingTop As Int
Dim Pos As Int
Dim Line As Int
Dim Column As Int 'ignore warning
Dim LineBaseline As Int
Dim LineAscent As Int 'ignore warning
Dim LineDescent As Int 'ignore warning
Dim LineTop As Int
Dim LineBottom As Int
Dim LineCount As Int 'ignore warning
Dim LineStart As Int
Dim ScrollX As Int 'ignore warning
Dim ScrollY As Int
Dim xy(4) As Int
joEditText = edt
PaddingLeft = joEditText.RunMethod("getPaddingLeft", Null)
PaddingTop = joEditText.RunMethod("getPaddingTop", Null)
ScrollX = joEditText.RunMethod("getScrollX", Null)
ScrollY = joEditText.RunMethod("getScrollY", Null)
Pos = joEditText.RunMethod("getSelectionStart", Null)
joLayout = joEditText.RunMethod("getLayout", Null)
Line = joLayout.RunMethod("getLineForOffset", Array As Object(Pos))
LineBaseline = joLayout.RunMethod("getLineBaseline", Array As Object(Line))
LineBottom = joLayout.RunMethod("getLineBottom", Array As Object(Line))
LineTop = joLayout.RunMethod("getLineTop", Array As Object(Line))
LineAscent = joLayout.RunMethod("getLineAscent", Array As Object(Line))
LineDescent = joLayout.RunMethod("getLineDescent", Array As Object(Line))
LineCount = joLayout.RunMethod("getLineCount", Null)
LineStart = joLayout.RunMethod("getLineStart", Array As Object(Line))
Column = Pos - LineStart
xy(0) = joLayout.RunMethod("getPrimaryHorizontal", Array As Object(Pos)) + PaddingLeft
xy(1) = LineBaseline + PaddingTop - ScrollY 'base line
'Log("GetXYCursor, xy(1): " & xy(1))
xy(2) = LineTop + PaddingTop - ScrollY 'top of the line
'Log("GetXYCursor, xy(2): " & xy(2))
xy(3) = LineBottom + PaddingTop - ScrollY 'text bottom line
'Log("GetXYCursor, xy(3): " & xy(3))
Return xy
End Sub
Type EditTextLine(iLineIndex As Int, _
iStartIndex As Int, _
iEndIndex As Int, _
iTop As Int, _
iLeft As Int, _
iRight As Int, _
strText As String)
Sub GetEditTextLines(edt As EditText, strText As String, oCS As CSBuilder) As List
Dim i As Int
Dim xy() As Int
Dim iYOld As Int
Dim iLeft As Int
Dim iLineIndex As Int
Dim lstLines As List
Dim iFirstCharIndex As Int
Dim iLastY As Int
Dim iLastX As Int
If oCS.IsInitialized Then
strText = oCS.ToString
End If
lstLines.Initialize
For i = 0 To strText.Length
SetSelection(edt, i, i)
xy = GetXYCursor(edt)
If i = 0 Then
iLeft = xy(0) 'will stay the same
iYOld = xy(3)
End If
If xy(1) > iYOld Or i = strText.Length Then
Dim tEDTLine As EditTextLine
tEDTLine.iLineIndex = iLineIndex
tEDTLine.iStartIndex = iFirstCharIndex
tEDTLine.iEndIndex = i - 1
tEDTLine.iLeft = iLeft
tEDTLine.iRight = iLastX
tEDTLine.iTop = iLastY
tEDTLine.strText = strText.SubString2(iFirstCharIndex, i)
lstLines.Add(tEDTLine)
iLineIndex = iLineIndex + 1
iFirstCharIndex = i
iYOld = xy(3)
Else
iLastX = xy(0)
iLastY = xy(3)
End If
Next
Return(lstLines)
End Sub