Reputation: 1148
I have an app with a custom keyboard. To do this, I use a page renderer so I can use an Android layout which makes the keyboard logic a lot easier to handle.
When I do a longish press (.5s) on the keyboard, everything works great. When I do a quick tap on a key (what most people do), the EditText
targeted by the keyboard loses focus, causing the keyboard to hide and the cursor to be removed from the EditText
. I set up a FocusChanged
handler to hide the keyboard when the user clicks elsewhere on the screen. With this error, when I do FindFocus
after a keyboard tap, the focus returns as null
. I showed layout bounds in case of some ghost view receiving the click, but there's nothing there. I don't know what the lifecycle is on a keyboard event, but whatever is causing this issue is called after mKeyboardView.Key
.
Any ideas? Thanks.
class KeyboardPageRenderer : PageRenderer
{
public CustomKeyboardView mKeyboardView;
public EditText mTargetView;
public Android.InputMethodServices.Keyboard mKeyboard;
Activity activity;
global::Android.Views.View view;
protected override void OnElementChanged(ElementChangedEventArgs<Page> e)
{
base.OnElementChanged(e);
if (e.OldElement != null || Element == null)
{
return;
}
try
{
SetupUserInterface();
SetupEventHandlers();
this.AddView(view);
}
catch (System.Exception ex)
{
System.Diagnostics.Debug.WriteLine(@" ERROR: ", ex.Message);
}
}
void SetupUserInterface()
{
activity = this.Context as Activity;
view = activity.LayoutInflater.Inflate(Resource.Layout.Main, this, false);
mKeyboard = new Android.InputMethodServices.Keyboard(Context, Resource.Xml.keyboard);
mTargetView = view.FindViewById<EditText>(Resource.Id.target);
mKeyboardView = view.FindViewById<CustomKeyboardView>(Resource.Id.keyboard_view);
mKeyboardView.Keyboard = mKeyboard;
}
void SetupEventHandlers()
{
mTargetView.Touch += (sender, e) =>
{
ShowKeyboardWithAnimation();
e.Handled = false;
mTargetView.ShowSoftInputOnFocus = false;
};
mTargetView.FocusChange += (sender, e) =>
{
var idk = FindFocus();
if (!mTargetView.IsFocused)
{
mKeyboardView.Visibility = ViewStates.Gone;
}
};
mKeyboardView.Key += (sender, e) =>
{
long eventTime = JavaSystem.CurrentTimeMillis();
KeyEvent ev = new KeyEvent(eventTime, eventTime, KeyEventActions.Down, e.PrimaryCode, 0, 0, 0, 0, KeyEventFlags.SoftKeyboard | KeyEventFlags.KeepTouchMode);
DispatchKeyEvent(ev);
};
}
public void ShowKeyboardWithAnimation()
{
if (mKeyboardView.Visibility == ViewStates.Gone)
{
mKeyboardView.Visibility = ViewStates.Visible;
Android.Views.Animations.Animation animation = AnimationUtils.LoadAnimation(
Context,
Resource.Animation.slide_up_bottom
);
mKeyboardView.ShowWithAnimation(animation);
}
}
protected override void OnLayout (bool changed, int l, int t, int r, int b)
{
base.OnLayout (changed, l, t, r, b);
var msw = MeasureSpec.MakeMeasureSpec (r - l, MeasureSpecMode.Exactly);
var msh = MeasureSpec.MakeMeasureSpec (b - t, MeasureSpecMode.Exactly);
view.Measure (msw, msh);
view.Layout (0, 0, r - l, b - t);
}
}
EDIT:
Whole project can be found here. iOS project is working pretty well if anyone is looking to implement that as well.
Upvotes: 2
Views: 478
Reputation: 9084
Delete the EditText.FocusChange
method and modify your CustomKeyboardView.Key
method like this :
mKeyboardView.Key += (sender, e) =>
{
long eventTime = JavaSystem.CurrentTimeMillis();
KeyEvent ev = new KeyEvent(eventTime, eventTime, KeyEventActions.Down, e.PrimaryCode, 0, 0, 0, 0, KeyEventFlags.SoftKeyboard | KeyEventFlags.KeepTouchMode);
//Make your editText get Focus
mTargetView.RequestFocus();
DispatchKeyEvent(ev);
};
Here is my workaround :
mKeyboardView.Key += async (sender, e) =>
{
long eventTime = JavaSystem.CurrentTimeMillis();
KeyEvent ev = new KeyEvent(eventTime, eventTime, KeyEventActions.Down, e.PrimaryCode, 0, 0, 0, 0, KeyEventFlags.SoftKeyboard | KeyEventFlags.KeepTouchMode);
DispatchKeyEvent(ev);
await Task.Delay(1);
//mTargetView.RequestFocus();
};
Then, the cursor will always be visible.
Upvotes: 1