信息提醒之对话框(AlertDialog + ProgressDialog)-更新中(下)

简介: 信息提醒之对话框(AlertDialog + ProgressDialog)-更新中(下)

进度对话框


查看大拿的总结


进度对话框通过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类来不断更新进度对话框的进度值。

20160224213310889.gif

// 水平进度条的最大值
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();


20160224225504083.gif

主要代码:

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

在对话框按钮和内容文本中插入图像


20160224233538437.gif

给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表示全透明,此时就看不到对话框了。

20160224233443146.gif

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


相关文章
|
9天前
|
人工智能 开发工具 iOS开发
Claude Code 新手完全上手指南:安装、国产模型配置与常用命令全解
Claude Code 是一款运行在终端环境中的 AI 编程助手,能够直接在命令行中完成代码生成、项目分析、文件修改、命令执行、Git 管理等开发全流程工作。它最大的特点是**任务驱动、终端原生、轻量高效、多模型兼容**,无需图形界面、不依赖 IDE 插件,能够深度融入开发者日常工作流。
3125 8
|
12天前
|
Shell API 开发工具
Claude Code 快速上手指南(新手友好版)
AI编程工具卷疯啦!Claude Code凭借任务驱动+终端原生的特性,成了开发者的效率搭子。本文从安装、登录、切换国产模型到常用命令,手把手带新手快速上手,全程避坑,30分钟独立用起来。
3194 20
|
5天前
|
人工智能 Linux BI
国内用 Claude Code 终于不用翻墙了:一行命令搞定,自动接 DeepSeek
JeecgBoot AI专题研究 一键脚本:Claude Code + JeecgBoot Skills + DeepSeek 全平台接入 一行命令装好 Claude Code + JeecgBoot Skills + DeepSeek 接入,无需翻墙使用 Claude Code,支持 Wind
2115 3
国内用 Claude Code 终于不用翻墙了:一行命令搞定,自动接 DeepSeek
|
24天前
|
人工智能 JSON 供应链
畅用7个月无影 JVS Claw |手把手教你把JVS改造成「科研与产业地理情报可视化大师」
LucianaiB分享零成本畅用JVS Claw教程(学生认证享7个月使用权),并开源GeoMind项目——将JVS改造为科研与产业地理情报可视化AI助手,支持飞书文档解析、地理编码与腾讯地图可视化,助力产业关系图谱构建。
23589 15
畅用7个月无影 JVS Claw |手把手教你把JVS改造成「科研与产业地理情报可视化大师」
|
1天前
|
人工智能 自然语言处理 文字识别
阿里云百炼Qwen3.7-Max简介:能力、优势、支持订阅计划参考
Qwen3.7-Max是阿里云百炼面向智能体时代推出的新一代旗舰模型,对标GPT-5.5、Claude Opus 4.7等闭源旗舰。该模型支持百万级token上下文窗口,具备顶级推理能力、多模态搜索与视觉理解增强、流式输出低延迟响应等核心优势,覆盖编程、办公、长周期自主执行等复杂场景。同时支持OpenAI接口兼容,便于系统快速迁移。用户可通过Token Plan团队版、Coding Plan或节省计划等订阅方式灵活调用,适合企业级高要求场景使用。
|
11天前
|
人工智能 JSON BI
DeepSeek V4-Pro 接入 Claude Code 完全实战:体验、测试与关键避坑指南
Claude Code 作为当前主流的 AI 编程辅助工具,凭借强大的代码理解、工程执行与自动化能力深受开发者喜爱,但原生模型的使用成本相对较高。为了在保持能力的同时进一步降低开销,不少开发者开始寻找兼容度高、价格更友好的替代模型。DeepSeek V4 系列的发布带来了新的选择,该系列包含 V4-Pro 与 V4-Flash 两款模型,并提供了与 Anthropic 完全兼容的 API 接口,理论上只需简单修改配置,即可让 Claude Code 无缝切换为 DeepSeek 引擎。
2628 3
|
3天前
|
人工智能 自然语言处理 安全
Claude Code 全攻略:命令大全+三种模式+记忆体系+实战工作流完整手册
Claude Code 是当前最流行的终端级 AI 编程助手,能够直接在命令行中完成代码生成、项目理解、文件修改、命令执行、错误修复等全流程开发工作。它不依赖图形界面、不占用额外资源,却能深度理解项目结构,自动生成规范代码,大幅提升研发效率。
762 2
|
10天前
|
人工智能 安全 开发工具
Claude Code 官方工作原理与使用指南
Claude Code 不是传统代码补全工具,而是 Anthropic 推出的终端 AI 代理,具备代理循环、双驱动架构(模型+工具)、全局项目感知、6 种权限模式等核心能力,本文基于官方文档系统解析其工作原理与高效使用技巧。
1437 0