进度对话框
进度对话框通过android.app.ProgressDialog类实现,该类是AlertDialog的之类,但与AlertDialog类不同,我们可以直接使用new关键字创建ProgressDialog对象。
进度条对话框除了要设置普通对话框必要的值外,还需要设置另外两个值:进度的最大值和当前的进度。
// 设置进度的最大值 public void setMax(int max) // 设置当前的进度 public void setProgress(int value)
初始进度必须使用setProgress方法设置,而递增进度除了可以使用setProgress方法设置外,还可以使用以下方法
// 设置进度值的增量 public void incrementProgressBy(int diff)
区别在于 setProgress设置的绝对值,incrementProgressBy设置的是进度的增量。
与普通的对话框一样,进度对话框最多也只能添加3个按钮,而且可以设置进度对话框的风格:
// 创建ProgressDialog类 ProgressDialog pg = new ProgressDialog(); // 设置进度对话框为水平进度条风格 pg.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
案例说明:
本案例演示了水平和原型进度对话框的实现方法,其中进度条包含两个按钮“暂停”和 “停止”,单击暂停后,进度对话框关闭,再此显示进度对话框时,进度条的起始位置从上次关闭对话框的位置开始(仅限与水平进度条)。 单击取消,关闭对话框,再此显示时,进度从0开始。
要实现进度随着时间的变化而不断递增,需要使用多线程及定时器来完成这个工作, 本例中使用Handler类来不断更新进度对话框的进度值。
// 水平进度条的最大值 private static final int MAX_PROGRESS = 100; // 默认的初始值 private int progress = 0; private void showProgressBarDialog(int style) { final ProgressDialog progressDialog = new ProgressDialog(this); // 设置提示的title的图标,默认是没有的 progressDialog.setIcon(R.drawable.flag_mark_red); progressDialog.setTitle("数据处理中..."); progressDialog.setMessage("请稍后..."); // 设置进度对话框的风格 ,默认是圆形的 progressDialog.setProgressStyle(style); // 设置是否可以通过点击Back键取消 默认true progressDialog.setCancelable(false); // 设置在点击Dialog外是否取消Dialog进度条 默认true progressDialog.setCanceledOnTouchOutside(false); // 设置最大值 progressDialog.setMax(MAX_PROGRESS); // 设置暂停按钮 progressDialog.setButton(DialogInterface.BUTTON_POSITIVE, "暂停", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // 通过删除消息代码的方式停止定时器 progressDialogHandler.removeMessages(PROGRESSDIALOG_FLAG); } }); progressDialog.setButton(DialogInterface.BUTTON_NEGATIVE, "停止", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { progressDialogHandler.removeMessages(PROGRESSDIALOG_FLAG); progress = 0; progressDialog.setProgress(progress); } }); // 展示 progressDialog.show(); progressDialogHandler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); if (progress >= MAX_PROGRESS) { // 消失 并重置初始值 progressDialog.dismiss(); progress = 0; } else { progress++; progressDialog.incrementProgressBy(1); // 随机设置下一次递增进度 (50 +毫秒) progressDialogHandler.sendEmptyMessageDelayed(1, 50 + new Random().nextInt(500)); } } }; // 设置进度初始值 progress = (progress > 0) ? progress : 0; progressDialog.setProgress(progress); // 发送消息 progressDialogHandler.sendEmptyMessage(PROGRESSDIALOG_FLAG); }
注意事项:
进度对话框默认是圆形进度条,如需要设置水平进度条,使用setProgressStyle方法进行设置
调用sendEmptyMessage方法只能是handleMessage方法执行一次,要想以一定的时间间隔循环执行handleMessage方法,需要在handleMessage方法中调用sendEmptyMessageDelayed方法来设置hanleMessage方法下一次被调用的等待时间,这样就可以形成一个循环调用的效果。
sendEmptyMessage和 sendEmptyMessageDelayed方法的第一个参数表示消息代码,这个消息代码用来标识消息队列中的消息。 例如,使用sendMessageDelayed方法设置消息代码为1的消息在(50+)毫秒后调用handleMessage方法,可以利用这个消息代码删除该消息,这样系统就不会在(50+)毫秒之后调用handleMessage方法了。 在本例中,暂停和取消按钮单击事件都使用removeMessages方法删除了消息代码为1的消息。
消息代码可以是任意int类型的值
虽然ProgressDialog.getProgress可以获取当前进度,但是只有在水平进度条风格的对话框中才有效,如果是圆形进度条,该方法返回永远是0 。 因此本案例单独使用了一个progress变量来代替当前进度,当进度条风格是圆形时,就意味着对话框永远不会被关闭。
圆形进度条对话框的进度圆圈只是一个普通的动画,并没有任何表示进度的功能,这种对话框一般在很难估计准确的时间和进度时使用
登录对话框,自定义布局 -setView
我们可以直接使用布局文件或者代码创建视图对象,并将这些属兔对象添加到对话框中。
AlertDialog.Builder.setView方法可以将视图对象添加到当前的对话框中,使用下面的形式将一个视图对象添加到对话框中。
new AlertDialog.Builder(this) .setIcon(R.drawable.xxx) .setTitle("自定义对话框") .setView(......) .show();
主要代码:
private void showCustomViewDialog() { // 第一种方式 将布局文件转换为view LayoutInflater inflater = LayoutInflater.from(this); View view = inflater.inflate(R.layout.activity_alertdialog_login, null); // 第二种方式 因为R.layout.activity_login的根布局是LinearLayout //LinearLayout view = (LinearLayout) getLayoutInflater().inflate(R.layout.activity_alertdialog_login, null); new AlertDialog.Builder(this) .setIcon(R.drawable.tag_red) .setTitle("用户登录") .setView(view) .setPositiveButton("确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // 登录逻辑 } }) .setNegativeButton("取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // 取消逻辑 } }) .show(); }
activity_alertdialog_login.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="20dp" android:layout_marginRight="20dp" android:orientation="horizontal" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="用户名:" android:textSize="20sp" /> <EditText android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1"/> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="20dp" android:layout_marginRight="20dp" android:orientation="horizontal" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="密 码:" android:textSize="20sp" /> <EditText android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:password="true" /> </LinearLayout> </LinearLayout>
使用Activity托管对话框
Activity类提供了创建对话框的快捷方式。 在Activity类中有一个onCreateDialog方法。定义如下
protected Dialog onCreateDialog(int id)
当调用Activity.showDialog方法时,系统会调用onCreateDialog方法来返回一个Dialog对象 (AlertDialog是Dialog的子类)。 showDialog方法和onCreateDialog方法一样,也有一个int类型的id参数。该参数值传入onCreateDialog方法。可以利用不同的id来建立多个对话框。
import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.content.DialogInterface; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.ListView; import com.turing.base.R; public class ActivityDialog extends Activity implements View.OnClickListener { private final int DIALOG_DELETE_FILE = 1; private final int DIALOG_SIMPLE_LIST = 2; private final int DIALOG_SINGLE_CHOICE_LIST = 3; private final int DIALOG_MULTI_CHOICE_LIST = 4; private ListView lv = null; private String[] provinces = new String[] {"辽宁省", "山东省", "河北省", "福建省", "广东省", "黑龙江省"}; private ButtonOnClick buttonOnClick = new ButtonOnClick(1); @Override public void onClick(View view) { switch (view.getId()) { case R.id.btnDeleteFile: showDialog(DIALOG_DELETE_FILE); break; case R.id.btnSimpleList: showDialog(DIALOG_SIMPLE_LIST); break; case R.id.btnSingleChoiceList: showDialog(DIALOG_SINGLE_CHOICE_LIST); break; case R.id.btnMultiChoiceList: showDialog(DIALOG_MULTI_CHOICE_LIST); break; case R.id.btnRemoveDialog: removeDialog(DIALOG_DELETE_FILE); removeDialog(DIALOG_SIMPLE_LIST); removeDialog(DIALOG_SINGLE_CHOICE_LIST); removeDialog(DIALOG_MULTI_CHOICE_LIST); break; } } @Override protected Dialog onCreateDialog(int id) { Log.d("dialog", String.valueOf(id)); switch (id) { case DIALOG_DELETE_FILE: return new AlertDialog.Builder(this).setIcon( R.drawable.flag_mark_gray).setTitle("是否删除文件") .setPositiveButton("确定", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { new AlertDialog.Builder(ActivityDialog.this) .setMessage("文件已经被删除.") .create().show(); } }).setNegativeButton("取消", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { new AlertDialog.Builder(ActivityDialog.this) .setMessage( "您已经选择了取消按钮,该文件未被删除.") .create().show(); } }).create(); case DIALOG_SIMPLE_LIST: return new AlertDialog.Builder(this).setTitle("选择省份").setItems( provinces, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { final AlertDialog ad = new AlertDialog.Builder( ActivityDialog.this).setMessage( "您已经选择了: " + which + ":" + provinces[which]).show(); android.os.Handler hander = new android.os.Handler(); hander.postDelayed(new Runnable() { @Override public void run() { ad.dismiss(); } }, 5 * 1000); } }).create(); case DIALOG_SINGLE_CHOICE_LIST: return new AlertDialog.Builder(this).setTitle("选择省份") .setSingleChoiceItems(provinces, 1, buttonOnClick) .setPositiveButton("确定", buttonOnClick) .setNegativeButton("取消", buttonOnClick).create(); case DIALOG_MULTI_CHOICE_LIST: AlertDialog ad = new AlertDialog.Builder(this).setIcon( R.drawable.flag_mark_blue).setTitle("选择省份").setMultiChoiceItems( provinces, new boolean[] {false, true, false, true, false, false}, new DialogInterface.OnMultiChoiceClickListener() { public void onClick(DialogInterface dialog, int whichButton, boolean isChecked) { } }).setPositiveButton("确定", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { int count = lv.getCount(); String s = "您选择了:"; for (int i = 0; i < provinces.length; i++) { if (lv.getCheckedItemPositions().get(i)) s += i + ":" + lv.getAdapter().getItem(i) + " "; } if (lv.getCheckedItemPositions().size() > 0) { new AlertDialog.Builder(ActivityDialog.this) .setMessage(s).show(); } else { new AlertDialog.Builder(ActivityDialog.this) .setMessage("您未选择任何省份").show(); } } }).setNegativeButton("取消", null).create(); lv = ad.getListView(); return ad; } return null; } private class ButtonOnClick implements DialogInterface.OnClickListener { private int index; public ButtonOnClick(int index) { this.index = index; } @Override public void onClick(DialogInterface dialog, int whichButton) { if (whichButton >= 0) { index = whichButton; } else { if (whichButton == DialogInterface.BUTTON_POSITIVE) { new AlertDialog.Builder(ActivityDialog.this).setMessage( "您已经选择了: " + index + ":" + provinces[index]).show(); } else if (whichButton == DialogInterface.BUTTON_NEGATIVE) { new AlertDialog.Builder(ActivityDialog.this).setMessage("您什么都未选择.") .show(); } } } } @Override protected void onPrepareDialog(int id, Dialog dialog) { super.onPrepareDialog(id, dialog); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_activity_dialog); Button btnDeleteFile = (Button) findViewById(R.id.btnDeleteFile); Button btnSimpleList = (Button) findViewById(R.id.btnSimpleList); Button btnSingleChoiceList = (Button) findViewById(R.id.btnSingleChoiceList); Button btnMultiChoiceList = (Button) findViewById(R.id.btnMultiChoiceList); Button btnRemoveDialog = (Button) findViewById(R.id.btnRemoveDialog); btnDeleteFile.setOnClickListener(this); btnSimpleList.setOnClickListener(this); btnSingleChoiceList.setOnClickListener(this); btnMultiChoiceList.setOnClickListener(this); btnRemoveDialog.setOnClickListener(this); } }
对话框的高级应用
改变对话框的显示位置
默认对话框的位置都是位于屏幕的中央,其实可以根据需要位于屏幕的上下左右甚至是任意位置,
要控制对话框的显示位置,需要获得对话框的Window对象,并通过Window对象的一些方法来控制对话框的显示位置。
case 12: // 改变对话框的显示位置 // changePostionOfDialog(Gravity.TOP); // changePostionOfDialog(Gravity.BOTTOM); // changePostionOfDialog(Gravity.LEFT); // changePostionOfDialog(Gravity.RIGHT); // 右上方 // changePostionOfDialog(Gravity.RIGHT | Gravity.TOP); // 显示在任意位置 showAnyPostionOfDilaog(); break;
private void changePostionOfDialog(int postion) { /** AlertDialog alertDialog = new AlertDialog.Builder(this) .setIcon(R.drawable.flag_mark_blue) .setTitle("改变位置的AlertDiaolog") .setMessage("我在" + postion) .create(); alertDialog.getWindow().setGravity(postion); alertDialog.show(); **/ ProgressDialog progressDialog = new ProgressDialog(this); progressDialog.setIcon(R.drawable.flag_mark_yellow); progressDialog.setTitle("ProgressDialog改变位置"); progressDialog.setMessage("where am I ?"); progressDialog.getWindow().setGravity(postion); progressDialog.show(); }
private void showAnyPostionOfDilaog() { AlertDialog ad = new AlertDialog.Builder(this) .setIcon(R.drawable.flag_mark_blue) .setTitle("改变位置的AlertDiaolog") .setMessage("我在自定义的任意位置") .create(); Window window = ad.getWindow(); WindowManager.LayoutParams lp = window.getAttributes(); // 设置水平偏移量 lp.x = -20; // 设置垂直偏移量 lp.y = -120; window.setAttributes(lp); ad.show(); }
在对话框按钮和内容文本中插入图像
给TextView控件中插入图像的方法同样也适用。
AlertDialog alertDialog = new AlertDialog.Builder(this) .setIcon(R.drawable.flag_mark_blue) .setTitle("问候") .setMessage( Html.fromHtml("哈哈,<img src=''/>你好.", new Html.ImageGetter() { @Override public Drawable getDrawable(String source) { Drawable drawable = getResources().getDrawable( R.drawable.face); drawable.setBounds(0, 0, 32, 32); return drawable; } }, null)) .setPositiveButton( Html.fromHtml("<img src=''/>确定", new Html.ImageGetter() { @Override public Drawable getDrawable(String source) { Drawable drawable = getResources().getDrawable( R.drawable.ok); drawable.setBounds(0, 0, 20, 20); return drawable; } }, null), null) .setNegativeButton( Html.fromHtml("<img src=''/>取消", new Html.ImageGetter() { @Override public Drawable getDrawable(String source) { Drawable drawable = getResources().getDrawable( R.drawable.cancel); drawable.setBounds(0, 0, 20, 20); return drawable; } }, null), null).create(); alertDialog.show();
改变对话框的透明度
通过WindowManager.LayoutParams.alpha可以设置对话框的透明度。
Alpha的取值范围为0.0f ~ 1.0f之间,f表示float类型的数字。 默认1.0f ,完全不透明。 0.0f表示全透明,此时就看不到对话框了。
0.7f
private void showTransparency_dialog(float v) { // 创建对话框 AlertDialog ad = new AlertDialog.Builder(this) .setTitle("改变对话框的透明度") .setIcon(R.drawable.tag_red) .setMessage("Alpha的取值范围 0~1 ,默认 1 ,我的透明度是" + v) .setPositiveButton("确定",null) .create(); // 设置透明度 Window window = ad.getWindow(); WindowManager.LayoutParams lp = window.getAttributes(); lp.alpha = v ; window.setAttributes(lp); // 展示对话框 ad.show(); }