黑马程序员android 对话框

 ------- <a href="http://www.itheima.com" target="blank">android培训</a>、<a href="http://www.itheima.com" target="blank">java培训</a>、期待与您交流! ----------

对话框

对话框是一个提示用户做出决定或输入其它信息的小窗口。同时对话框不会填满屏幕。

对话框

如果想要设计包括语言建议在内的对话,请阅读对话框设计指南信息。

dialogs.png

Dialog类是创建对话框的基类。但是,您通常不应该直接实例化一个对话框。相反,你应该使用下面的子类中的一个:

AlertDialog(弹出对话框)

对话框可以显示一个标题和最多三个按钮,还包括可选的项目列表以及自定义布局。

DatePickerDialog(日期选择对话框)及TimePickerDialog(时间选择对话框)

允许用户选择一个日期或者时间的对话框。

这些类定义对话框的风格和结构,但你要使用DialogFragment作为对话框的容器。DialogFragment类提供了创建对话框并管理其外观需要的所有控件,而不用再调用Dialog的方法。

使用DialogFragment管理对话框可以确保它正确处理生命周期事件,比如用户按下返回按钮或旋转屏幕等。DialogFragment类还允许对话框的用户界面就像传统片段那样,作为一个更大的用户界面内的可嵌入组件重新使用。

本指南中的以下各节介绍如何将DialogFragment与AlertDialog对象进行组合。如果你想创建日期或时间选择器,应该改为阅读选择器指南。

注意:由于DialogFragment类最初添加了Android3.0(API级别11),该文件描述了如何使用该公司所提供支持库的DialogFragment类。把该库添加到应用,你可以使用DialogFragment并运行Android1.6或更高版本设备的各种API。如果应用程序支持的最低版本是API级别11或更高,那么你可以使用DialogFragment的框架版本,但要注意本文件中的链接都是支持API库的。当使用支持库时,请确保您导入的是android.support.v4.app.DialogFragment类,而不是android.app.DialogFragment。

创建对话片段

你可以进行包括自定义布局和对话框设计指南在内的各种对话框设计,其中对话框设计指南可以通过扩展DialogFragment并创建在onCreateDialog()回调方法中的AlertDialog获得。

例如,下方提供了一个在DialogFragment中管理的基本AlertDialog:

 
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();
    }
}
 

现在,当你创建这个类以及show()该对象的实例时,出现的对话框如图1。

下一节将介绍更多使用AlertDialog.Builder API来创建对话框的信息。

基于对话复杂程度,可以实现DialogFragment中包括所有基本片段生命周期方法在内的其他回调方法。

构建警告对话框

该AlertDialog类允许你建立各种对话框的设计和往往是你唯一需要的对话框类。如图2中,警告对话框有三个区域:

  1. 标题。此为可选项。应该仅当内容区域被详细信息、列表或者自定义布局占据时使用。如果需要陈述简单的消息或问题(例如图1对话框),则不需要标题。
  2. 内容区域。可以显示消息,列表或者其他自定义布局。
  3. 动作按钮。一个对话框的操作按钮不能超过3个。
dialogs_regions.png

AlertDialog.Builder类提供了API,可以使用包括自定义布局在内的内容来创建AlertDialog。 要建立 AlertDialog:

 
// 1. Instantiate an AlertDialog.Builder with its constructor
AlertDialog.Builder builder = new 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();
 

下列主题显示如何使用AlertDialog.Builder定义各种对话框属性。

添加按钮

为了添加图2所示按钮,调用setPositiveButton() and setNegativeButton()方法:

 
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();
 

set...Button()方法需要按钮标题(由字符串资源提供)和DialogInterface.OnClickListener(当按下按钮时进行相应操作)。

可以添加下列三种不同的操作按钮:

  • 肯定

使用此按钮来接受并继续进行操作( "OK"操作)。

  • 否定

使用此按钮来取消操作。

  • 中立

当用户不希望继续操作时使用此按钮,但并不一定取消操作。例如操作可能显示“稍后提醒”。

AlertDialog只能添加各类型按钮各一个。也就是说不能添加两个肯定按钮。

添加列表

AlertDialog API有三种类型可用列表:

  • 传统单选项列表
  • 永久单选项列表(单选按钮)
  • 永久多选项列表(复选框)
dialog_list.png

要创建图3所示单选项列表,请使用setItems() 方法:

 
@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();
}
 

因为列表在对话框内容区域显示,对话框不能同时显示消息和列表,你应该为setTitle()对话框设置一个标题。要指定列表项目,可以调用setItems()来传递数组。或者可以使用setAdapter()指定列表。这样可以使用 ListAdapter返回动态数据列表。

如果用 ListAdapter返回列表,则要使用Loader以便内容加载异步。

添加持久多选或单选列表

要添加多项选择(复选框)或者单项选择(单选按钮)列表,分别使用setMultiChoiceItems()或者setSingleChoiceItems()方式。

dialog_checkboxes.png

例如这里显示了如何创建图4所示保存 ArrayList所选项目的多选列表:

 
@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();
}
 

尽管传统列表和单选列表都提供了“单选”操作,如果要坚持用户的选择您可以使用setSingleChoiceItems()。如果再次打开对话框,就应该指示用户当前选择,然后创建单选按钮列表。

创建自定义布局

如果想要对话框自定义布局,可以创建一个布局并调用 AlertDialog.Builder对象的setView()添加到 AlertDialog。

默认情况下自定义布局填充对话框窗口,但是仍可以使用AlertDialog.Builder方法来添加按钮和标题。

dialog_custom.png

例如下面是图5对话框的布局文件: 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>
 

为了扩展DialogFragment布局,使用getLayoutInflater()来获得LayoutInflater同时调用inflate( )(第一个参数是布局资源ID,第二个参数是布局父类视图)。然后调用setView()来进行对话框布局。

 
@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();
}
 

提示:如果想要自定义对话框,就用活动来作为对话框,而不是使用对话框API。简单创建一个活动并在<activity>清单元素设置主题为Theme.Holo.Dialog。

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

Passing Events Back to the Dialog's Host

当用户触摸对话框操作按钮之一或者选择列表中的项目时,DialogFragment可能会执行必要操作,但是往往会向活动或片段传递事件。要做到这一点,就需要定义每种类型的单击事件的方法接口。然后在要接收操作事件的主机组件实现该接口。

例如DialogFragment定义了提供返回主机活动的事件的界面:

 
public class NoticeDialogFragment extends DialogFragment {
 
    /* The activity that creates an instance of this dialog fragment must
     * implement this interface in order to receive event callbacks.
     * Each method passes the DialogFragment in case the host needs to query it. */
    public interface NoticeDialogListener {
        public void onDialogPositiveClick(DialogFragment dialog);
        public void onDialogNegativeClick(DialogFragment dialog);
    }
 
    // Use this instance of the interface to deliver action events
    NoticeDialogListener mListener;
 
    // Override the Fragment.onAttach() method to instantiate the NoticeDialogListener
    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        // Verify that the host activity implements the callback interface
        try {
            // Instantiate the NoticeDialogListener so we can send events to the host
            mListener = (NoticeDialogListener) activity;
        } catch (ClassCastException e) {
            // The activity doesn't implement the interface, throw exception
            throw new ClassCastException(activity.toString()
                    + " must implement NoticeDialogListener");
        }
    }
    ...
}
 

The activity hosting the dialog creates an instance of the dialog with the dialog fragment's constructor and receives the dialog's events through an implementation of the NoticeDialogListener interface:

 
public class MainActivity extends FragmentActivity
                          implements NoticeDialogFragment.NoticeDialogListener{
    ...
 
    public void showNoticeDialog() {
        // Create an instance of the dialog fragment and show it
        DialogFragment dialog = new NoticeDialogFragment();
        dialog.show(getSupportFragmentManager(), "NoticeDialogFragment");
    }
 
    // The dialog fragment receives a reference to this Activity through the
    // Fragment.onAttach() callback, which it uses to call the following methods
    // defined by the NoticeDialogFragment.NoticeDialogListener interface
    @Override
    public void onDialogPositiveClick(DialogFragment dialog) {
        // User touched the dialog's positive button
        ...
    }
 
    @Override
    public void onDialogNegativeClick(DialogFragment dialog) {
        // User touched the dialog's negative button
        ...
    }
}
 

因为主机活动实现了由 onAttach()执行的回调方式NoticeDialogListener,对话框片段可以使用接口回调方法来传递事件。

 
public class NoticeDialogFragment extends DialogFragment {
    ...
 
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        // Build the dialog and set up the button click handlers
        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) {
                       // Send the positive button event back to the host activity
                       mListener.onDialogPositiveClick(NoticeDialogFragment.this);
                   }
               })
               .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
                   public void onClick(DialogInterface dialog, int id) {
                       // Send the negative button event back to the host activity
                       mListener.onDialogNegativeClick(NoticeDialogFragment.this);
                   }
               });
        return builder.create();
    }
}
 

显示对话框

当想要显示对话框时,创建DialogFragment实例并调用show(),传递FragmentManager和对话框片段的标签名称。

可以通过调用 FragmentActivity的getSupportFragmentManager()或者 Fragment的getFragmentManager()。例如:

 
public void confirmFireMissiles() {
    DialogFragment newFragment = new FireMissilesDialogFragment();
    newFragment.show(getSupportFragmentManager(), "missiles");
}
 

第二个参数"missiles"是系统用来必要时保存和恢复片段状态的标记名称。标签还可以调用findFragmentByTag()来获得控制代码。

显示对话框全屏或作为嵌入式片段

这种情况下不能使用AlertDialog.Builder 或其他Dialog对话来建立对话框。如果想要 嵌入DialogFragment,就必须定义对话框UI,然后加载onCreateView()回调的布局。 下面是作为对话或者嵌入片段的DialogFragment例子(使用名为purchase_items.xml的布局):

 
public class CustomDialogFragment extends DialogFragment {
    /** The system calls this to get the DialogFragment's layout, regardless
        of whether it's being displayed as a dialog or an embedded fragment. */
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        // Inflate the layout to use as dialog or embedded fragment
        return inflater.inflate(R.layout.purchase_items, container, false);
    }
 
    /** The system calls this only when creating the layout in a dialog. */
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        // The only reason you might override this method when using onCreateView() is
        // to modify any dialog characteristics. For example, the dialog includes a
        // title by default, but your custom layout might not need it. So here you can
        // remove the dialog title, but you must call the superclass to get the Dialog.
        Dialog dialog = super.onCreateDialog(savedInstanceState);
        dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
        return dialog;
    }
}
 

这里显示了一些代码,可以决定是否根据屏幕尺寸用对话或全屏UI来显示片段:

 
public void showDialog() {
    FragmentManager fragmentManager = getSupportFragmentManager();
    CustomDialogFragment newFragment = new CustomDialogFragment();
 
    if (mIsLargeLayout) {
        // The device is using a large layout, so show the fragment as a dialog
        newFragment.show(fragmentManager, "dialog");
    } else {
        // The device is smaller, so show the fragment fullscreen
        FragmentTransaction transaction = fragmentManager.beginTransaction();
        // For a little polish, specify a transition animation
        transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
        // To make it fullscreen, use the 'content' root view as the container
        // for the fragment, which is always the root view for the activity
        transaction.add(android.R.id.content, newFragment)
                   .addToBackStack(null).commit();
    }
}
 

欲查询执行片段事务的更多信息,请参见片段指南。

这一事例中mIsLargeLayout boolean指定当前设备是否要使用应用程序大布局设计。设置这种boolean的最好方法就是用不同屏幕大小的替代资源值来声明bool资源值。例如,有适用于不同屏幕尺寸的bool资源的两个版本:

res/values/bools.xml

 
<!-- Default boolean values -->
<resources>
    <bool name="large_layout">false</bool>
</resources>
 

res/values-large/bools.xml

 
<!-- Large screen boolean values -->
<resources>
    <bool name="large_layout">true</bool>
</resources>
 

接着使用活动onCreate()方法可以初始化mIsLargeLayout值。

 
boolean mIsLargeLayout;
 
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
 
    mIsLargeLayout = getResources().getBoolean(R.bool.large_layout);
}
 

用对话框在大屏幕上显示活动

想要仅当在大屏幕时显示对话框活动,可以在<activity>清单元素中应用Theme.Holo.DialogWhenLarge主题:

 
<activity android:theme="@android:style/Theme.Holo.DialogWhenLarge" >
 

请参阅样式和主题指南,以便查找用主题定义活动样式的更多信息。

关闭对话框

当用户触摸AlertDialog.Builder创建的任何操作按钮时,系统会关闭对话框。

当用户触摸对话框(除单选按钮和复选框之外)列表中的项目时,系统也会关闭对话框。否则可以在DialogFragment调用dismiss()来关闭对话框。

如果对话框消失时需要执行某些操作,就可以在DialogFragment实现onDismiss()方法。

可以取消对话框。如果用户按下返回按钮,触摸对话框区域外的屏幕就会进行这一操作。如果显性调用对话框的cancel( )(比如相应对话框的“取消”按钮)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值