2010-12-07 110 views
34

私は、ダイアログを表示し、ダイアログが閉じられるまで待ってから、ダイアログの内容に応じて結果を返すメソッドを実装したいと思います。これは可能ですか?Android:ダイアログからユーザー入力を待ちますか?

public String getUserInput() 
{ 
    //do something to show dialog 
    String input = //get input from dialog 
    return input; 
} 

私は実際に返される文字列はダイアログを経由して取得しなければならない方法「のパブリック文字列getUserInputを()」、持っているインターフェイスを実装しようとしています。これは簡単にJavaで行われ、アンドロイドで不可能と思われる?

EDIT:バックグラウンドスレッド(私はAsynchTaskからそれを呼び出す)から呼び出されなければなりませんコメント

getInput()に要求されるようにいくつかのサンプルコードを投稿。 getInput()はダイアログを表示し、waitを呼び出します。ダイアログ上で[OK]ボタンを押すと、ダイアログはメンバー変数にユーザー入力を設定し、通知を呼び出します。 notifyが呼び出されると、getInput()が続行され、メンバー変数が返されます。

/** 
* 
*/ 

import android.app.Activity; 
import android.content.Intent; 
import android.os.Bundle; 
import android.view.View; 
import android.view.WindowManager; 
import android.view.View.OnClickListener; 
import android.widget.Button; 
import android.widget.EditText; 

/** 
* @author 
*/ 
public class TextEntryActivity extends Activity { 
    private EditText et; 

    /* 
    * (non-Javadoc) 
    * @see android.app.Activity#onCreate(android.os.Bundle) 
    */ 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     setContentView(R.layout.activity_text_entry); 
     getWindow().setFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND, 
       WindowManager.LayoutParams.FLAG_BLUR_BEHIND); 
     // title 
     try { 
      String s = getIntent().getExtras().getString("title"); 
      if (s.length() > 0) { 
       this.setTitle(s); 
      } 
     } catch (Exception e) { 
     } 
     // value 

     try { 
      et = ((EditText) findViewById(R.id.txtValue)); 
      et.setText(getIntent().getExtras().getString("value")); 
     } catch (Exception e) { 
     } 
     // button 
     ((Button) findViewById(R.id.btnDone)).setOnClickListener(new OnClickListener() { 

      @Override 
      public void onClick(View v) { 
       executeDone(); 
      } 
     }); 
    } 

    /* (non-Javadoc) 
    * @see android.app.Activity#onBackPressed() 
    */ 
    @Override 
    public void onBackPressed() { 
     executeDone(); 
     super.onBackPressed(); 
    } 

    /** 
    * 
    */ 
    private void executeDone() { 
     Intent resultIntent = new Intent(); 
     resultIntent.putExtra("value", TextEntryActivity.this.et.getText().toString()); 
     setResult(Activity.RESULT_OK, resultIntent); 
     finish(); 
    } 


} 

立ち上げを行うだろう。このような

String m_Input; 

public synchronized String getInput() 
{ 
    runOnUiThread(new Runnable() 
    { 
     @Override 
     public void run() 
     { 
      AlertDialog.Builder alert = new AlertDialog.Builder(context); 
      //customize alert dialog to allow desired input 
      alert.setPositiveButton("Ok", new DialogInterface.OnClickListener() { 
      public void onClick(DialogInterface dialog, int whichButton) 
      { 
          m_Input = alert.getCustomInput(); 
          notify(); 
      } 
     }); 
     alert.show(); 
     } 
    }); 

    try 
    { 
     wait(); 
    } 
    catch (InterruptedException e) 
    { 
    } 

    return m_Input; 
} 
+5

UIスレッドで呼び出されるメソッドでユーザーを待つことはできません。したがって、プログラムフローのイベントドリブンモデルに切り替えるか、バックグラウンドメソッドが何を待っていたとしても、ユーザーアクションの更新に応じてUIスレッドでonWhatever()メソッドが呼び出されるまで待つことができるバックグラウンドスレッドから呼び出す必要があります。 –

+0

私は本当に理解していない、バックグラウンドスレッドからこれを呼び出す方法を説明し、次に私の文字列をonWhatever()返しますか? – ab11

+0

3(?)以上のUIスレッドをブロックしている場合は、アプリケーションを終了するかどうかを尋ねるANRダイアログポップアップが表示されるのは3秒だと思います。 AndroidのUIスレッドでブロッキングを実行しないでください。 –

答えて

11

フィードバックをいただきありがとうございます。私はこのスレッドをwait()と一緒に解決することができました。 )。私はこれが与えられたパラダイムの最大のアイデアではないことを認識していますが、私が働いている図書館に適合することが必要でした。

+1

いくつかのコードを投稿できますか? – Caner

+2

いくつかのコードで私の答えを更新しました – ab11

+0

ありがとう! – Caner

1

何かがある:

public void launchPreferedNameEdit() { 
    Intent foo = new Intent(this, TextEntryActivity.class); 
    foo.putExtra("value", objItem.getPreferedNickname()); 
    this.startActivityForResult(foo, EDIT_PREFERED_NAME); 
} 

あなたはこれが可能である

protected void onActivityResult(int requestCode, int resultCode, Intent data) { 
    switch (requestCode) { 
     case EDIT_PREFERED_NAME: 
      try { 
       String value = data.getStringExtra("value"); 
       if (value != null && value.length() > 0) { 

       } 
      } catch (Exception e) { 
      } 
      break; 
     default: 
      break; 
    } 
} 
+0

私は間違っているかもしれませんが、これは私が記述していた問題?問題を明確にするために質問を編集しました。 – ab11

+0

あなたが説明したように、それは不可能です。しかし、私の投稿は、入力テキストを持つアクティビティでこれを行う方法を提供しています。 – Pentium10

27

を使用して結果を得ますか?

いいえAndroidにブロックUIモデルはありません。すべてが非同期です。

UPDATE

質問自体にあなたのコメントのいくつかに応じて、あなたは、バックグラウンドスレッドからUIを表示することはできません。私がこの答えで書いたように、AndroidにはブロックUIモデルはありません。 this sample projectのように、ダイアログが受け入れられたときに実行したいダイアログのボタンハンドラにコードを入れてください。

+0

この回答がダウン投票された特別な理由はありますか? –

+2

誰かが聞きたくない答えかもしれませんか?私はそれが数回起こった。 – blindstuff

+2

バックグラウンドスレッドから直接UIを表示することはできませんが、バックグラウンドスレッドからUIスレッドが表示されるように要求することができます。 –

10

これを行う正しい方法は、イベントドリブンのプログラムモデルです。つまり、「私たちに電話しないで、私たちはあなたに電話します。

単純なコンソールモードのプログラミングでは、コードは値を取得するまで戻らないブロッキング入力関数を呼び出す傾向があります。

多くのGUIプログラミング環境が異なるように動作します。コードは通常は実行されていませんが、潜在的な関心事が発生したときにオペレーティングシステム/ウィンドウマネージャによって呼び出されます。あなたはこれに応答して何かをしてすぐに戻ります。もしそうでなければ、OSはあなたが帰ってくるまであなたに連絡する方法がないので、他の何かに通知することはできません。 (Win32と比較すると、メッセージループがAndroidによって実装されているようになり、メッセージループがイベントで呼び出すコードの残りの部分のみを書くことができます - すぐに返さないと、メッセージループがハングします)

結果として、プログラムフローという概念を再考する必要があります。 To-Doリストを単純な一連のステートメントとして書き出すのではなく、それをお互いに依存する一連のアクションと考えてください。あなたが現在どの状態変数に入っているのかを覚えておいてください。ユーザー入力などのイベントで呼び出された場合、そのイベントが次のステップに進むことができるかどうかを確認し、そうであれば状態変数を更新してからすぐにOSに戻り、次のイベント。イベントが必要なものでなかった場合は、状態を更新せずに戻ります。

このモデルがうまくいかない場合は、ブロッキング入力を使用してコンソールモードアプリケーションのように動作するプログラムロジックのバックグラウンドスレッドを作成します。しかし、あなたの入力関数は実際にはフラグや入力が利用可能であることを通知する何かを待つだけです。その後、Androidがイベントを配信するUIスレッドで、フラグを更新してすぐに返されます。バックグラウンドスレッドは、データが提供されたことを示すためにフラグが変更されたことを確認し、実行を継続します。 (アンドロイド端末エミュレータのようなものは、バックグラウンドコンポーネントが実際には別のプロセス、つまりコンソールモードのLinuxプロセスであり、パイプからのI/Oを潜在的にブロックすることで入力を取得します。画面上に表示するためにstdoutパイプから引き出します)。

0

ケース:プリファレンス変更リスナーイベントの後にデータが処理される準備ができていて、ユーザーから照会されたStringを追加する必要がありました。オプションメニューが開いている間に警告ダイアログをポップすることはできません。だから私は待たなければなりませんでした。私はワークフロー内の次のアクティビティに半分のオブジェクトを投げ込み、onResume()を設定してそのプレースホルダがnullだった場合、そのダイアログをポップしてオブジェクトを終了しました* "ダイアログのボタンハンドラ "*

これは私の最初の投稿であるので、私は上記の正しい答えに投票することはできませんが、これに慣れている誰かを保存したいと思います。ダイアログが場所です。

0

最初に初めてのユーザー入力が必要な場合は、「ユーザー入力が必要」などのマークを付けるように設定することができます。イベントを処理すると、そのフラグをチェックし、設定されている場合は、イベントの唯一のアクションとしてダイアログを起動し、フラグを解除します。次に、ユーザ入力を処理した後のダイアログイベントハンドラから、ダイアログが必要でない場合に通常意図されているコードを呼び出すことができます。

0

私はこれまでに提供されたすべてのソリューションを理解するのに苦労していました。

Iコードをユーザ入力が実行可能でOK'edした後のでように、実行されることになっthatsのラップ:

Runnable rOpenFile = new Runnable() { 
     @Override 
     public void run() { 
      .... code to perform 
     } 
    } 

そして右下のIがユーザに実行可能な関数の名前を渡すことダイアログメソッド。

userInput("Open File", rOpenFile); 

userInputメソッドは、上記のalertDialogビルダーに基づいています。ユーザーの入力がOk'edになると、目的の実行可能ファイルが開始されます。

private void userInput(String sTitle, final Runnable func) { 
    AlertDialog.Builder aBuilder = new AlertDialog.Builder(this); 

    aBuilder.setTitle(sTitle); 
    final EditText input = new EditText(this); 
    input.setInputType(InputType.TYPE_CLASS_TEXT); 
    aBuilder.setView(input); 

    bDialogDone = false; 

    aBuilder.setPositiveButton("Ok", new DialogInterface.OnClickListener() { 
     @Override 
     public void onClick(DialogInterface dialog, int which) { 
      final String sText = input.getText().toString(); 
      sEingabe = sText; 
      func.run(); 
     } 
    }); 
    aBuilder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() { 
     @Override 
     public void onClick(DialogInterface dialog, int which) { 
      dialog.cancel(); 
      sEingabe = ""; 
     } 
    }); 

    aBuilder.show(); 
} 
関連する問題