読者です 読者をやめる 読者になる 読者になる
スポンサーリンク

Android SDK の動かないコード(中級編) ダイアログにsetTitleしないと,ダイアログのサイズが最小になってしまう

Android 動かないコード


以下のAndroidアプリのコードが意図した動作をしないのは,なぜですか。(制限時間1分)

やりたい事:

  • 幅が300dpのダイアログを表示する。
  • ダイアログ内の横幅いっぱいに,テキストボックスやボタンを表示する。

アクティビティ側のコード:

// カスタムレイアウトでダイアログを表示
ViewGroup dialog_root = (ViewGroup)findViewById(R.id.layout_dialog_root);
View layout_dialog = getLayoutInflater()
    .inflate(R.layout.my_dialog, dialog_root);

new AlertDialog.Builder(this)
	.setView(layout_dialog) // カスタムレイアウトをセット
.show();


my_dialog.xml(カスタムダイアログのレイアウト定義XML):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:id="@+id/layout_dialog_root"
              android:orientation="vertical"
              android:layout_width="300dp"
              android:layout_height="200dp"
              android:background="@color/white"
              >
    
    <!-- テキスト入力 -->
    <EditText
        android:id="@+id/edit1"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
    ></EditText>

    <!-- ボタン -->
    <Button
          android:layout_width="fill_parent"
          android:layout_height="wrap_content"
          android:textSize="20dp"
          android:layout_marginTop="15dp"
          android:id="@+id/btn1"
          android:text="@string/hello"
    />

</LinearLayout>

発生する問題と解決策

これだと,300dpに満たない,非常に小さなダイアログが表示されてしまう。

ダイアログのレイアウトの layout_widthなどの設定が無視されている。

ダイアログのサイズがおかしい。最小化されたような感じ。



もしダイアログに setTitle() でタイトルを表示すれば,

ダイアログのレイアウトの layout_width に従い,指定した通りの大きさで

ダイアログが表示される。

new AlertDialog.Builder(this)
	.setTitle("タイトル") // この行を追加
	.setView(layout_dialog)
.show();

補足:ダイアログのモーダルネス

Tosatは表示中に画面の田の部分を操作可能だが,

Dialogを表示すると,画面の他の部分は操作を受け付けなくなる。

そういう意味では,AlertDialogはある意味モーダルダイアログであるといえる。


しかし,

「ダイアログの裏側の画面を動かしているスレッドを完全に停止させる」

という意味での,完全な「モーダルダイアログ」のAPIは存在しない。

ModalなDialogの使用方法
https://groups.google.com/group/andro...

  • WinAPIのMessageBoxのように、ユーザーがボタンをクリックするまで次の行の命令を待っているようなAPIはありませんでしょうか?
  • ダイアログを閉じないと次の行の命令を実行しない、といった機能はAndroidには用意されていない


「完全なモーダルダイアログ」を実装するためのサンプルコード(全て,マルチスレッドプログラミングの知識が必要):

モーダルダイアログが欲しい (その2)
http://d.hatena.ne.jp/Kazzz/20100727/p1

  • モーダルダイアログと近似した振る舞いのダイアログとするのはよいが、Androidの場合UIスレッドを止めるのは御法度なので、本来の意味のモーダルは実現できない。なのでAsyncTask等を使用して他のスレッドを使用している場合を想定し、そのスレッドの処理をブロックするスレッドモーダル(造語)を実現する
  • スレッド間のオブジェクトとして CountDownLatch signal を定義し,ダイアログのonDismissイベントが呼ばれるまでの間は,元スレッドは await() によって停止し続ける,という仕組み
    • http://java.sun.com/j2se/1.5.0/ja/docs/ja/api/java/util/concurrent/CountDownLatch.html
      • CountDownLatch は、指定された「カウント」を使用して初期化されます。await メソッドは、countDown() メソッド呼び出しの結果として、現在のカウントがゼロに達するまでブロックします。その後、待機中のスレッドがすべて解放され、後続の await の呼び出しがすべて返されます。


Android モーダルダイアログの実現
http://kobadroid.web.fc2.com/androidm...

  • Androidにはモーダルダイアログがないので、ウィザード的なフローを作るときに困ります。ここではスレッドを使ってモーダルダイアログを実現する方法を紹介
  • androidのデフォルトのイベントループlooper()とは別に、自前のイベントループを作ってしまう
  • 基本的なマルチスレッドプログラミングの理解が必要