ScrollViews and EditText - Preventing auto-focus

Jim Brown

Active Member
Licensed User
Longtime User
*EDIT - Issue solved. See my post - HERE

If you use EditText's in ScrollViews there is a tendency for the edit texts to automatically gain focus as they come into view. Is there a way to prevent this?

I want to detect when the 'user' clicks into an edit text rather than when the system activates it

The situation I have is, if there is a edit text in a low position on screen and a user clicks it, the soft keyboard will appear over the top of the edit text hiding it. his is because no scrolling or jumping occurs automatically (because of the edit text being inside a scroll view)

To get around this I thought of using existing EditText FocusChanged (HasFocus As Boolean) sub and scrolling the view to the focused edit text
The problem is, the scroll view jumps around due to the auto-focusing taking place (as explained above)

What I think I need then, is an event to trigger when the user manually taps the edit text. However, such event would need to fire 'before' the soft keyboard is invoked

Any work-around ideas? If need be I will post an example later
Thanks
 
Last edited:

Jim Brown

Active Member
Licensed User
Longtime User
Thanks for the idea nfordbscndrd. That custom keyboard is one option to consider. Nice

Alas though, I can't seem the solve the issue at hand. Here is an example of what happens. If you run the code below and slowly scroll the display Android auto-focuses each EditText as it becomes the main one in view

What I want to do though, is detect an actual "user" activation. Then I can act on that and re-position the scroll view

As it is, the scroll view will jump around because the EditText_FocusChanged sub is automatically getting triggered. At this point I can't tell whether Android or the user activated the EditText


B4X:
' ScrollView and EditText -- Autofocus issue
Sub Process_Globals
End Sub

Sub Globals
   Dim sv As ScrollView
   Dim ed1,ed2 As EditText
End Sub

Sub Activity_Create(FirstTime As Boolean)
   sv.Initialize(180%y)
   ed1.Initialize("EditText") : ed2.Initialize("EditText")
   Activity.AddView(sv,0,0,100%x,100%y)
   sv.Panel.AddView(ed1,10%x,50%y,40%x,8%y)
   sv.Panel.AddView(ed2,10%x,120%y,40%x,8%y)
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

' Here, I only want to re-position scroll view when
' the "user" clicks into an edit text
'
' Right now though, Android auto-focus's the EditText
' when it comes into view
Sub EditText_FocusChanged (HasFocus As Boolean)
   If HasFocus=True Then 
      'Dim p As Phone : p.HideKeyboard(Activity)
      Dim ed As EditText : ed=Sender
      Dim yp  As Int : yp=ed.Top-40%y
      If yp<0 Then yp=0
      DoEvents : sv.ScrollPosition=yp
   End If
End Sub
 
Upvote 0

nfordbscndrd

Well-Known Member
Licensed User
Longtime User
Try adding the following:

Sub Global
...
Dim Timer1 As Timer
End Sub

Sub Activity_Create
...
Timer1.Initialize("Timer1", 50)
Timer1.Enabled =
False
End sub

Sub EditText_FocusChanged
If HasFocus-True Then
...
Timer1.Enabled = True
end if
end sub

Sub Timer1_Tick
Dim p As Phone
p.HideKeyboard(Activity)
timer1.Enabled =
False
end sub
 
Upvote 0

pmckirahan

New Member
Licensed User
Longtime User
Autofocus Edittexts in a scroll view...

Has anyone figured out how to implement the Linear Layout solution? I have and app that we have written that contains many text fields in a scrollview. Scrolling is clumsy when the text fields keep getting autofocus.
 
Upvote 0

Jim Brown

Active Member
Licensed User
Longtime User
UPDATE: I have found a solution to the "EditText's in ScrollViews" issue whereby the soft keyboard can obscure the edit text. This happens because no adjustPan takes place automatically.

So, the solution is to use IME_HeightChanged() sub as a trigger to 'scroll' the ScrollView up


B4X:
' ScrollView and EditTexts -- Autofocus issue

' Solution to keyboard overlaying EditText views
' Use IME keyboard hanlder - IME_HeightChanged sub
Sub Process_Globals
End Sub

Sub Globals
   Dim sv As ScrollView
   Dim ed1, ed2, ed3 As EditText
   Dim IME_Handler As IME
   Dim LastFocusedEditText As EditText
End Sub

Sub Activity_Create(FirstTime As Boolean)
   sv.Initialize(220%y)
   sv.Color=Colors.Red
   Activity.AddView(sv,0,0,100%x,100%y)
   ed1.Initialize("EditText") : ed1.Text="Edit One"
   ed2.Initialize("EditText") : ed2.Text="Edit Two"
   ed3.Initialize("EditText") : ed3.Text="Edit Three"
   sv.Panel.AddView(ed1,10%x,50%y,48%x,12%y)
   sv.Panel.AddView(ed2,20%x,90%y,48%x,20%y)
   sv.Panel.AddView(ed3,30%x,140%y,48%x,8%y)
   ' Initialize the IME keyboard handler
   ' Want to handle height changes so we can monitor when
   ' soft keyboard pops up
   IME_Handler.Initialize("IME")
   IME_Handler.AddHeightChangedEvent
End Sub

Sub Activity_Resume
End Sub

Sub Activity_Pause (UserClosed As Boolean)
End Sub

' When EditText's exist in a ScrollView the FocusChanged sub is called 
' by Android in an automated fashion, or when the user clicks the EditText
' Let's grab the last focused EditText
Sub EditText_FocusChanged (HasFocus As Boolean)
   If HasFocus=True Then LastFocusedEditText=Sender
End Sub

' When the soft keyboard pops up check to see if the last focused EditText is undermneath it.
Sub IME_HeightChanged(NewHeight As Int, OldHeight As Int)
   ' Act only when keyboard is opened
    If NewHeight<OldHeight Then
      If LastFocusedEditText.IsInitialized=True Then
         Dim svOffs As Int : svOffs=NewHeight-LastFocusedEditText.Height-30dip
         Dim etScreenYPos As Int : etScreenYPos=LastFocusedEditText.Top-sv.ScrollPosition
         If etScreenYPos>svOffs Then
            sv.ScrollPosition=sv.ScrollPosition+etScreenYPos-svOffs
         End If
      End If
   End If
End Sub
 
Upvote 0

Andris

Active Member
Licensed User
Longtime User
UPDATE: I have found a solution to the "EditText's in ScrollViews" issue whereby the soft keyboard can obscure the edit text. This happens because no adjustPan takes place automatically.

So, the solution is to use IME_HeightChanged() sub as a trigger to 'scroll' the ScrollView up


B4X:
' ScrollView and EditTexts -- Autofocus issue

' Solution to keyboard overlaying EditText views
' Use IME keyboard hanlder - IME_HeightChanged sub
Sub Process_Globals
End Sub

Sub Globals
   Dim sv As ScrollView
   Dim ed1, ed2, ed3 As EditText
   Dim IME_Handler As IME
   Dim LastFocusedEditText As EditText
End Sub

Sub Activity_Create(FirstTime As Boolean)
   sv.Initialize(220%y)
   sv.Color=Colors.Red
   Activity.AddView(sv,0,0,100%x,100%y)
   ed1.Initialize("EditText") : ed1.Text="Edit One"
   ed2.Initialize("EditText") : ed2.Text="Edit Two"
   ed3.Initialize("EditText") : ed3.Text="Edit Three"
   sv.Panel.AddView(ed1,10%x,50%y,48%x,12%y)
   sv.Panel.AddView(ed2,20%x,90%y,48%x,20%y)
   sv.Panel.AddView(ed3,30%x,140%y,48%x,8%y)
   ' Initialize the IME keyboard handler
   ' Want to handle height changes so we can monitor when
   ' soft keyboard pops up
   IME_Handler.Initialize("IME")
   IME_Handler.AddHeightChangedEvent
End Sub

Sub Activity_Resume
End Sub

Sub Activity_Pause (UserClosed As Boolean)
End Sub

' When EditText's exist in a ScrollView the FocusChanged sub is called
' by Android in an automated fashion, or when the user clicks the EditText
' Let's grab the last focused EditText
Sub EditText_FocusChanged (HasFocus As Boolean)
   If HasFocus=True Then LastFocusedEditText=Sender
End Sub

' When the soft keyboard pops up check to see if the last focused EditText is undermneath it.
Sub IME_HeightChanged(NewHeight As Int, OldHeight As Int)
   ' Act only when keyboard is opened
    If NewHeight<OldHeight Then
      If LastFocusedEditText.IsInitialized=True Then
         Dim svOffs As Int : svOffs=NewHeight-LastFocusedEditText.Height-30dip
         Dim etScreenYPos As Int : etScreenYPos=LastFocusedEditText.Top-sv.ScrollPosition
         If etScreenYPos>svOffs Then
            sv.ScrollPosition=sv.ScrollPosition+etScreenYPos-svOffs
         End If
      End If
   End If
End Sub

Nice solution Jim! The only negative is that it requires that the ScrollView inside panel height has to be set longer than otherwise necessary if the obstructed EditText is close to the bottom of the panel, thus creating empty space at the end of the panel, in order to enable it to scroll up. I'll live with that though!
 
Upvote 0
Top