这里的项目展示了哪些有效,哪些无效。代码也在下面。我发现很多stackoverflow帖子显示了明确的解决方案,但由于某种原因,除非我在后台线程中运行,否则这对我没有用。
我正在创建一个AlertDialog和一个EditText。我的目标是显示警告对话框,显示键盘,并在编辑文本中显示光标。出于某种原因,我不能只是RequestFocus和ShowSoftInput。它只适用于我创建后台线程,然后拨打电话......为什么?难道我做错了什么?
这是我在后台线程中运行代码时应用程序的样子截图,而不是...
链接到Xamarin Android项目: https://drive.google.com/open?id=0B5x7JEZ8aQihVnM4am8yRWlQYkU
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
// Get our button from the layout resource,
// and attach an event to it
Button button = FindViewById<Button>(Resource.Id.myButton);
button.Click += delegate { button.Text = string.Format("{0} clicks!", count++); };
AlertDialog.Builder alertBuilder = new AlertDialog.Builder(this);
AlertDialog alertDialog = null;
TextView titleTV = new TextView(this);
titleTV.Text = "title";
titleTV.TextSize = 18f;
titleTV.SetTextColor(Android.Graphics.Color.Green);
titleTV.SetBackgroundColor(Android.Graphics.Color.White);
titleTV.SetPadding(0, 12, 0, 12);
titleTV.Gravity = GravityFlags.CenterHorizontal | GravityFlags.CenterVertical;
alertBuilder.SetCustomTitle(titleTV);
EditText editText = new EditText(this);
editText.SetHeight(600);
editText.Text = "super coooool dude";
editText.TextSize = 14f;
editText.SetPadding(18, 12, 18, 12);
editText.Gravity = GravityFlags.Left | GravityFlags.Top;
editText.ShowSoftInputOnFocus = true;
editText.RequestFocus();
alertBuilder.SetView(editText);
alertBuilder.SetPositiveButton("Done", (sender, e) => { });
alertBuilder.SetNegativeButton("Cancel", (sender, e) => { });
alertDialog = alertBuilder.Create();
alertDialog.Show();
// STACKOVERFLOW LOOK HERE.
//// Calling ForceShowKeyboard does not work here..... Why?
//this.ForceShowKeyboard(editText);
// But, calling ForceShowKeyboard works when in a background thread, sleeping a bit, then run on main thread again
Thread t = new Thread(() => this.DoThreadSTuff(editText));
t.IsBackground = true;
t.Start();
}
private void DoThreadSTuff(EditText editText)
{
// I dont think a sleep is needed, but i found a similar issue in Xamarin.iOS once upon a time, and a sleep was needed. It seems Xamarin.Android doesn't require a sleep though.
//Thread.Sleep(2);
RunOnUiThread(() =>
{
this.ForceShowKeyboard(editText);
});
}
private void ForceShowKeyboard(EditText editText)
{
editText.RequestFocus();
InputMethodManager imm = (InputMethodManager)this.GetSystemService(Android.Content.Context.InputMethodService);
imm.ShowSoftInput(editText, ShowFlags.Implicit);
}
答案 0 :(得分:1)
为什么直接拨打
this.ForceShowKeyboard(editText);
时键盘无法显示。
您可以找到对话框源代码here,当您显示对话框时,它会向处理程序发送SHOW
消息,然后让UI线程显示对话框。
public void show() {
......
sendShowMessage();
}
private void sendShowMessage() {
if (mShowMessage != null) {
// Obtain a new message so this dialog can be re-used
Message.obtain(mShowMessage).sendToTarget();
}
}
.....
mShowMessage = mListenersHandler.obtainMessage(SHOW, listener);
private static final class ListenersHandler extends Handler {
......
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
......
case SHOW:
((OnShowListener) msg.obj).onShow(mDialog.get());
break;
}
}
}
所以Dialog.Show()
是异步方法。
这意味着在对话显示之前将调用this.ForceShowKeyboard(editText);
。所以你看不到键盘。
为什么在后台线程中运行代码时会显示键盘。
您在另一个主题中调用RunOnUIThread()
。 RunOnUIThread
的委托将被发布到UI线程的事件队列中。这意味着它将在您创建对话框时运行。所以你可以看到键盘。
通过检查RunOnUIThread()
的源代码,它也是一个处理程序。
public final void runOnUiThread(Runnable action) {
if (Thread.currentThread() != mUiThread) {
mHandler.post(action);
} else {
action.run();
}
}
换句话说,当你创建对话框时,它会向UI线程处理程序发送一条消息,处理程序将使EditText
成为焦点。
了解Android Handler,它将帮助您理解。