Android Dialog

 

setyournumber

 

想通过点击通讯录图标,选择用户并返回相应联系人号码到这个AlertDialog的EditText中显示,发现EditText中的号码不会更新。相应的EditText已经setText了新的号码,但是UI没有任何变化。重新打开Dialog才会更新这个Edittext。

1、想通过EditText.invalidate()重绘,发现不起作用。

2、通过showDialog(id);

重载protected void onPrepareDialog ( int id, Dialog dialog )更新对话框内容,可以实现,对于我的程序过于繁琐。

3、最后我选择,点击通讯录图标cancel掉alertDialog,在通过onActivityResult得到了联系人号码后重新打开一个alertDialog。

 

注意:一直以为调用dialog后,Activity部分被遮盖,所以Activity会调用OnPause(),今天发现其实Activity调用Dialog后不会调用OnPause(),显然这种情况下只有一个Activity,dialog不是Activity,调用OnPause条件是一个Activity部分遮盖另一个Activity。详细可以查看Activity生命周期。

 

Dialogs 对话框

Dialog Design 对话框设计

dialogDesign

分三部分,标题区域、内容区域、动作区域

其中动作区域一般是OK或者Cancel,OK在右侧,Cancel在左侧。如果还要用更多按钮,按钮上的文本最好选择动词。

 

dialogDesign2

Alerts Dialog

先询问用户是否确认,之后再继续运行程序。

alertsDialog1

alertsDialog2

有标题和没有标题的AlertDialog

注意对话框标题的描述方式:

alertsDialog3

 

Popups 

pop1

 

最常用的Toast也算Dialog中的一种

toast

Dialog类是所有Dialog的基类,使用的时候应该避免实例化Dialog,最好用如下的几个子类

AlertDialog类:

显示的对话框,可以设置title标题,最多3个按钮,可以包含一个可选择的列表,也可以用户自定义一个layout

DatePickerDialog or TimePickerDialog

拥有预先定义的UI,可以用来选择日期或者时间

ProgressDialog

Android提供ProgressDialog,但是避免使用这个ProgressDialog,如果需要进行进度的显示,在Layout中使用ProgressBar。

以上的这些类已经为你提供了类型和基本的结构,但是你应该使用DialoguFragment为你的Dialog做一个容器(Container)

DialogFrame可以让你在创建对话框时拥有控制权,并且可以定义它的外观,而不用调用Dialog对象的方法。

使用DialogFrame类管理dialog可以确保它正确处理生命周期的事件,例如当用户按了返回按钮,或者旋转了屏幕。DialogFrame类还也允许你重用dialog的UI,作为一个更大的UI的内嵌组件,就像Fragment。(在大小屏幕内显示不同的UI)

 

Creating a Dialog Fragment

 

public class FireMissilesDialogFragment extends DialogFragment {
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        // Use the Builder class for convenient dialog construction
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        builder.setMessage(R.string.dialog_fire_missiles)
               .setPositiveButton(R.string.fire, new DialogInterface.OnClickListener() {
                   public void onClick(DialogInterface dialog, int id) {
                       // FIRE ZE MISSILES!
                   }
               })
               .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
                   public void onClick(DialogInterface dialog, int id) {
                       // User cancelled the dialog
                   }
               });
        // Create the AlertDialog object and return it
        return builder.create();
    }
}

创建一个FireMissilesDialogFragment类的实例之后,调用show()就可以出现如下的对话框

firemissles

Building an Alert Dialog

AlertDialog允许你进行不同的设计,经常是你唯一需要的对话框,包含三个部分,标题title,内容区域content area,动作按钮Action Button

建立 AlertDialog分三步:


//1. Instantiate an AlertDialog.Builder with its constructor

AlertDialog.Builder builder = <strong>new</strong> AlertDialog.Builder(getActivity());

//2. Chain together various setter methods to set the dialog characteristics

builder.setMessage(R.string.dialog_message)

.setTitle(R.string.dialog_title);

//3. Get the AlertDialog from create()

AlertDialog dialog = builder.create();

Adding buttons

给ALerDialog增加按钮


AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
//Add the buttons
builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int id) {
            // User clicked OK button
        }
    });
builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int id) {
            // User cancelled the dialog
        }
    });
//Set other dialog properties
...

//Create the AlertDialog
AlertDialog dialog = builder.create();

共有三种不同类型的按钮

Positive,像是OK

Positive ,像是Cancel

Neutral,既不是ok也不想cancel,可以用于“稍后提醒我”这类选择

 

 

Adding a list


@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
    builder.setTitle(R.string.pick_color)
           .setItems(R.array.colors_array, new DialogInterface.OnClickListener() {
               public void onClick(DialogInterface dialog, int which) {
               // The 'which' argument contains the index position
               // of the selected item
           }
    });
    return builder.create();
}

pickacolor

点击单选

 

Adding a persistent multiple-choice or single-choice list

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    mSelectedItems = new ArrayList();  // Where we track the selected items
    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
    // Set the dialog title
    builder.setTitle(R.string.pick_toppings)
    // Specify the list array, the items to be selected by default (null for none),
    // and the listener through which to receive callbacks when items are selected
           .setMultiChoiceItems(R.array.toppings, null,
                      new DialogInterface.OnMultiChoiceClickListener() {
               @Override
               public void onClick(DialogInterface dialog, int which,
                       boolean isChecked) {
                   if (isChecked) {
                       // If the user checked the item, add it to the selected items
                       mSelectedItems.add(which);
                   } else if (mSelectedItems.contains(which)) {
                       // Else, if the item is already in the array, remove it
                       mSelectedItems.remove(Integer.valueOf(which));
                   }
               }
           })
    // Set the action buttons
           .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
               @Override
               public void onClick(DialogInterface dialog, int id) {
                   // User clicked OK, so save the mSelectedItems results somewhere
                   // or return them to the component that opened the dialog
                   ...
               }
           })
           .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
               @Override
               public void onClick(DialogInterface dialog, int id) {
                   ...
               }
           });

    return builder.create();
}

Creating a Custom Layout 建立一个自定义的Layout

res/layout/dialog_signin.xml

 


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
    android:src="@drawable/header_logo"
    android:layout_width="match_parent"
    android:layout_height="64dp"
    android:scaleType="center"
    android:background="#FFFFBB33"
    android:contentDescription="@string/app_name" />
<EditText
    android:id="@+id/username"
    android:inputType="textEmailAddress"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="16dp"
    android:layout_marginLeft="4dp"
    android:layout_marginRight="4dp"
    android:layout_marginBottom="4dp"
    android:hint="@string/username" />
<EditText
    android:id="@+id/password"
    android:inputType="textPassword"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="4dp"
    android:layout_marginLeft="4dp"
    android:layout_marginRight="4dp"
    android:layout_marginBottom="16dp"
    android:fontFamily="sans-serif"
    android:hint="@string/password"/>
</LinearLayout>

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
    // Get the layout inflater
    LayoutInflater inflater = getActivity().getLayoutInflater();

    // Inflate and set the layout for the dialog
    // Pass null as the parent view because its going in the dialog layout
    builder.setView(inflater.inflate(R.layout.dialog_signin, null))
    // Add action buttons
           .setPositiveButton(R.string.signin, new DialogInterface.OnClickListener() {
               @Override
               public void onClick(DialogInterface dialog, int id) {
                   // sign in the user ...
               }
           })
           .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
               public void onClick(DialogInterface dialog, int id) {
                   LoginDialogFragment.this.getDialog().cancel();
               }
           });
    return builder.create();
}

Tip:如果你想要一个自定义的对话框,可以用一个Activity代替Dialog,简单创建一个Activity并在Manifest中设置它的主题为Theme.Holo.Dialog

<activity android:theme=”@android:style/Theme.Holo.Dialog” >

 

Activity的showDialog()这个函数在API13弃用了。使用最新DialogFragment类替代,通过android的兼容包可以在旧平台使用。

一个DialogFragment实现的Alert Dialog:

 

 


public static class MyAlertDialogFragment extends DialogFragment {

    public static MyAlertDialogFragment newInstance(int title) {
        MyAlertDialogFragment frag = new MyAlertDialogFragment();
        Bundle args = new Bundle();
        args.putInt("title", title);
        frag.setArguments(args);
        return frag;
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        int title = getArguments().getInt("title");

        return new AlertDialog.Builder(getActivity())
                .setIcon(R.drawable.alert_dialog_icon)
                .setTitle(title)
                .setPositiveButton(R.string.alert_dialog_ok,
                    new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int whichButton) {
                            ((FragmentAlertDialog)getActivity()).doPositiveClick();
                        }
                    }
                )
                .setNegativeButton(R.string.alert_dialog_cancel,
                    new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int whichButton) {
                            ((FragmentAlertDialog)getActivity()).doNegativeClick();
                        }
                    }
                )
                .create();
    }
}

activity创建这个fragment,用这些方法显示出dialog,获取数据结果。


void showDialog() {
    DialogFragment newFragment = MyAlertDialogFragment.newInstance(
            R.string.alert_dialog_two_buttons_title);
    newFragment.show(getFragmentManager(), "dialog");
}

public void doPositiveClick() {
    // Do stuff here.
    Log.i("FragmentAlertDialog", "Positive click!");
}

public void doNegativeClick() {
    // Do stuff here.
    Log.i("FragmentAlertDialog", "Negative click!");
}

下面是对showDialog(…)的使用说明  转载

在 Android 开发中时常会遇到这样的问题:在删除列表中记录项时弹出确认对话框,对话框的提示消息取决于用户选中的项。例如:Are you sure you want to delete XXX。XXX由用户选中的记录项确定。

通常可以在 Activity 的 onCreateDialog 创建托管对话框(免去对话框状态管理的问题)。在调用 showDialog 的时候,如果该对话框还没有创建,则先调用 onCreateDialog 创建该对话框。随后 onPreparedDialog 被调用。因此,可以在 onPreparedDialog 中更新对话框的内容。

 

如果 AlertDialog 是在 Activity 的 onCreateDialog 中通过 AlertDialog.Builder 创建的,并且想在 onPreparedDialog 中改变其状态(比如:setTitle, setMessage),你必须先在 onCreateDialog 中调用 AlertDialog.Builder 的方法设置其初始值,否则在 onPreparedDialog 中的方法调用无效。下面通过代码说明此问题

main.xml

 

	<?xml version="1.0" encoding="utf-8"?>
	<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	    android:orientation="vertical"
	    android:layout_width="fill_parent"
	    android:layout_height="fill_parent">
	    <Button android:id="@+id/btn_show_1"
	        android:layout_width="wrap_content"
	        android:layout_height="wrap_content"
	        android:text="show dialog 1" />
	    <Button android:id="@+id/btn_show_2"
	        android:layout_width="wrap_content"
	        android:layout_height="wrap_content"
	        android:text="show dialog 2" />
	</LinearLayout>  

在界面里放置了两个 Button ,分别用于显示 AlertDialog 。

 


public class Main extends Activity {
    private static final int TIME_ALERT_DIALOG_1 = 1;
    private static final int TIME_ALERT_DIALOG_2 = 2;  

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);  

	        Button button1 = (Button) findViewById(R.id.btn_show_1);  

	        Button button2 = (Button) findViewById(R.id.btn_show_2);  

	        button1.setOnClickListener(new OnClickListener() {  

	            public void onClick(View v) {
	                // TODO Auto-generated method stub
	                showDialog(TIME_ALERT_DIALOG_1);
	            }
	        });  

	        button2.setOnClickListener(new OnClickListener() {  

	            public void onClick(View v) {
	                // TODO Auto-generated method stub
	                showDialog(TIME_ALERT_DIALOG_2);
	            }
	        });
	    }  

	    @Override
	    protected Dialog onCreateDialog(int id) {
	        switch (id) {
	        case TIME_ALERT_DIALOG_1:
	            AlertDialog.Builder timeDialog1 = new AlertDialog.Builder(this);
	            timeDialog1.setTitle("Alert 1: have not called setMessage in onCreateDialog");  

	            return timeDialog1.create();
	        case TIME_ALERT_DIALOG_2:
	            AlertDialog.Builder timeDialog2 = new AlertDialog.Builder(this);
	            timeDialog2.setTitle("Alert 2: have called setMessage in onCreateDialog");
	            timeDialog2.setMessage("");
	            return timeDialog2.create();
	        default:
	            break;
	        }
	        return super.onCreateDialog(id);
	    }  

	    @Override
	    protected void onPrepareDialog(int id, Dialog dialog) {
	        switch (id) {
	        case TIME_ALERT_DIALOG_1:  

	            AlertDialog timeDialog1 = (AlertDialog) dialog;
	            timeDialog1.setMessage(DateFormat.format("h:mm:ss", System
	                    .currentTimeMillis()));
	            break;
	        case TIME_ALERT_DIALOG_2:  

	            AlertDialog timeDialog2 = (AlertDialog) dialog;
	            timeDialog2.setMessage(DateFormat.format("h:mm:ss", System
	                    .currentTimeMillis()));
	            break;
	        default:
	            break;
	        }
	        super.onPrepareDialog(id, dialog);
	    }  

这两个 AlertDialog 的区别在于 AlertDialog1 在创建的时候没有设置 Message。结果是尽管 AlertDialog1 在 onPreparedDialog 中设置了 Message, 但是 AlertDialog1 根本不会显示 Message 部分。

showdialog1

showdialog2

showdialog3

showdialog4

 

显示对话框

对话框经常作为Activity的一部分来创建和显示。你通常应该从protected Dialog Activity.onCreateDialog (int id) 回调方法里创建对话框。当你使用这个回调函数时,Android系统会有效的设置这个Activity为每个对话框的所有者,从而自动管理每个对话框的状态并挂靠到Activity上。这样,每个对话框继承这个Activity的特定属性。比如,当一个对话框打开时,菜单键显示为这个Activity定义的选项菜单,音量键修改Activity使用的音频流。

当你想要显示一个对话框时,调用showDialog(int id) 方法并传递一个唯一标识这个对话框的整数。

当对话框第一次被请求时,Android从你的Activity中调用onCreateDialog(int id),你应该在这里初始化这个对话框Dialog。这个回调方法被传以和showDialog(int id)相同的ID。当你创建这个对话框后,在Activity的最后返回这个对象。

在对话框被显示之前,Android还调用了可选的回调函数onPrepareDialog(int id, Dialog). 如果你想在每一次对话框被打开时改变它的任何属性,你可以定义这个方法。这个方法在每次打开对话框时被调用,而onCreateDialog(int) 仅在对话框第一次打开时被调用。如果你不定义onPrepareDialog(),那么这个对话框将保持和上次打开时一样。这个方法也被传递以对话框的ID,和在onCreateDialog()中创建的对话框对象。

定义onCreateDialog(int) 和 onPrepareDialog(int, Dialog) 回调函数的最佳方法是使用一个switch 语句来检查传递进来的id 参数。每个case 应该检查一个唯一的对话框ID然后创建和定义相应的对话框。比如,想象一下一个游戏使用两个不同的对话框:一个用来指示这个游戏已经暂停而另一个来指示游戏结束。首先,为每个对话框定义一个常量:

1.static final int DIALOG_PAUSED_ID = 0;

2.static final int DIALOG_GAMEOVER_ID = 1;

然后,为每一个ID用一个switch case定义这个onCreateDialog(int) 回调函数:

 


protected Dialog onCreateDialog(int id) {
    Dialog dialog;
    switch(id) {
    case DIALOG_PAUSED_ID:
        // do the work to define the pause Dialog
        break;
    case DIALOG_GAMEOVER_ID:
        // do the work to define the game over Dialog
        break;
    default:
        dialog = null;
    }
    return dialog;
} 

当是时候显示其中之一的对话框时,使用对话框ID调用showDialog(int):

1.showDialog(DIALOG_PAUSED_ID);

 

 

Tagged on:

发表评论

电子邮件地址不会被公开。 必填项已用*标注

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>