I'm currently working on a Xamarin.Android application where I'm trying to modify the device keyboard's default behavior.
Desired Functionality:
- When editing a non-empty text field, the keyboard should work normally.
- If the field is empty and the user presses the delete key, the keyboard should automatically close (simulating a back button press).
- This modification should be implemented without requiring code changes across the entire application.
Current Implementation:
private EditText currentEditText;
private string lastContent = "";
public override void OnWindowFocusChanged(bool hasFocus)
{
try
{
base.OnWindowFocusChanged(hasFocus);
SetupKeyboardDetection();
if (hasFocus)
{
HideNavigationBar();
}
else
{
HideNavigationBarPeekView();
}
}
catch { }
}
private void SetupKeyboardDetection()
{
var rootView = Window.DecorView.RootView;
rootView.ViewTreeObserver.GlobalLayout += (sender, args) =>
{
var r = new Rect();
rootView.GetWindowVisibleDisplayFrame(r);
var screenHeight = rootView.Height;
var keyboardHeight = screenHeight - r.Bottom;
if (keyboardHeight > screenHeight * 0.15)
{
if (!GlobalValues.IsKeyboardOpen)
{
GlobalValues.IsKeyboardOpen = true;
HandleFocusChange();
}
}
else
{
if (GlobalValues.IsKeyboardOpen)
{
GlobalValues.IsKeyboardOpen = false;
if (currentEditText != null)
{
currentEditText.TextChanged -= OnEditTextChanged;
currentEditText.KeyPress -= OnEditTextKeyPress;
currentEditText = null;
}
}
}
};
}
private void HandleFocusChange()
{
var focusedView = CurrentFocus;
if (focusedView is EditText focusedEditText)
{
if (currentEditText != null)
{
currentEditText.TextChanged -= OnEditTextChanged;
currentEditText.KeyPress -= OnEditTextKeyPress;
}
currentEditText = focusedEditText;
lastContent = currentEditText.Text;
currentEditText.TextChanged += OnEditTextChanged;
currentEditText.KeyPress += OnEditTextKeyPress;
ShowKeyboard();
}
}
private void OnEditTextChanged(object sender, Android.Text.TextChangedEventArgs e)
{
if (currentEditText != null)
{
string newContent = currentEditText.Text;
if (newContent != lastContent)
{
lastContent = newContent;
}
}
}
private void OnEditTextKeyPress(object sender, View.KeyEventArgs e)
{
if (e.Event.Action == KeyEventActions.Down)
{
if (e.KeyCode == Keycode.Del)
{
var editText = sender as EditText;
if (editText != null && string.IsNullOrEmpty(editText.Text))
{
e.Handled = true;
HideKeyboard();
}
}
else if (e.KeyCode == Keycode.Enter)
{
e.Handled = true;
FocusNextElement();
}
}
}
private void FocusNextElement()
{
View current = CurrentFocus;
if (current != null)
{
View next = current.FocusSearch(FocusSearchDirection.Forward);
if (next != null && (next is EditText || next.IsShown))
{
next.RequestFocus();
}
else
{
HideKeyboard();
}
}
}
Current Implementation Issues:
Password Fields:
- The delete key functionality doesn't work at all on EditText fields
with inputType="password".
Enter Key Behavior:
- Pressing Enter moves focus to the next field (as intended), but unexpectedly hides the keyboard.
Field Switching Issues:
- When switching between fields without dismissing the keyboard, the new field doesn't properly recognize input events.
Final Field Submission:
- When pressing Enter on the last field, the keyboard no longer closes automatically.
Additional Context:
The behavior is working correctly on standard EditText fields.
I'm looking for a solution that maintains consistency across all input types (including passwords) while preserving the native keyboard experience.
Would anyone have suggestions to resolve these edge cases? I’d be happy to share my current code snippets if helpful.