0

ここでは、動作するものとしないものを示すプロジェクトです。コードも以下にあります。私は、これのための明確な解決策を示す多くのstackoverflowの投稿が見つかりましたが、私はバックグラウンドスレッドで実行しない限り、私のために何らかの理由で動作しません。バックグラウンドスレッドで実行しない限り、フォースショーキーボードは機能しません

私はAlertDialogとEditTextを作成しています。私の目標は、警告ダイアログを表示し、キーボードを表示し、編集テキストにカーソルを置くことです。何らかの理由で、私はRequestFocusとShowSoftInputだけではできません。バックグラウンドスレッドを作成してから呼び出しを行うと機能します...なぜですか?私は何か間違っているのですか?

enter image description hereenter image description here

ここで私は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); 
    } 

答えて

1

this.ForceShowKeyboard(editText);に直接電話すると、キーボードが表示されないのはなぜですか?

あなたはダイアログを表示するとき、それはハンドラにSHOWメッセージを送信した後、UIスレッドがダイアログを表示するようになる、ダイアログソースコードhereを見つけることができます。

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の知識を入手してください。

関連する問題