Android Question Hiding keyboard before opening overflow menu

RB Smissaert

Well-Known Member
Licensed User
Using the AppCompat library (3.52) and this is the text of the manifest file (in case that is relevant):

B4X:
AddManifestText(
<uses-sdk android:minSdkVersion="7" android:targetSdkVersion="26"/>
android:normalScreens="true" 
android:smallScreens="true" 
android:anyDensity="true"/>)
SetApplicationAttribute(android:icon, "@drawable/icon")
SetApplicationAttribute(android:label, "$LABEL$")
SetApplicationAttribute(android:supportsRtl, "true")
'SetApplicationAttribute(android:largeHeap, "true")

'AddPermission(android.permission.USE_FINGERPRINT)
'End of default text.

'SetApplicationAttribute(android:hardwareAccelerated, "false")

'End of default text.
SetApplicationAttribute(android:theme, "@style/MyAppTheme")
'CreateResourceFromFile(Macro, Themes.LightTheme)

SetActivityAttribute(Main, android:windowSoftInputMode, adjustResize)
'SetActivityAttribute(Main, android:windowSoftInputMode, adjustPan)

CreateResource(values, themes.xml,
<resources>
<dimen name="action_button_padding">0dp</dimen>
    <style name="MyAppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <item name="colorPrimary">#FF9800</item>
        <item name="colorPrimaryDark">#F57C00</item>
        <item name="colorAccent">#FFA726</item>
        <item name="windowNoTitle">true</item>
        <item name="windowActionBar">false</item>
  <item name="windowActionModeOverlay">true</item>
  <item name="android:actionButtonStyle">@style/ActionButton</item>
  <item name="android:listPreferredItemHeightSmall">30dp</item>
    </style>
 <style name="ActionButton" parent="@android:style/Widget.ActionButton">
    <item name="android:paddingStart">0dp</item>
       <item name="android:paddingEnd">2dp</item>
       <item name="android:minWidth">2dp</item>
    <item name="android:drawablePadding">@dimen/action_button_padding</item>
   </style>
</resources>
)
In Main, Globals I have this:

B4X:
Private ActionBar As ACToolBarLight
The menu is created like this:

B4X:
#IgnoreWarnings: 11
Sub Activity_CreateMenu(Menu As ACMenu)
 
 Dim i As Int
 Dim item As ACMenuItem
 

 Menu.Clear
 
 'initialize with default value (not in menu group)
 '-------------------------------------------------
 For i = 0 To 21
  arrMenuIconsInfo(i, 0) = -1
 Next

 'Menu group 1
 For i = eMenuButtonType.FindPatient To eMenuButtonType.Map   '0 to 7
  item = Menu.AddWithGroup2(1, i, i, arrMenuIconFilesTitles(i, 2), arrMenuIcons(i, 0))
  item.ShowAsAction = item.SHOW_AS_ACTION_ALWAYS
  arrMenuIconsInfo(i, 0) = 1
  arrMenuItems(i) = item
 Next
 
 'Menu group 2
 For i = eMenuButtonType.Appointments To eMenuButtonType.Phone_Patient   '8 to 14
  item = Menu.AddWithGroup2(2, i, i, arrMenuIconFilesTitles(i, 2), arrMenuIcons(i, 0))
  item.ShowAsAction = item.SHOW_AS_ACTION_ALWAYS
  arrMenuIconsInfo(i, 0) = 2
  arrMenuItems(i) = item
 Next
 
 'Menu group 3
 For i = eMenuButtonType.SQL To eMenuButtonType.Show_All_Run_SQL   '15 to 21
  item = Menu.AddWithGroup2(3, i, i, arrMenuIconFilesTitles(i, 2), arrMenuIcons(i, 0))
  item.ShowAsAction = item.SHOW_AS_ACTION_ALWAYS
  arrMenuIconsInfo(i, 0) = 3
  arrMenuItems(i) = item
 Next
 
 ActionBar.Menu.SetGroupVisible(2, False)
 ActionBar.Menu.SetGroupVisible(3, False)
 ActionBar.Menu.SetGroupVisible(1, True)
 iCurrentMenuGroup = 1
 
 'overflow menu (3 dots)
 '----------------------
 For i = eMenuButtonType.Export2CSV To eMenuButtonType.Dev_Test '21 to 45
  AddOverflowMenuItem(Menu, i)
 Next
 

End Sub

Sub AddOverflowMenuItem(Menu As ACMenu, iIDX As Int)
 
 Dim item As ACMenuItem
 
 item = Menu.Add(iIDX, iIDX, arrMenuIconFilesTitles(iIDX, 2), Null)
 arrMenuItems(iIDX) = item
 
End Sub
Now if the keyboard is showing and the user clicks the overflow menu icon (3 vertical dots) then
the overflow menu won't show fully, so I need to hide the keyboard before the menu is opened.

I tried this, but although that will hide the keyboard the overflow menu is still not showing fully:

B4X:
#If Java
public boolean _onCreateOptionsMenu(android.view.Menu menu) {
  if (processBA.subExists("activity_createmenu")) {
  processBA.raiseEvent2(null, true, "activity_createmenu", false, new de.amberhome.objects.appcompat.ACMenuWrapper(menu));
  return true;
  }
  else
  return false;
}
  @Override
  public boolean onMenuOpened(int featureId, android.view.Menu menu) {
     if (menu != null) {
       processBA.raiseEvent(null, "activity_menuopen");
     }
  return super.onMenuOpened(featureId, menu);
  }
#End If

Sub Activity_MenuOpen
 ime.HideKeyboard
End Sub
So, how can I hide the keyboard before the overflow menu opens?


RBS
 

RB Smissaert

Well-Known Member
Licensed User
Using the AppCompat library (3.52) and this is the text of the manifest file (in case that is relevant):

B4X:
AddManifestText(
<uses-sdk android:minSdkVersion="7" android:targetSdkVersion="26"/>
android:normalScreens="true"
android:smallScreens="true"
android:anyDensity="true"/>)
SetApplicationAttribute(android:icon, "@drawable/icon")
SetApplicationAttribute(android:label, "$LABEL$")
SetApplicationAttribute(android:supportsRtl, "true")
'SetApplicationAttribute(android:largeHeap, "true")

'AddPermission(android.permission.USE_FINGERPRINT)
'End of default text.

'SetApplicationAttribute(android:hardwareAccelerated, "false")

'End of default text.
SetApplicationAttribute(android:theme, "@style/MyAppTheme")
'CreateResourceFromFile(Macro, Themes.LightTheme)

SetActivityAttribute(Main, android:windowSoftInputMode, adjustResize)
'SetActivityAttribute(Main, android:windowSoftInputMode, adjustPan)

CreateResource(values, themes.xml,
<resources>
<dimen name="action_button_padding">0dp</dimen>
    <style name="MyAppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <item name="colorPrimary">#FF9800</item>
        <item name="colorPrimaryDark">#F57C00</item>
        <item name="colorAccent">#FFA726</item>
        <item name="windowNoTitle">true</item>
        <item name="windowActionBar">false</item>
  <item name="windowActionModeOverlay">true</item>
  <item name="android:actionButtonStyle">@style/ActionButton</item>
  <item name="android:listPreferredItemHeightSmall">30dp</item>
    </style>
 <style name="ActionButton" parent="@android:style/Widget.ActionButton">
    <item name="android:paddingStart">0dp</item>
       <item name="android:paddingEnd">2dp</item>
       <item name="android:minWidth">2dp</item>
    <item name="android:drawablePadding">@dimen/action_button_padding</item>
   </style>
</resources>
)
In Main, Globals I have this:

B4X:
Private ActionBar As ACToolBarLight
The menu is created like this:

B4X:
#IgnoreWarnings: 11
Sub Activity_CreateMenu(Menu As ACMenu)
 
 Dim i As Int
 Dim item As ACMenuItem
 

 Menu.Clear
 
 'initialize with default value (not in menu group)
 '-------------------------------------------------
 For i = 0 To 21
  arrMenuIconsInfo(i, 0) = -1
 Next

 'Menu group 1
 For i = eMenuButtonType.FindPatient To eMenuButtonType.Map   '0 to 7
  item = Menu.AddWithGroup2(1, i, i, arrMenuIconFilesTitles(i, 2), arrMenuIcons(i, 0))
  item.ShowAsAction = item.SHOW_AS_ACTION_ALWAYS
  arrMenuIconsInfo(i, 0) = 1
  arrMenuItems(i) = item
 Next
 
 'Menu group 2
 For i = eMenuButtonType.Appointments To eMenuButtonType.Phone_Patient   '8 to 14
  item = Menu.AddWithGroup2(2, i, i, arrMenuIconFilesTitles(i, 2), arrMenuIcons(i, 0))
  item.ShowAsAction = item.SHOW_AS_ACTION_ALWAYS
  arrMenuIconsInfo(i, 0) = 2
  arrMenuItems(i) = item
 Next
 
 'Menu group 3
 For i = eMenuButtonType.SQL To eMenuButtonType.Show_All_Run_SQL   '15 to 21
  item = Menu.AddWithGroup2(3, i, i, arrMenuIconFilesTitles(i, 2), arrMenuIcons(i, 0))
  item.ShowAsAction = item.SHOW_AS_ACTION_ALWAYS
  arrMenuIconsInfo(i, 0) = 3
  arrMenuItems(i) = item
 Next
 
 ActionBar.Menu.SetGroupVisible(2, False)
 ActionBar.Menu.SetGroupVisible(3, False)
 ActionBar.Menu.SetGroupVisible(1, True)
 iCurrentMenuGroup = 1
 
 'overflow menu (3 dots)
 '----------------------
 For i = eMenuButtonType.Export2CSV To eMenuButtonType.Dev_Test '21 to 45
  AddOverflowMenuItem(Menu, i)
 Next
 

End Sub

Sub AddOverflowMenuItem(Menu As ACMenu, iIDX As Int)
 
 Dim item As ACMenuItem
 
 item = Menu.Add(iIDX, iIDX, arrMenuIconFilesTitles(iIDX, 2), Null)
 arrMenuItems(iIDX) = item
 
End Sub
Now if the keyboard is showing and the user clicks the overflow menu icon (3 vertical dots) then
the overflow menu won't show fully, so I need to hide the keyboard before the menu is opened.

I tried this, but although that will hide the keyboard the overflow menu is still not showing fully:

B4X:
#If Java
public boolean _onCreateOptionsMenu(android.view.Menu menu) {
  if (processBA.subExists("activity_createmenu")) {
  processBA.raiseEvent2(null, true, "activity_createmenu", false, new de.amberhome.objects.appcompat.ACMenuWrapper(menu));
  return true;
  }
  else
  return false;
}
  @Override
  public boolean onMenuOpened(int featureId, android.view.Menu menu) {
     if (menu != null) {
       processBA.raiseEvent(null, "activity_menuopen");
     }
  return super.onMenuOpened(featureId, menu);
  }
#End If

Sub Activity_MenuOpen
 ime.HideKeyboard
End Sub
So, how can I hide the keyboard before the overflow menu opens?


RBS
This works, but is not nice at all.

B4X:
Sub Activity_MenuOpen
 If bKeyboardVisible Then 'set in IME_HeightChanged and HideKeyboard
  Sleep(100)
  CloseOverflowMenu
  Sleep(100)
  HideKeyboard
  Sleep(100)
  ShowOverflowMenu
 End If
End Sub

Sub HideKeyboard()
 ime.HideKeyboard
 bKeyboardVisible = False
End Sub

Sub ShowOverflowMenu
 Dim jo As JavaObject = ActionBar
 jo.RunMethod("showOverflowMenu", Null)
End Sub

Sub CloseOverflowMenu
 ActionBar.Menu.Close
End Sub
I can't make it work without the long Sleep intervals.

RBS
 

RB Smissaert

Well-Known Member
Licensed User
This works, but is not nice at all.

B4X:
Sub Activity_MenuOpen
 If bKeyboardVisible Then 'set in IME_HeightChanged and HideKeyboard
  Sleep(100)
  CloseOverflowMenu
  Sleep(100)
  HideKeyboard
  Sleep(100)
  ShowOverflowMenu
 End If
End Sub

Sub HideKeyboard()
 ime.HideKeyboard
 bKeyboardVisible = False
End Sub

Sub ShowOverflowMenu
 Dim jo As JavaObject = ActionBar
 jo.RunMethod("showOverflowMenu", Null)
End Sub

Sub CloseOverflowMenu
 ActionBar.Menu.Close
End Sub
I can't make it work without the long Sleep intervals.

RBS
Even with the Sleep(100) intervals it is not 100% reliable.
Is there no event raised by just clicking the ActionBar overflow icon?
This would make matters much easier as I can then hide the keyboard
before the overflow menu is opened.

RBS
 

RB Smissaert

Well-Known Member
Licensed User
You can add custom views to the action bar. You can use it to replace the standard menu with your own menu and with your own button. This will allow you to hide the keyboard and only then show a menu.
Thanks.
I had a feeling this might be the answer, but was hoping there was some simpler solution.
Will look at adding a custom overflow icon.

RBS
 

RB Smissaert

Well-Known Member
Licensed User
You can add custom views to the action bar. You can use it to replace the standard menu with your own menu and with your own button. This will allow you to hide the keyboard and only then show a menu.
Just to clarify: Are you saying/suggesting I keep my Activity.CreateMenu Sub the same, cover the overflow menu with a panel, add a button to this panel with say a FontAwesome overflow icon, then from that button call HideKeyboard first and then call Activity.OpenMenu?
This sounds the simplest to me. Not sure it is possible to replace the standard overflow icon with my own button.

RBS
 

RB Smissaert

Well-Known Member
Licensed User
No. I suggest that you don't use the built-in menu. Add a custom view to the action bar and show an ACPopupMenu or a different menu.
OK.
I thought I wasn't using the built-in menu as I was using AppCompat and doing this:

B4X:
Sub Activity_CreateMenu(Menu As ACMenu)
My understanding of menu's is basic.

RBS
 

RB Smissaert

Well-Known Member
Licensed User
No. I suggest that you don't use the built-in menu. Add a custom view to the action bar and show an ACPopupMenu or a different menu.
I thought that not using the built-in menu anymore would be quite a bit of work (but something to do maybe later), so solved this now with a simple transparent overlay panel over the Action bar, hiding the built-in overflow menu:

B4X:
Sub ReplaceOverFlow
 
 Dim cvs As B4XCanvas
 
 pnlOverFlow.Initialize("pnlOverFlow")
 pnlOverFlow.Width = 220dip
 pnlOverFlow.Height = 48dip
 pnlOverFlow.Color = Colors.ARGB(0, 100, 100, 100)
 
 btnOverFlow.Initialize("btnOverFlow")
 btnOverFlow.Width = 44dip
 btnOverFlow.Height = 48dip
 btnOverFlow.Color = Colors.ARGB(255, 255, 255, 32) 'colour of the ActionBar
 btnOverFlow.Gravity = Gravity.LEFT
 btnOverFlow.Typeface = Typeface.FONTAWESOME
 btnOverFlow.TextSize = 24
 btnOverFlow.Text = Chr(61762)
 
 pnlOverFlow.AddView(btnOverFlow, 144dip, 0dip, 44dip, 48dip)
 
 ActionBar.AddView(pnlOverFlow, 220dip, 48dip, Gravity.CENTER_HORIZONTAL)
 
 'to avoid a very faint line at the left of the btnOverFlow
 cvs.Initialize(btnOverFlow)
 cvs.DrawLine(0, 0, 0, btnOverFlow.Height, Colors.RGB(255, 255, 32), 1dip)
 cvs.Invalidate
 
End Sub

Sub btnOverFlow_Click
 If bKeyboardVisible Then
  HideKeyboard
 End If
 Sleep(140) 'is still needed
 Activity.OpenMenu
End Sub
All working perfectly fine sofar.


RBS
 
Top