Android Question How to keep xCustomListview-Item focused after .ResizeItem?

fredo

Well-Known Member
Licensed User
Longtime User
CustomListView is a versatile view that covers the basic requirements for lists with many variants.

Even the dynamic height adjustment of the items is possible, but then the focus of the item is lost.

B4X:
Sub Activity_Create(FirstTime As Boolean)
    
    Activity.LoadLayout("1")

    CustomListView1.Add( CreateListItemFlEditText("testtext 1. Some longer Text aaa bbb ccc ddd eee fff ggg hhh iii jjj kkk lll mmmmmmm nn oooo ppppp qqqqqqq.", "hinttext1", CustomListView1.AsView.Width, 20dip), -111)
    CustomListView1.Add( CreateListItemFlEditText("testtext 2. A little longer than the text before.", "hinttext2", CustomListView1.AsView.Width, 20dip), -222)
    CustomListView1.Add( CreateListItemFlEditText("testtext 3. Short.", "hinttext3", CustomListView1.AsView.Width, 20dip), -333)
    CustomListView1.Add( CreateListItemFlEditText("testtext 4. This Text is longer to force another height of the edittext.", "hinttext4", CustomListView1.AsView.Width, 20dip), -444)

    bolReadyForInput = True
    
End Sub


Sub CreateListItemFlEditText(Text As String, Text2 As String, Width As Int, Height As Int) As Panel
   Dim p As Panel
   p.Initialize("")
   p.SetLayout(0, 0, Width, Height)
   '
   p.LoadLayout("editfloatmic")
   lblEdtFloatMic.TextColor = Starter.intColorAccent
   '
   Dim intH As Int = Starter.su.MeasureMultilineTextHeight(lblEdtFloatMeasureInvis, Text) +48dip
   Dim intHPan As Int = intH + 8dip
   panEdtFloatMic.Height = intH
   '
   edtFloatMic.Height = intH
   edtFloatMic.Text = Text
   edtFloatMic.EditText.HintColor = Starter.colorBlack38
   edtFloatMic.EditText.TextColor = Starter.colorBlack87
   edtFloatMic.Hint = Text2
   edtFloatMic.EditText.SingleLine = False
   edtFloatMic.EditText.Gravity = Bit.Or(Gravity.TOP, Gravity.LEFT)
   '
   p.SetLayout(0, 0, Width, intHPan)
   '
   lblEdtFloatMic.Text = ""
   Return p
End Sub

Sub edtFloatMic_TextChanged (Old As String, New As String)
    If Not(bolReadyForInput) Then Return
    
    Dim index As Int = CustomListView1.GetItemFromView(Sender)
    Dim b4xpnl As B4XView = CustomListView1.GetPanel(index)
    Dim b4xedtText As B4XView = b4xpnl.GetView(0)
    
    Dim b4xlblEdtFloatMeasureInvis As B4XView = b4xpnl.GetView(0)
    Dim intH As Int = Starter.su.MeasureMultilineTextHeight(b4xlblEdtFloatMeasureInvis, New) +48dip
    
    If intH = b4xedtText.Height Then Return
    
    
    ' --- --- --- --- --- --- --- --- --- ---
    ' New height is needed
    ' --- --- --- --- --- --- --- --- --- ---
    Dim intHPan As Int = intH +8dip
    b4xedtText.Height = intH
    '
    Dim panEdtFrame As B4XView= b4xpnl.GetView(1)
    panEdtFrame.Height = intH
        
    CustomListView1.ResizeItem(index, intHPan)

    'CustomListView1.JumpToItem(index )
    
    'b4xedtText.RequestFocus
    'b4xedtText. ( ...somehow set cursor to end of text ... )
    
    
End Sub

In the attached small testproject every clv item contains a layout with an edittext on it.

The aim is to enlarge the edittext and its parent-panel while the user enters more words. This is realized and works as usual via "MeasureMultilineTextHeight".

The problem is that the current clv-item loses focus as soon as the function".ResizeItem" is called.

Example: As you can see here, a word is inserted at position (1) and the height is readjusted.
Afterwards, however, the focus changes to the top item at position (2).​





JumpToItem was tried out, but led to an optical jumping back and forth, which is not conducive to a positive user experience.

Does anyone have a solution how to execute a "ResizeItem" on the xCustomListview, so that the focus remains on the active EditText (including cursor position)?
 

Attachments

  • clvtest.zip
    11.7 KB · Views: 315

udg

Expert
Licensed User
Longtime User
Since you know the index of the panel you're working on, you can use JumpToItem or ScrollToItem to go back to it once the text is updated.
I read you tried with unsatisfactory results JumpToItem. Could it be that it needed a few milliseconds more to complete any inner actions? Did you try to a sleep(100) or similar before calling it?
 
Upvote 0

fredo

Well-Known Member
Licensed User
Longtime User
Yep. That was it.
I will consider Sleep a lot more often before asking questions (oh, and the sleep(100) is fantastic too ...)

B4X:
Sub edtFloatMic_TextChanged (Old As String, New As String) As ResumableSub
    If Not(bolReadyForInput) Then Return Null
    
    Dim index As Int = CustomListView1.GetItemFromView(Sender)
    Dim b4xpnl As B4XView = CustomListView1.GetPanel(index)
    Dim b4xpnl2 As B4XView = b4xpnl.GetView(1)
    Dim b4xedtText As B4XView = b4xpnl2.GetView(0)
    
    Dim b4xlblEdtFloatMeasureInvis As B4XView = b4xpnl.GetView(0)
    Dim intH As Int = Starter.su.MeasureMultilineTextHeight(b4xlblEdtFloatMeasureInvis, New) +48dip
    
    If intH = b4xedtText.Height Then Return Null
    
    Log(" ")
    Log($"edtFloatMic_TextChanged, index=${index}, new.Length=${New.Length}"$)

    ' --- --- --- --- --- --- --- --- --- ---
    ' New height is needed
    ' --- --- --- --- --- --- --- --- --- ---
    Dim intHPan As Int = intH +8dip
    b4xedtText.Height = intH
    '
    Dim panEdtFrame As B4XView= b4xpnl.GetView(1)
    panEdtFrame.Height = intH

    Log($"  edtFloatMic_TextChanged, x110, .ResizeItem(${index}, ${intHPan}) "$)
    CustomListView1.ResizeItem(index, intHPan)
    Sleep(100)
    
    Log($"  edtFloatMic_TextChanged, x114, .JumpToItem(${index})"$)
    CustomListView1.JumpToItem(index)
    'Sleep(100)
    
    Log($"  edtFloatMic_TextChanged, x118, b4xedtText.RequestFocus"$)
    b4xedtText.RequestFocus
    'Sleep(100)
    
    Return Null
End Sub

Sub edtFloatMic_FocusChanged (HasFocus As Boolean)
    Dim index As Int = CustomListView1.GetItemFromView(Sender)
    Log(" ")
    Log($"edtFloatMic_FocusChanged, HasFocus=${HasFocus}, index=${index}"$)
End Sub




The log while tapping on the keyboard word suggestions:
B4X:
edtFloatMic_FocusChanged, HasFocus=true, index=5
 
edtFloatMic_TextChanged, index=5, new.Length=59
  edtFloatMic_TextChanged, x110, .ResizeItem(5, 263)
 
edtFloatMic_FocusChanged, HasFocus=false, index=5
 
edtFloatMic_FocusChanged, HasFocus=true, index=0
  edtFloatMic_TextChanged, x114, .JumpToItem(5)
  edtFloatMic_TextChanged, x118, b4xedtText.RequestFocus
 
edtFloatMic_FocusChanged, HasFocus=false, index=0
 
edtFloatMic_FocusChanged, HasFocus=true, index=5
 
edtFloatMic_TextChanged, index=5, new.Length=96
  edtFloatMic_TextChanged, x110, .ResizeItem(5, 317)
 
edtFloatMic_FocusChanged, HasFocus=false, index=5
 
edtFloatMic_FocusChanged, HasFocus=true, index=6
  edtFloatMic_TextChanged, x114, .JumpToItem(5)
  edtFloatMic_TextChanged, x118, b4xedtText.RequestFocus
 
edtFloatMic_FocusChanged, HasFocus=false, index=6
 
edtFloatMic_FocusChanged, HasFocus=true, index=5
 
edtFloatMic_TextChanged, index=5, new.Length=137
  edtFloatMic_TextChanged, x110, .ResizeItem(5, 371)
 
edtFloatMic_FocusChanged, HasFocus=false, index=5
 
edtFloatMic_FocusChanged, HasFocus=true, index=6
  edtFloatMic_TextChanged, x114, .JumpToItem(5)
  edtFloatMic_TextChanged, x118, b4xedtText.RequestFocus
 
edtFloatMic_FocusChanged, HasFocus=false, index=6
 
edtFloatMic_FocusChanged, HasFocus=true, index=5
 

Attachments

  • clvtestworking.zip
    11.7 KB · Views: 318
Upvote 0

MrKim

Well-Known Member
Licensed User
Longtime User
I have found an additional issue with .ResizeItem.
I have additional views and ResizeItem actually causes the focus to jump to another View! This means not only
B4X:
customlistview.JumpToItem
but also
B4X:
customlistview.requestfocus
Also, JumpToItem moves the view to the top of the customlistview - not a good look to have the view move when you are editing it.

I solved the problem by resizing myself.
B4X:
Sub SetEditTextHeight(Obj As View)  'ignore
    Dim TxtHt As Int  , Pnl As Panel, i As Int', SS As NotePoperties
    Try
        TxtHt = CTxt.Height
        CTxt.Height = Max(60dip, 30dip + su.MeasureMultilineTextHeight(CTxt, CTxt.Text))
            If TxtHt <> CTxt.Height Then
                Pnl = CTxt.Parent
                Pnl.Height = CTxt.Height
                Pnl.Invalidate
                Pnl = Pnl.Parent
                Pnl.Height = CTxt.Height
                Dim p2 As Panel
                TxtHt = CTxt.Height - TxtHt
                For i = Pnl.Tag + 1 To ActiveList.Size - 1
                    p2 = ActiveList.GetPanel(i).Parent
                    p2.top = p2.top + TxtHt
                    p2.Tag = i + 1
                Next
            p2 = Pnl.Parent
            p2.Height = p2.Height + TxtHt
        End If
    Catch
        Resizing = False
        ToastMessageShow("SetEditTextHeight" & CRLF & LastException.Message, True)
    End Try
   
End Sub
I am converting an app (as recommended from the customlistview class to the lib.
 
Upvote 0
Cookies are required to use this site. You must accept them to continue using the site. Learn more…