Android开发&Dialog

安卓开发中如果想提示用户某些信息,一般都是Toast、dialog或者SnackBar。
toast用作说明;SnackBar则相对“正式”一些,可以显示一些文字信息,并且可以与用户进行简单交互;dialog一般来说用于显示“重量”级信息,例如警示框,进度条等需要用于确切关注的内容。

1、Dialog初级入门 —— 使用系统Dialog

SDK中封装好的Dialog主要包括以下四种

  1. AlertDialog——提示对话框框
  2. ProgressDialog——进程对话框
  3. DatePickerDialog——日期选择对话框
  4. TimePickerDialog——时间选择对话框

1、基本提示框:AlertDialog

AlertDialog继承自Dialog,构造方法访问属性为protected,一般需要借助AlertDialog的内部类Builder来生成具体对象(类似情况可以推及Notification);

//参数是一个上下文对象Context
AlertDialog.Builder builder=new AlertDialog.Builder(context);

通过Builder类可以设定显示内容以及按钮的点击事件等

setTitle(String title): 为对话框设置标题 ;

setIcon (int iconId): 为对话框设置图标;

setMessage(String message): 为对话框设置内容;

setView(View view): 给对话框设置自定义样式 ;

setSingleChoiceItems(CharSequence[] items, int checkedItem,DialogInterface.OnClickListener listener):用来设置对话框显示一系列的单选框;

setMultiChoiceItems(CharSequence[] items, boolean[] checkedItems,DialogInterface.OnMultiChoiceClickListener listener):用来设置对话框显示一系列的复选框;

setNeutralButton(CharSequence text, DialogInterface.OnClickListener listener) : 响应中立行为的点击;

setPositiveButton(CharSequence text, DialogInterface.OnClickListener listener) : 响应Yes/Ok的点击 ;

setNegativeButton(CharSequence text, DialogInterface.OnClickListener listener) :响应No/Cancel的点击 ;

create() : 创建对话框 ;

show() : 显示对话框;

一般情况下,使用系统已有的方法就足够了,这能够胜任大部分的需求,效果图如下:

对话框样例(源自百度图片)

当我们需要显示单选框或者复选框时,可以通过setView将内容部分更换为需要的View:

//layoutId是布局文件的id号。
View view=LayoutInflater.from(context).inflate(layoutId,ViewGroup);
builder.setView(view);
builder.show();

2、等待框&进度框:ProgressDialog

ProgressDialog是通过把ProgeressBar引入dialog封装成的对话框,它可以直接new出新的对象,需要传入一个context参数。ProgressDialog还有一个构造方法

public ProgressDialog(Context context,int theme);

第二个参数表示ProgressDialog的样式,一般默认为圆形,效果如图:
这里写图片描述

还可以设置为水平样式

public static final int STYLE_HORIZONTAL;

如下图:
这里写图片描述
进度显示可以通过设置当前值和最大值来确定:

setMax() 设置进度条最大的值;
getMax()
setProgress() 设置当前进度条的值。
getProgress()

3、时间、日期选择框——TimePickerDialog、DatePickerDialog

日期和时间Dialog类似,以TimePickerDialog为例。

(DatePickerDialog中月份是从0开始计算,即month为0表示1月份)

TimePickerDialog一般用来设置定时提醒:

//将hour和minutes设为类的成员
private int hour,minutes;
...
new TimePickerDialog(this, new TimePickerDialog.OnTimeSetListener() {
    @Override
    public void onTimeSet(TimePicker view, int hourOfDay, int minute){
        //获取设置的时间
        this.hour=hourOfDay;
        this.minutes=minute;
    }
},0,0,true).show();

2、Dialog进阶——自定义AlertDialog

AlertDialog对象的 setView方法将自定义布局view加载到dialog内容显示区域,但标题等部分还是会显示出来;因此若想要完全自定义Dialog显示效果,需要使用setContentView;两者区别如下:

  • setview 是将 message 处的布局替换为 view
  • setContentView 是将整个对话框替换为 view

自定义AlertDialog显示效果,需要先设计界面布局
XML布局:dialog.xml

<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:orientation="horizontal"
          android:layout_width="wrap_content"
            android:rowCount="2"
            android:columnCount="4"
            android:background="#00ff00"
            android:layout_gravity="center"
            android:alpha="100"
            android:padding="0dp"
            android:layout_height="wrap_content">

    <LinearLayout
        android:orientation="vertical">
        <ImageView
            android:clickable="true"
            android:id="@+id/sizeSmall"
            android:layout_width="62dp"
            android:layout_height="42dp"/>
        <TextView
            android:gravity="center"
            android:text="字体-"
            android:layout_width="62dp"
            android:layout_height="20dp"/>
            />
    </LinearLayout>
    <LinearLayout
        android:orientation="vertical">
        <ImageView
            android:clickable="true"
            android:id="@+id/sizeLarge"
            android:layout_width="62dp"
            android:layout_height="42dp"/>
        <TextView
            android:text="字体+"
            android:gravity="center"
            android:layout_width="62dp"
            android:layout_height="20dp"/>
        />
    </LinearLayout>
    <LinearLayout
        android:orientation="vertical">
        <ImageView
            android:clickable="true"
            android:id="@+id/lightDecrease"
            android:layout_width="62dp"
            android:layout_height="42dp"/>
        <TextView
            android:gravity="center"
            android:text="亮度-"
            android:layout_width="62dp"
            android:layout_height="20dp"/>
        />
    </LinearLayout>
    <LinearLayout
        android:orientation="vertical">
        <ImageView
            android:clickable="true"
            android:id="@+id/lightIncrease"
            android:layout_width="62dp"
            android:layout_height="42dp"/>
        <TextView
            android:text="亮度+"
            android:gravity="center"
            android:layout_width="62dp"
            android:layout_height="20dp"/>
        />
    </LinearLayout>

    <LinearLayout
        android:orientation="vertical">
        <ImageView
            android:clickable="true"
            android:id="@+id/edit"
            android:layout_width="62dp"
            android:layout_height="42dp"/>
        <TextView
            android:text="编辑"
            android:gravity="center"
            android:layout_width="62dp"
            android:layout_height="20dp"/>
        />
    </LinearLayout>
    <LinearLayout
        android:orientation="vertical">
        <ImageView
            android:clickable="true"
            android:id="@+id/toPdf"
            android:layout_width="62dp"
            android:layout_height="42dp"/>
        <TextView
            android:text="pdf"
            android:gravity="center"
            android:layout_width="62dp"
            android:layout_height="20dp"/>
        />
    </LinearLayout>
    <LinearLayout
        android:orientation="vertical">
        <ImageView
            android:clickable="true"
            android:id="@+id/exit"
            android:layout_width="62dp"
            android:layout_height="42dp"/>
        <TextView
            android:text="退出"
            android:gravity="center"
            android:layout_width="62dp"
            android:layout_height="20dp"/>
        />
    </LinearLayout>
    <LinearLayout
        android:orientation="vertical">
        <ImageView
            android:clickable="true"
            android:id="@+id/save"
            android:layout_width="62dp"
            android:layout_height="42dp"/>
        <TextView
            android:text="保存"
            android:gravity="center"
            android:layout_width="62dp"
            android:layout_height="20dp"/>
        />
    </LinearLayout>
</GridLayout>

现有一需求,需要让弹出的菜单栏在屏幕中间,大小为wrap_content,现在就自定义dialog来满足需求:

AlertDialog.Builder builder=new AlertDialog.Builder(this);
//设置提示框可取消
builder.setCancelable(true);
//加载需要显示的布局文件
View view=getLayoutInflater().inflate(R.layout.menu_dialog,null);
AlertDialog dialog=builder.create();
//这里要确保show方法调用在setContentView方法之前
dialog.show();
Window window=dialog.getWindow();
WindowManager.LayoutParams lp=window.getAttributes();
// 设置不透明度,取值0-11表示不透明
lp.alpha = 0.8f; 
window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
window.setGravity(Gravity.CENTER);
window.setAttributes(lp);
//自定义Dialog时不能使用已有的setTitle等方法;否则会空指针异常
dialog.setContentView(view);

自定义dialog显示效果:
这里写图片描述

3、Dialog定制全屏显示——顶部进度框,底部菜单栏

Dialog类与AlertDialog相比,没有多余需要显示的部分,因此实现全屏效果时,应直接继承Dialog 类。

一般系统会强行为Dialog添加某些约束,例如无法完全占满屏幕Width等,因此需要自定义Theme布局,来确保Dialog拥有与Activity相同的整个屏幕:

/res/values/styles.xml中添加如下样式

<style name="ActivityBottomView">
    <item name="android:windowFullscreen">true</item>
    <item name="android:windowFrame">@null</item>
    <item name="android:windowIsFloating">true</item>
    <item name="android:windowNoTitle">true</item>
    <item name="android:background">@android:color/transparent</item>
    <item name="android:backgroundDimEnabled">true</item>
    <item name="android:backgroundDimAmount">0.6</item>
</style>

<style name="ActivityBottomViewAnimation">
    <item name="android:windowEnterAnimation">@anim/dialog_activity_menu_enter</item>
    <item name="android:windowExitAnimation">@anim/dialog_activity_menu_exit</item>
</style>

<style name="ActivityTopViewAnimation">
    <item name="android:windowEnterAnimation">@anim/dialog_activity_top_enter</item>
    <item name="android:windowExitAnimation">@anim/dialog_activity_top_exit</item>
</style>

backgroundDimEnabled为true表示开启遮罩窗体,在Dialog弹出后,没有被Dialog遮挡的部分会有半透明效果,backgroundDimAmount用于设置半透明度

新建如下动画效果,保证顶部进度框与底部菜单栏可以平滑的进入和退出

/res/dialog_activity_menu_enter.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:duration="300"
        android:fromYDelta="100%"
        android:toYDelta="0"/>
</set>

/res/dialog_activity_menu_exit.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:duration="300"
        android:fromYDelta="0"
        android:toYDelta="100%"/>
</set>

/res/dialog_activity_top_enter.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:duration="300"
        android:fromYDelta="-100%"
        android:toYDelta="0"/>
</set>

/res/dialog_activity_top_exit.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:duration="300"
        android:fromYDelta="0"
        android:toYDelta="-100%"/>
</set>

1、底部菜单栏:ActivityBottomView

public class ActivityBottomView extends Dialog {
    private static final String TAG = "ActivityBottomView";

    private Context context;
    private View dialogView;

    /**
     * @param context 上下文
     * @param View 需要在底部显示的视图
     */
    public ActivityBottomView(Context context,View dialogView) {
        super(context, R.style.ActivityBottomView);
        //调用该方法,保证菜单栏Width可以充满整个屏幕
        setOwnerActivity((Activity)context);
        this.context = context;
        this.dialogView=dialogView;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public void show() {
        super.show();
        Window window = getWindow();
        WindowManager.LayoutParams params = window.getAttributes();
        params.alpha = 1F;
        //这标志表示含义为:所有在该弹出框后的内容都将模糊不清,即显示遮罩窗体
        params.flags = WindowManager.LayoutParams.FLAG_DIM_BEHIND;
        window.setAttributes(params);
        window.setGravity(Gravity.BOTTOM);
        window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
        window.setLayout(WindowManager.LayoutParams.MATCH_PARENT,WindowManager.LayoutParams.WRAP_CONTENT);
        window.setDimAmount(0.35F);
        window.setWindowAnimations(R.style.ActivityBottomViewAnimation);
        setContentView(dialogView);
    }
}

2、顶部进度框:ActivityTopProgress

public class ActivityTopProgress extends Dialog {
    private static final String TAG = "ActivityTopProgress";

    private Context context;
    private View dialogView;
    private ImageView iv_animator;
    private TextView tv_message;
    private ImageView iv_divider;
    private RotateAnimation animator;

    /**
     * @param context 上下文
     */
    public ActivityTopProgress(Context context) {
        super(context, R.style.ActivityBottomView);
        setOwnerActivity((Activity) context);
        this.context = context;
        this.dialogView = LayoutInflater.from(context).inflate(R.layout.layout_top_progress, null);
        this.iv_animator = (ImageView) this.dialogView.findViewById(R.id.iv_animator);
        this.tv_message = (TextView) this.dialogView.findViewById(R.id.tv_message);
        this.iv_divider = (ImageView) this.dialogView.findViewById(R.id.iv_divider);
        //针对ImageView开启一个自定义的旋转效果
        this.animator = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5F, Animation
            .RELATIVE_TO_SELF, 0.5F);
        this.animator.setDuration(1 * 1000);
        this.animator.setRepeatCount(Animation.INFINITE);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public void show() {
        super.show();
        //获取顶部statusBar的高度
        int paddingTop = ActivityUtil.getStatusBarHeightPixels(context);
        //设置iv_divider高度等于状态栏statusBar高度
        iv_divider.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
            paddingTop));
        Window window = getWindow();
        WindowManager.LayoutParams params = window.getAttributes();
        params.alpha = 1F;
        params.flags = WindowManager.LayoutParams.FLAG_DIM_BEHIND;
        window.setAttributes(params);
        window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
        window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
        window.setGravity(Gravity.TOP);
        window.setLayout(WindowManager.LayoutParams.MATCH_PARENT,WindowManager.LayoutParams.WRAP_CONTENT);
        window.setDimAmount(0.35F);
        window.setWindowAnimations(R.style.ActivityTopViewAnimation);
        window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
        setContentView(dialogView);
        iv_animator.startAnimation(animator);
    }

    public void setMessage(CharSequence message) {
        tv_message.setText(message);
    }

    @Override
    public void dismiss() {
        super.dismiss();
        iv_animator.clearAnimation();
    }
}

进度框对应的/res/layout/layout_top_progres.xml文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:orientation="vertical"
    android:layout_height="wrap_content">

    <ImageView
        android:background="@color/white"
        android:id="@+id/iv_divider"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:gravity="center_vertical"
        android:orientation="horizontal">

        <ImageView
            android:id="@+id/iv_animator"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@mipmap/ic_volume_bluetooth_in_call"/>

        <TextView
            android:layout_marginLeft="@dimen/activity_horizontal_margin"
            android:id="@+id/tv_message"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="start"/>
    </LinearLayout>
</LinearLayout>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值