Day16、PopupWindow弹出窗和其他AlertDialog的子对话框

一、PopupWindow,在学了自定义对话框后紧接着学习“弹出窗”

1.弹出窗和对话框(PopupWindow和AlertDialog)的异同点,一搜一大堆,一般而言:PopupWindow不像AlertDialog那么霸道,它不会抢夺焦点,以下运行结果可以看出。
2.PopupWindow的实现步骤。
第一步:自定义.xml布局文件;
第二步:获取LayoutInflate对象;
第三步:调用inflate()方法获取View对象;
第四步:创建PopupWindow对象;
第五步:调用PopupWindow的showAsDropDown或者showAsLocation方法显示对话窗口。
3.重复利用上节代码,只是在activity_main.xml中多添加一个按钮,沿用自定义的define_dialog.xml这里直接贴出MainActivity.java文件代码:
package com.oldtogether.defineddialog;

import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.PopupWindow;
import android.widget.Toast;

public class MainActivity extends ActionBarActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button btnTest = (Button) findViewById(R.id.btn_test);
        btnTest.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                Toast.makeText(MainActivity.this, "PopupWindow不像AlertDialog那样霸道,他不会抢夺焦点的", Toast.LENGTH_LONG).show();
            }
        });
    }
    PopupWindow popupWindow;
    public void btnClick(View v){
        LayoutInflater inflater = LayoutInflater.from(this);
        View myView = inflater.inflate(R.layout.define_dialog, null);

        popupWindow = new PopupWindow(myView, 400, 500);//后两个参数单位是像素px,对话框的长和高
        myView.findViewById(R.id.btn_sure).setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                popupWindow.dismiss();
                Toast.makeText(MainActivity.this, "点击了确定", Toast.LENGTH_LONG).show();
            }
        });
        //显示方式,只设置含一个参数的下拉方法,参数是锚定点,指明在那个锚定控件下会出现该弹出窗
        popupWindow.showAsDropDown(v);
    }
}
3.运行结果

这里写图片描述
这里写图片描述

二、使用Activity实现类似对话框

1.知识是相通的,可以设置Activity的相关属性,来实现类似对话框。
2.MainActivity2.java中显示主布局,代码如下:
package com.oldtogether.defineddialog;

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity2 extends ActionBarActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button btnTest = (Button) findViewById(R.id.btn_test);
        btnTest.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                Toast.makeText(MainActivity2.this, "PopupWindow不像AlertDialog那样霸道,他不会抢夺焦点的", Toast.LENGTH_LONG).show();
            }
        });
    }

    public void btnClick(View v) {
        Intent intent = new Intent(this, DialogActivity.class);
        startActivity(intent);
    }
}
3.在DialogActivity.java中设置显示自定义的布局,很简单,代码如下:
package com.oldtogether.defineddialog;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.Window;

public class DialogActivity extends Activity{
     @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.define_dialog);

        findViewById(R.id.btn_sure).setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                finish();
            }
        });
    }
}
4.运行结果:

这里写图片描述
这里写图片描述

5.从上面的运行结果可以看出,在对话框形式上只会达到了类同,而区别甚大,细心的人会发现,DialogActivity上面有软件图标,和我们定义的project,然而只需要两行代码可以改变这一现象。
1):
//第一步:在AndroidManifest.xml文件中设置style下的theme为Dialog
        <activity 
            android:name=".DialogActivity"
            android:theme="@android:style/Theme.Dialog">
        </activity>
2):
//第二步:设置Activity的窗口风格,注意在加载布局之前加代码,代码如下:
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.define_dialog);
3):运行结果:

这里写图片描述

三、AlertDialog家族中还有其他对话框,如ProgressDialog(进度对话框)、DatePickerDialog(日期选择对话框)、TimePickerDialog(时间选择对话框)

1.日期选择对话框,代码如下:
package com.oldtogether.defineddialog;

import java.util.Calendar;

import android.app.DatePickerDialog;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.Toast;

public class MainActivity3 extends ActionBarActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button btnTest = (Button) findViewById(R.id.btn_test);
        btnTest.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                Toast.makeText(MainActivity3.this, "PopupWindow不像AlertDialog那样霸道,他不会抢夺焦点的", Toast.LENGTH_LONG).show();
            }
        });
    }

    public void btnClick(View v) {
        //获得系统的时间对象
        Calendar c = Calendar.getInstance();
        //创建一个DatePickerDialog对话框,并将它显示
        new DatePickerDialog(this,
                //绑定监听器(我们可以修改和选择时间当然少不了监听器)
                new DatePickerDialog.OnDateSetListener() {

                    @Override
                    public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
                        String text = "您选择了:"+year+"年"+(monthOfYear+1)+"月"+dayOfMonth+"日";
                        Toast.makeText(MainActivity3.this, text, Toast.LENGTH_LONG).show();
                    }
                }, 
                c.get(Calendar.YEAR), 
                c.get(Calendar.MONTH),
                c.get(Calendar.DAY_OF_MONTH)).show();
    }
}
2.运行结果:

这里写图片描述

3.TimePickerDialog(时间选择对话框),直接贴关键代码
public void btnClick(View v) {
        //获得系统的时间对象
        Calendar c = Calendar.getInstance();
        //创建一个TimePickerDialog对话框,并将它显示
        new TimePickerDialog(this, 
                new TimePickerDialog.OnTimeSetListener() {

                    @Override
                    public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
                        String text = "您选择了:"+hourOfDay+"时"+minute+"分";
                        Toast.makeText(MainActivity4.this, text, Toast.LENGTH_LONG).show();
                    }
                },
                //设置初始时间
                c.get(Calendar.HOUR_OF_DAY), 
                c.get(Calendar.MINUTE),
                //是否为24小时制
                true).show();
    }
4.运行结果

这里写图片描述

四、进度对话框(日常生活中很常见进度对话框,比如说加载游戏时的进度条,安装某款软件时的进度条)。

1.简单环形进度对话框,代码如下
package com.oldtogether.defineddialog;

import android.app.ProgressDialog;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity5 extends ActionBarActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button btnTest = (Button) findViewById(R.id.btn_test);
        btnTest.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                Toast.makeText(MainActivity5.this, "PopupWindow不像AlertDialog那样霸道,他不会抢夺焦点的", Toast.LENGTH_LONG).show();
            }
        });
    }

    ProgressDialog pd;
    public void showProgress(){
        pd = new ProgressDialog(this);
        pd.setTitle("正在玩命加载中......");
        pd.setMessage("请您稍等");
        pd.setCancelable(true);//设置可取消,比如我们在加载游戏界面时间过长时,会怀疑网连上了没有,此时需要取消
        pd.setProgressStyle(ProgressDialog.STYLE_SPINNER);//设置进度条显示的风格,当然默认为圆圈
        pd.show();
    }
    public void btnClick(View v) {
        showProgress();
    }
}
1.1运行结果

这里写图片描述

2.虽然上面的环形进度条显示了,但是没有什么意义,因为我们不知道它到底进行什么耗时操作,那怎么设置耗时操作呢?直接贴代码:
package com.oldtogether.defineddialog;

import android.app.ProgressDialog;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity5 extends ActionBarActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button btnTest = (Button) findViewById(R.id.btn_test);
        btnTest.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                Toast.makeText(MainActivity5.this, "PopupWindow不像AlertDialog那样霸道,他不会抢夺焦点的", Toast.LENGTH_LONG).show();
            }
        });
    }

    ProgressDialog pd;
    public void showProgress(){
        pd = new ProgressDialog(this);
        pd.setTitle("正在玩命加载中......");
        pd.setMessage("请您稍等");
        pd.setCancelable(true);//设置可取消,比如我们在加载游戏界面时间过长时,会怀疑网连上了没有,此时需要取消
        pd.setProgressStyle(ProgressDialog.STYLE_SPINNER);//设置进度条显示的风格,当然默认为圆圈
        pd.show();
    }

    //Handler线程之间的通讯,作用等同于Activity之间的Intent
    Handler handler = new Handler(){
        @Override
        //主线程(UI线程)
        public void handleMessage(Message msg) {//接受子线程的消息
            pd.dismiss();
        }
    };

    public void btnClick(View v) {
        /*
         * 点击按钮发生两件事情,并且是并行的(因为new Thread)
         * 1、环形进度条旋转;
         * 2、子线程运行。
         */
        showProgress();

        //创建一个子线程(new Thread然后点出start,最后重写run)
        new Thread(){
            public void run() {
                for(int i=0;i<3;i++){
                    try {
                        Thread.sleep(1000);//循环一次睡1秒(总共睡三秒),注意单位是毫秒
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                handler.sendEmptyMessage(0);//发送消息,在子线程里面
            };
        }.start();
    }
}
2.1运行结果

这里写图片描述

3.水平进度条的进度实现,代码如下:
package com.oldtogether.defineddialog;

import android.app.ProgressDialog;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity6 extends ActionBarActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button btnTest = (Button) findViewById(R.id.btn_test);
        btnTest.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                Toast.makeText(MainActivity6.this, "PopupWindow不像AlertDialog那样霸道,他不会抢夺焦点的", Toast.LENGTH_LONG).show();
            }
        });
    }

    ProgressDialog pd;
    public void showProgress(){
        pd = new ProgressDialog(this);
        pd.setTitle("正在玩命加载中......");
        pd.setMessage("请您稍等");
        pd.setCancelable(true);//设置可取消,比如我们在加载游戏界面时间过长时,会怀疑网连上了没有,此时需要取消
        pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);//设置进度条显示的风格
        pd.setMax(10);//设置总量
        pd.show();
    }

    //Handler线程之间的通讯,作用等同于Activity之间的Intent
    Handler handler = new Handler(){
        @Override
        //主线程(UI线程)
        public void handleMessage(Message msg) {//接受子线程的消息
            if(msg.what == 0){
                pd.dismiss();
            }else if(msg.what == 1){
                pd.setProgress(msg.arg1);
            }
        }
    };

    public void btnClick(View v) {
        /*
         * 点击按钮发生两件事情,并且是并行的(因为new Thread)
         * 1、条形进度条递增;
         * 2、子线程运行。
         */
        showProgress();

        //创建一个子线程(new Thread然后点出start,最后重写run)
        new Thread(){
            public void run() {
                for(int i=1;i<=10;i++){
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    Message msg = Message.obtain();//为了节省资源
                    msg.arg1=i;
                    msg.what=1;
                    handler.sendMessage(msg);
                }
                handler.sendEmptyMessage(0);//发送消息,在子线程里面
            };
        }.start();
    }
}
3.1运行结果

这里写图片描述
这里写图片描述

五、心得总结:

1.PopupWindow可以以下拉和指定位置的方式弹出对话框,并且用此方法得到的对话框不会抢夺焦点;
2.ProgressDialog进度对话框和Handler一起使用,用来完成一系列耗时操作;
3.主线程和子线程。通常情况下,控件的更新只能由主线程控制,但是有时候,子线程想操作某控件,可以吗?答案是可以的,但是必须通过发送Message来告诉主线程,最终决定权还是主线程。(比如上面的是一个间接的耗时操作)。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值