一 使用背景: 传统的对话框位置 主题风格受系统影响 为了满足我们的UI需求 我们可以自行定义对话框。
二 使用步骤原理
1 自定义主题风格(一般的对话框主题都为无边框全透明)
2 写xml布局(自定义对话框要展示的界面内容)
3 继承Dialog类编写相关的逻辑(一般提供 点击事件回调)
4 位置的摆放问题
5总结 一般通过构造函数 传参数为对话框的样式主题 为对话框设置主题
setContentView中传我们自己的布局 我们就可以编写自己的dialog布局界面了
三 下面提供一个简单的具体实现的Demo
1 首先写个自定义类继承Dialog即可,实现构造。
2 创建自己的样式
<!--自定义dialog背景全透明无边框theme -->
<style name="MyDialog" parent="android:style/Theme.Dialog">
<!--背景颜色及和透明程度-->
<item name="android:windowBackground">@android:color/transparent</item>
<!--是否去除标题 -->
<item name="android:windowNoTitle">true</item>
<!--是否去除边框-->
<item name="android:windowFrame">@null</item>
<!--是否浮现在activity之上-->
<item name="android:windowIsFloating">true</item>
<!--是否模糊-->
<item name="android:backgroundDimEnabled">false</item>
</style>
3 创建一个简单的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:background="@android:color/transparent"
android:gravity="center">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/dialog_bg"
android:orientation="vertical"
android:gravity="center">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="5dp"
android:text="权限申请"
android:textColor="@android:color/holo_blue_light"
android:textSize="20sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="15dp"
android:text="我需要申请您的网络权限"
android:textColor="@android:color/darker_gray"
android:textSize="20sp" />
<LinearLayout
android:layout_marginTop="30dp"
android:layout_gravity="bottom"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:id="@+id/btn_refuse"
android:text="拒绝"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"/>
<Button
android:id="@+id/btn_accept"
android:text="同意"
android:textColor="@android:color/holo_blue_light"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
4 具体的逻辑实现
package com.example.zhangbiao.customdialog.MyDialog;
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import com.example.zhangbiao.customdialog.R;
/**
* Created by 晴天 on 2018/7/30
*/
public class CustomDialog extends Dialog {
private Context mContext;
private Button mBtnRefuse;
private Button mBtnAccept;
private OnAcceptClickListener onAcceptClistenter;
private OnRefuseClickListener onRefuseClickListener;
/*
*一个参数的构造函数 new时传一个参数上下文时被调用
* */
public CustomDialog(@NonNull Context context) {
super(context, R.style.MyDialog);// 此处为了方便直接调用父类的2参数构造吧主题传过去
getLayout();
initUI();
initData();
}
/*
*
*第二个参数 主题的资源id 一般情况下我们调用对话框时 传递上下文 主题即可
*/
public CustomDialog(@NonNull Context context, int themeResId) {
super(context, themeResId);
mContext = context;
getLayout();
initUI();
initData();
}
/*
*第三个参数 关闭对话框的接口
*/
protected CustomDialog(@NonNull Context context, boolean cancelable, @Nullable OnCancelListener cancelListener) {
super(context, cancelable, cancelListener);
mContext = context;
getLayout();
initUI();
initData();
}
// (此方法在你调用dialog的show()方法时被调用)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
/*
* 获得布局
* */
private void getLayout() {
// 加载我们自己的布局文件
setContentView(R.layout.dialog_custom);
}
/*
* 初始化UI控件
* */
private void initUI() {
// 指定对话框的位置
Window win = getWindow();
win.setGravity(Gravity.TOP);// 默认为居中显示
// 找控件
mBtnRefuse = findViewById(R.id.btn_refuse);
mBtnAccept = findViewById(R.id.btn_accept);
}
/*
* 逻辑的相关操作
* */
private void initData() {
mBtnAccept.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
onAcceptClistenter.onClick();
}
});
mBtnRefuse.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
onRefuseClickListener.click();
}
});
}
/*
* 接受按钮的点击事件
* */
public void OnAcceptClistenter(OnAcceptClickListener onAcceptClistenter) {
if (onAcceptClistenter != null) {
this. onAcceptClistenter = onAcceptClistenter;
}
}
/*
* 拒绝按钮的回调
* */
public void OnRefuseClickListener(OnRefuseClickListener onRefuseClickListener) {
if (onRefuseClickListener != null) {
this.onRefuseClickListener = onRefuseClickListener;
}
}
/*
* 对外部对话框提供点击事件回调
* */
public interface OnRefuseClickListener {
void click();
}
public interface OnAcceptClickListener {
void onClick();
}
}
主activity中调用
package com.example.zhangbiao.customdialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Toast;
import com.example.zhangbiao.customdialog.MyDialog.CustomDialog;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/*
* 自定义对话框
* 一 使用背景: 传统的对话框位置 主题风格受系统影响 为了满足我们的UI需求 自行定义对话框样式
*
* 二 使用步骤原理
* 1 自定义主题风格(一般的对话框主题都为无边框全透明)
* 2 写xml布局(自定义对话框要展示的界面内容)
* 3 继承Dialog类编写相关的逻辑(一般提供 点击事件回调)
*
* 4 位置的摆放问题
*
* 5总结 一般通过构造函数 传参数为对话框的样式主题 为对话框设置主题
* setContentView中传我们自己的布局 我们就可以编写自己的dialog布局界面了
* */
final CustomDialog dialog = new CustomDialog(this);
dialog.show();
dialog.OnAcceptClistenter(new CustomDialog.OnAcceptClickListener() {
@Override
public void onClick() {
Toast.makeText(MainActivity.this, "非常好您接受了权限!!!", Toast.LENGTH_SHORT).show();
// TODO 相关逻辑处理
dialog.dismiss();
}
});
dialog.OnRefuseClickListener(new CustomDialog.OnRefuseClickListener() {
@Override
public void click() {
Toast.makeText(MainActivity.this, "很遗憾您拒绝了权限!!!", Toast.LENGTH_SHORT).show();
// TODO 相关逻辑处理
dialog.dismiss();
}
});
}
}
简单的运行结果:
四 一些坑:
你也许会不满意当前的对话框的摆放位置,但是你会发现,类无论你在布局文件中设置matchparent 还是wrapcontent,对话框的大小竟然没有变化,但是你给布局设置具体的数值的时候,布局会变换的不是你原来的样子。变样子了。此时我们应该使用系统提供的api(window对象及布局参数)设置对话框的位置,大小。
1 首先如果我们使用默认大小的对话框时,如果想要指定摆放位置可以使用Window的setGravity()简单的变化位置
如下:
private void initUI() {
// 指定对话框的位置
Window win = getWindow();
win.setGravity(Gravity.BOTTOM);// 默认为居中显示
// 找控件
mBtnRefuse = findViewById(R.id.btn_refuse);
mBtnAccept = findViewById(R.id.btn_accept);
}
当然你也可以使用这个api 他的内部是通过布局参数改变位置的
// 指定对话框的位置
Window win = getWindow();
win.setGravity(Gravity.BOTTOM);// 默认为居中显示
WindowManager.LayoutParams lp = win.getAttributes();
//不设置lp.width 和lp.height,对话框大小由布局决定
// lp.width = 525; //大小
// lp.height =330;
//自定义位置
lp.x = 30;
lp.y = 30;
lp.gravity = Gravity.LEFT | Gravity.TOP;//不设置这个时,lp.x和lp.y无效
//window.setGravity(Gravity.CENTER);//居中显示
win.setAttributes(lp);
实现结果:
注意此处你的width height付值 的时候要进行dp到px转换。