Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 598|回复: 0

《Android Dev Guide》系列教程12:用户界面之建立对话框Dialogs

[复制链接]

该用户从未签到

发表于 2011-10-25 08:53:26 | 显示全部楼层 |阅读模式
建立对话框Dialog
Dialog是一个常见的显示在当前activity之上的小窗口。下面的activity会失去焦点,而dialog回接受用户输入。dialog常用在与程序直接相关联的通知和短小的activity中。
Android API支持以下几种dialog:
AlertDialog:
它可以包含0、1、2、3个按钮,或者一个列表或者多选单选按钮等,它是一个功能最强大的dialog接口,详细信息可参考下面的章节。
ProgressDialog:
它会显示一个进度条或者进度环,因为他是AlertDialog的子类,所有野支持按钮。
DatePickerDialog:
用来选择日期的对话框。
TimerPickerDialog:
用来选择时间的。
如果你想要定制自己的dialog,你可以继承Dialog对象,或者它的任何一个子类,并且定义一个新的布局。



显示一个Dialog
Dialog 总是被当做activity的一部分来创建和显示。你可以在activity的onCreateDialog(int)方法中创建一个dialog。当你使用这个方法,android系统会自动的管理每个dialog的状态并且关联到所在的activity中,让这个activity成为dialog的管理者。每个dialog都会继承activity的某些特性。例如,当dialog打开时,按下menu弹出的是所在activity的菜单,调节的是所在activity的音量。
注意:如果你决定在onCreateDialog()方法之外建立dialog,他将不会连接到activity中,此时,你可以使用setOwnerActivity(Activity)方法来绑定activity。
当你显示dialog时,调用showDialog(int)来传递一个dialog的id句柄。
当一个dialog首次显示时,android会在实例化dialog的activity中调用onCreateDialog(int)方法。回调方法会传递相同的id给showDialog(int)。当 创建完一个dialog后,会再方法的最后返回这个对象。
在dialog显示前,android回调用可选的方法 :onPrepareDialog(int,Dialog)。如果你想在每次调用dialog时改变一些配置的话,你可以定义这个方法。OnPrepareDialog(int,Dialog)方法会在每次调用dialog时调用,而onCreateDialog(int)方法只会调用一次。如果你不定义onPrepareDialog()方法,那么打开的dialog会保持上一次的状态。这个方法也会传递dialog的id句柄。
定义这两个onXXX()方法最好使用一个switch结构来检测Id参数,每一个case项都应该创建自己的dialog。例如。想象一个游戏使用两个不同的dialog,一个暂停一个结束游戏:

static final int DIALOG_PAUSED_ID = 0;  

static final int DIALOG_GAMEOVER_ID = 1;  
复制代码
然后,再onCreateDialog(int)里根据id创建dialog:
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;  

}  
复制代码
注意:在例子中没有详写,因为定义dialog属于另外的章节。现在可以调用showDilaog(int)来显示一个dialog了:
showDialog(DIALOG_PAUSED_ID);  
复制代码

取消Dialog的显示调用dialog的dismiss()方法可以隐藏正在显示的dialog,如果必要的话,可以调用activity的dismissDialog(int)方法,他俩效果是一样的。如果使用的onCreateDialog(int)方法来管理dialog的状态,那么每次当你的dialog消失时,对话框的状态都会被activity保存着。如果不太需要这个对话框或者不希望activity保留dialog的状态,可以调用removeDialog(int)方法。它会删除任何关于dialog的引用,如果dialog正在显示,此方法会让dialog隐藏。隐藏dialog监听器的使用如果你想让activity在dialog隐藏时执行某些动作,那么你可以建立一个监听器。首先定义DialogInterface.OnDismissListerner 接口,这个接口只有一个方法,onDismiss(DialogInterface),当dialog隐藏时被调用,然后传递OnDismissListener 对象给setOnDismissLister()方法。然而,注意dialog也可以是取消,用户让这个dialog取消也是一种特殊的情况。当用户按下back键时,或者调用cancel()方法时会发生这种情况。当一个dialog被取消时,OnDismissLister监听器仍然会收到通知,但如果你喜欢的到明确的取消消息,可以注册DialogInterface.OnCancelLister监听器。

AlertDialog的创建
AlertDialog时Dialog的子类,Dilaog绝大多数是这个强大类型,你可以在以下情况下使用:@ 一个标题@ 一个文本信息@ 一个两个或者三个按钮@ 一个单选或者多选列表建立AlertDialog,使用AlertDialog.Builder子类。使用AlertDialog.Builder(Context)方法来获得一个Builder,并且使用它的公共方法来定义AlertDialog所有的属性。最后,调用create()方法来显示。下面显示了如何定义AlertDialog.Builder类的一些属性,如果在onCreateDialog()方法中使用了例子中的代码,你可以返回结果对话框来显示这个dialog。添加按钮


创建一个上图所示包含按钮的AlertDialog,可以使用setXXXButton()方法: AlertDialog.Builder builder = new AlertDialog.Builder(this);  

builder.setMessage("Are you sure you want to exit?")  

       .setCancelable(false)  

       .setPositiveButton("Yes", new DialogInterface.OnClickListener() {  

           public void onClick(DialogInterface dialog, int id) {  

                MyActivity.this.finish();  

           }  

       })  

       .setNegativeButton("No", new DialogInterface.OnClickListener() {  

           public void onClick(DialogInterface dialog, int id) {  

                dialog.cancel();  

           }  

       });  

AlertDialog alert = builder.create();  
复制代码
首先,通过setMessage(CharSequence)为dialog添加一个message,然后通过setCancelable(boolean)方法让此dialog无法通过按back键来取消。每个按钮都需要调用setXXXButton()方法,例如setPositiveButton()方法,DialogInterface.OnClickListener()类会定义按下按钮所要做的处理。注意:每种类型的按钮只能加一个,这就是说,你不能添加多于一个的positive按钮。最多能添加三个按钮,positive, neutral, 和 negative.他们名字所显示的功能并未实现,但能帮你记住要实现的功能。
添加一个列表




如上图所示,使用setItems()方法添加可选列表:
final CharSequence[] items = {"Red", "Green", "Blue"};  

AlertDialog.Builder builder = new AlertDialog.Builder(this);  

builder.setTitle(&quotick a color");  

builder.setItems(items, new DialogInterface.OnClickListener() {  

    public void onClick(DialogInterface dialog, int item) {  

        Toast.makeText(getApplicationContext(), items[item], Toast.LENGTH_SHORT).show();  

    }  

});  

AlertDialog alert = builder.create();  
复制代码
首先,使用setTitle(CharSequence)方法设置标题,然后使用setItem()方法添加可选列表,这个列表会接收一个item数组来显示,DialogInterFace.OnClickListener类会定义他们的点击事件。
添加选择框和单选按钮

通过setMultiChoiceItems()方法或 setSingleChoiceItems()方法来分别建立一个多选按钮列表或者单选列表,如果再onCreateDialog()方法中建立了其中一种列表,android会为你管理这个list。当activity处于活动状态时,dialog会记住当才选中项,如果退出了程序,选择结果便会丢失。注意:当用户离开或者暂停activity时,如果你想保存选择状态,你必须在整个activity的生命周期中保存这个设置。永久的保存所选项,甚至当前进程完全被关闭,你需要使用数据存储方式来保存。建立一个如上图所示的列表dialog,代码和上面的例子相同,只需要把setItems()方法改为setSingleChoiceItems()方法即可。
final CharSequence[] items = {"Red", "Green", "Blue"};  

AlertDialog.Builder builder = new AlertDialog.Builder(this);  

builder.setTitle("Pick a color");  

builder.setSingleChoiceItems(items, -1, new DialogInterface.OnClickListener() {  

    public void onClick(DialogInterface dialog, int item) {  

        Toast.makeText(getApplicationContext(), items[item], Toast.LENGTH_SHORT).show();  

    }  

});  

AlertDialog alert = builder.create();  
复制代码
setSingleChoiseItems()方法的第二个参数是checkedItem的id值,从0开始对应着位置,如果返回”-1“表明没有选中任何项。


进度对话框 ProgressDialog 的建立


ProgressDialog时AlertDialog的子类,它会显示一个表示进度的圆形动画,来表示一个进度或者任务正在运行,也可以时一个进度条,能清晰的表示出进度。他也能添加按钮,比如取消一个下载进程。调用ProgressDialog.show()方法可以显示进程对话框,例如,上图的对话框可通过如下代码生成: ProgressDialog dialog = ProgressDialog.show(MyActivity.this, "",   

                        "Loading. Please wait...", true);  
复制代码
第一个参数是程序的Context引用,四二个为标题,第三个为显示的信息,最后一个为类型,(当创建进度条时才会用到,下节讨论)。默认的进度条为圆形的样式,如果你想生成一个通过具体数值来显示任务的加载情况的进度条,下一节会讨论。进度条的显示显示一个进度条要经过以下几个步骤:1-使用ProgressDialog(Context)方法初始化2-使用setProgressStyle(int)方法设置类型。3-调用show()方法显示,或者在onCreateDialog(int)方法里返回一个ProgressDialog。4-你可以调用setProgress(int)方法,根据整体的任务完成度来设置一个具体进度值,或者使用incrementPressBy(int)来设置一个增长值。例如:
ProgressDialog progressDialog;  

progressDialog = new ProgressDialog(mContext);  

progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);  

progressDialog.setMessage("Loading...");  

progressDialog.setCancelable(false);  
复制代码
设置代码非常简单,大部分代码是在dialog参与进程并且更新的功能里。你会发现,另起一个线程来做这个工作是很有必要的,要把消息传递给activity的UI线程里需要用到 Handler 消息机制。如果你并不熟悉使用额外的线程,那么看这个例子:这个例子使用了第二个线程来跟踪任务的进度(实际上只是在数值上加到100),线程通过 Handler 发了一个Message 给主activity,然后主activity更新ProgressDialog。
package com.example.progressdialog;  

import android.app.Activity;  

import android.app.Dialog;  

import android.app.ProgressDialog;  

import android.os.Bundle;  

import android.os.Handler;  

import android.os.Message;  

import android.view.View;  

import android.view.View.OnClickListener;  

import android.widget.Button;  

public class NotificationTest extends Activity {  

    static final int PROGRESS_DIALOG = 0;  

    Button button;  

    ProgressThread progressThread;  

    ProgressDialog progressDialog;  

     

    /** Called when the activity is first created. */  

    public void onCreate(Bundle savedInstanceState) {  

        super.onCreate(savedInstanceState);  

        setContentView(R.layout.main);  

        // Setup the button that starts the progress dialog  

        button = (Button) findViewById(R.id.progressDialog);  

        button.setOnClickListener(new OnClickListener(){  

            public void onClick(View v) {  

                showDialog(PROGRESS_DIALOG);  

            }  

        });   

    }  

     

    protected Dialog onCreateDialog(int id) {  

        switch(id) {  

        case PROGRESS_DIALOG:  

            progressDialog = new ProgressDialog(NotificationTest.this);  

            progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);  

            progressDialog.setMessage("Loading...");  

            progressThread = new ProgressThread(handler);  

            progressThread.start();  

            return progressDialog;  

        default:  

            return null;  

        }  

    }  

    // Define the Handler that receives messages from the thread and update the progress  

    final Handler handler = new Handler() {  

        public void handleMessage(Message msg) {  

            int total = msg.getData().getInt("total");  

            progressDialog.setProgress(total);  

            if (total >= 100){  

                dismissDialog(PROGRESS_DIALOG);  

                progressThread.setState(ProgressThread.STATE_DONE);  

            }  

        }  

    };  

    /** Nested class that performs progress calculations (counting) */  

    private class ProgressThread extends Thread {  

        Handler mHandler;  

        final static int STATE_DONE = 0;  

        final static int STATE_RUNNING = 1;  

        int mState;  

        int total;  

         

        ProgressThread(Handler h) {  

            mHandler = h;  

        }  

         

        public void run() {  

            mState = STATE_RUNNING;     

            total = 0;  

            while (mState == STATE_RUNNING) {  

                try {  

                    Thread.sleep(100);  

                } catch (InterruptedException e) {  

                    Log.e("ERROR", "Thread Interrupted");  

                }  

                Message msg = mHandler.obtainMessage();  

                Bundle b = new Bundle();  

                b.putInt("total", total);  

                msg.setData(b);  

                mHandler.sendMessage(msg);  

                total++;  

            }  

        }  

         

        /* sets the current state for the thread,

         * used to stop the thread */  

        public void setState(int state) {  

            mState = state;  

        }  

    }  

}  
复制代码
自定义dialog的建立

如果你想自定义dialog的布局,你可以自己创建一个dialog布局。定义好之后,传递根View对象或者资源ID到setContextView(View)方法。例如,如上图的dialog:1-建立一个xml布局文件custom_dialog.xml;

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  

              android:id="@+id/layout_root"  

              androidrientation="horizontal"  

              android:layout_width="fill_parent"  

              android:layout_height="fill_parent"  

              android:padding="10dp"  

              >  

    <ImageView android:id="@+id/image"  

               android:layout_width="wrap_content"  

               android:layout_height="fill_parent"  

               android:layout_marginRight="10dp"  

               />  

    <TextView android:id="@+id/text"  

              android:layout_width="wrap_content"  

              android:layout_height="fill_parent"  

              android:textColor="#FFF"  

              />  

</LinearLayout>  
复制代码

这个xml在LinearLayout里定义了一个ImageView和TextView。
2-设置上面的布局为dialog的context view ,并且定义ImageView和TextView两个元素。

Context mContext = getApplicationContext();  

Dialog dialog = new Dialog(mContext);  

dialog.setContentView(R.layout.custom_dialog);  

dialog.setTitle("Custom Dialog");  

TextView text = (TextView) dialog.findViewById(R.id.text);  

text.setText("Hello, this is a custom dialog!");  

ImageView image = (ImageView) dialog.findViewById(R.id.image);  

image.setImageResource(R.drawable.android);  
复制代码
实例化dialog后,使用setContextView(int)方法设置自定义的布局。现在dialog便有了一个自定义的布局,你可以使用findViewById(int)方法来获得或者修改布局。3-完成了,现在你可以显示自定义的dialog了。一个dialog必须有一个title,如果你没有调用setTitile()方法,那么会标题处会显示空,但dialog仍然可见,如果你不想显示标题,只有写一个自己的dialog类了。然而,因为一个AlertDialog使用AlertDialog.builder类创建起来非常简单,你不必使用setContextView(int)方法。但必须使用setView(view)方法代替。这个方法会接受一个view参数,你需要从xml中得到根view元素。得到xml布局,通过LayoutInflater类的getLayoutflater()方法(或者getSystemService()方法),然后调用inflate(int,ViewGroup)方法,第一个参数是xml文件id,第二个参数是根view的id,在这点上,你可以使用inflated 布局来获得xml中的view对象并且定义ImageView和TextView对象,然后实例化AlertDialog.Builder类并且使用setView(View)方法来设置布局。这有一个自定义dialog布局文件的例子:
AlertDialog.Builder builder;  

AlertDialog alertDialog;  

Context mContext = getApplicationContext();  

LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(LAYOUT_INFLATER_SERVICE);  

View layout = inflater.inflate(R.layout.custom_dialog,  

                               (ViewGroup) findViewById(R.id.layout_root));  

TextView text = (TextView) layout.findViewById(R.id.text);  

text.setText("Hello, this is a custom dialog!");  

ImageView image = (ImageView) layout.findViewById(R.id.image);  

image.setImageResource(R.drawable.android);  

builder = new AlertDialog.Builder(mContext);  

builder.setView(layout);  

alertDialog = builder.create();  
复制代码
使用自定义布局这种方式来生成dialog,可以让你使用更高级的特性,比如管理按钮、列表、标题、图标等。
回复

使用道具 举报

该用户从未签到

发表于 2011-10-25 08:53:28 | 显示全部楼层

Re:《Android

谢谢分享。。。。。。。。。。。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

GMT+8, 2025-1-11 14:05 , Processed in 0.415142 second(s), 45 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表