我的世界服务器配置文件

server.properties配置文件

generator-settings=					#井号开头的内容为注释
op-permission-level=4				#op权限等级 
allow-nether=true					#允许末地 
level-name=world					#主世界文件夹名称 
enable-query=false					#是否开启GameSpy4协议服务器监听器
allow-flight=true					#是否允许飞行 
announce-player-achievements=true	#公布玩家成就信息 
server-port=25566					#服务器端口 
level-type=DEFAULT					#世界类型 
enable-rcon=false					#是否开启rcon监听
force-gamemode=false				#force游戏模式
level-seed=							#服务器种子 
server-ip=192.168.19.32				#服务器指向ip
max-build-height=256				#建筑*大高度 
spawn-npcs=false					#是否有主城NPC 
white-list=false					#是否开启白名单 
spawn-animals=true					#是否允许动物生成 
hardcore=false						#是否开启*限模式
snooper-enabled=false				#是否给snoop.minecraft.net网站发送服务器数据,推荐关闭
online-mode=false					#是否联网游戏(非正版一定要改false) 
resource-pack=						#服务器资源包下载地址
pvp=true							#是否开启pvp 
difficulty=3						#服务器难度 和平0~3困难(自行调整)
enable-command-block=true			#是否开启命令方块 
server-name=Server					#服务器名称 
gamemode=0							#游戏模式 
player-idle-timeout=0				#服务器*长挂机时间 
max-players=20						#*大玩家数 
spawn-monsters=true					#是否允许生成怪物 
generate-structures=true			#是否生成建筑物
view-distance=10					#可见距离 
motd=Server							#服务器标语 

Android中的Dialog的使用以及自定义Dialog

在安卓开发中,我们会在某些特定的事件前面用来提示用户是否真的需要这样操作,避免因为用户误触而导致的一些不可逆的操作,而在处理这种事件
的一种方式就是用Dilaog来 让用户确定自己的操作。

Dilaog的布局分为上、中、下三个块,上为显示标题和图标的位置,中间显示的内容,下面显示的是操作的按钮。

官方给我们提供的AlertDialog 这个类,它不仅能创建带按钮的提示对话框,还可以生产带列表的对话框,总来的来说有以下四种情况:
1.带“确定”、“取消”,“中立”等几个按钮的提示框,其中按钮数量不固定,根据需要去添加。
2.带列表的对话框。
3.带单选列表项的对话框。
4.带多选列表项的对话框。

那么我们先来看*种情况:显示一个**常规**的对话框

new AlertDialog.Builder(this).setIcon(android.R.drawable.btn_star)
.setTitle(“这个是标题”).setMessage(“你有对象吗?”)
.setPositiveButton(“有”,new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,int which) {
Toast.makeText(MainActivity.this, “恭喜你”, Toast.LENGTH_SHORT).show();
dialog.dismiss();
}
})
.setNeutralButton(“保密”,new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,int which) {
Toast.makeText(MainActivity.this, “装逼,一看就是单身狗”, Toast.LENGTH_SHORT).show();
dialog.dismiss();
}
})
.setNegativeButton(“没有”,new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,int which) {
Toast.makeText(MainActivity.this, “那你还写个毛代码”, Toast.LENGTH_SHORT).show();
dialog.dismiss();
}
}).show();// show很关键

这样就弹出了一个基本的对话框,有三个按钮,有内容,有标题和标题图标。在这里如果你是5.0版本一下引用的是“android.app.AlertDialog”这个
包,那么三个按钮是weight为1:1:1的比例显示的。如果你引用的是“android.support.v7.app.AlertDialog”这个包的话,
那么两个确认的按钮在右边显示,中立的“保密”按钮会在左边显示。一般情况下我们只有两个按钮,我们首选v7包下的对话框显示,毕竟这是一个看脸的年代。

如果是5.0及以上版本都显示的是图2
%title插图%num

我们先来看第二种情况:显示一个带**列表**的对话框

final String itemContent[] = new String[]{“李宇春”,”王尼玛”,”罗玉凤”,”林志玲”};

new AlertDialog.Builder(this).setIcon(android.R.drawable.btn_star)
.setTitle(“你选对象的标准是什么?”).setItems(itemContent, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int i) {
Toast.makeText(MainActivity.this, “你喜欢”+itemContent[i], Toast.LENGTH_SHORT).show();
dialog.dismiss();
}
}).show();// show很关键

在这里需要说明的是对于dialog中内容的设置,如setMessage(),setItems(),setItemchoice()是有优先级的,如果你同时设置了三种,或者其中的两种,
如果有setMessage(),那么就只会显示你设置的message的内容,而另外设置的Items()或者ItemsChoice()中的内容不会显示,因为setMessage的优先级是*高的,
而且这三种显示内容的方式是并列的关系,就是只能选择一直方式展示对话框中间部分的内容。
%title插图%num

我们来看第三种情况:显示一个带**单选**的对话框

final String itemContent[] = new String[]{“李宇春”, “王尼玛”, “罗玉凤”, “林志玲”};
str = itemContent[0];//str为一个全局变量的字符串,用来在点击确定时候获取选中的值
new AlertDialog.Builder(this)
.setIcon(android.R.drawable.btn_star)
.setTitle(“你选对象的标准是什么?”).setSingleChoiceItems(itemContent, 0, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int i) {
str = itemContent[i];
}
}).setNegativeButton(“取消”, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int i) {
dialog.dismiss();
}
}).setPositiveButton(“确定”, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int i) {
Toast.makeText(MainActivity.this, “你喜欢” + str, Toast.LENGTH_SHORT).show();
dialog.dismiss();
}
})
.show();

 

我们来看第四种情况:显示一个带**单选**的对话框

final String itemContent[] = new String[]{“李宇春”, “王尼玛”, “罗玉凤”, “林志玲”};
final boolean checkedItems[] = new boolean[itemContent.length];//创建一个和可选项长度相同的数组记录选中项

new AlertDialog.Builder(this)
.setIcon(android.R.drawable.btn_star)
.setTitle(“你选对象的标准是什么?”).setMultiChoiceItems(itemContent, checkedItems, new DialogInterface.OnMultiChoiceClickListener() {
@Override
public void onClick(DialogInterface dialog, int i, boolean b) {
checkedItems[i] = b;
}
}).setNegativeButton(“取消”, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int i) {
dialog.dismiss();
}
}).setPositiveButton(“确定”, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int i) {
String str = getChoose(itemContent, checkedItems);
if (str.equals(“请至少选则一个项目”)) {
Toast.makeText(MainActivity.this, str, Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(MainActivity.this, str, Toast.LENGTH_SHORT).show();
dialog.dismiss();
}

}
})
.show();

private String getChoose(String[] itemContent, boolean[] checkedItems) {
String strChoose = “”;//接收选中的字符串
for (int i = 0; i < checkedItems.length; i++) {
if (checkedItems[i]) {//如果是选中则将其拼接到strChoose后
strChoose += TextUtils.concat(itemContent[i], “,”).toString();
}
}
//返回字符串前判断字符串长度是否大于0(即是否有选中的),有则返回选中的,没有则应该提示不能选中空的
if (strChoose.length() > 0) {
//去掉*末尾的逗号
strChoose = TextUtils.concat(“你选中了:”, strChoose.substring(0, strChoose.length() – 1)).toString();
} else {
strChoose = “请至少选则一个项目”;
}
return strChoose;
}
%title插图%num

我们用我们自己写的布局替换系统Dilaog的布局:

View dialogView = LayoutInflater.from(this).inflate(R.layout.my_dialog, null);//解析我们自己写的布局
final Dialog dialog = new AlertDialog.Builder(this).create();//创建一个dialog
dialog.show();//此处dialog应该先show然后再加载布局,否则会报错
dialog.setContentView(dialogView);
//初始化控件
ImageView mImage = (ImageView) dialogView.findViewById(R.id.dialog_title_image);
TextView mTitle = (TextView) dialogView.findViewById(R.id.dialog_title_content);
TextView mMessage = (TextView) dialogView.findViewById(R.id.dialog_message_text);
Button mCancelBtn = (Button) dialogView.findViewById(R.id.dialog_cancel_button);
Button mEnsureBtn = (Button) dialogView.findViewById(R.id.dialog_ensure_button);
mImage.setBackgroundResource(R.mipmap.ic_launcher);
mTitle.setText(“这是标题”);
mMessage.setText(“这是内容”);
mCancelBtn.setText(“取消”);
mEnsureBtn.setText(“确定”);
mCancelBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(MainActivity.this, “取消”, Toast.LENGTH_SHORT).show();
dialog.dismiss();
}
});
mEnsureBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(MainActivity.this, “确定”, Toast.LENGTH_SHORT).show();
dialog.dismiss();
}
});

布局文件的代码为:(xml名称为:my_dialog)
<?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=”40dp”
android:orientation=”horizontal”>

<ImageView
android:id=”@+id/dialog_title_image”
android:layout_width=”30dp”
android:layout_height=”30dp”
android:layout_gravity=”center_vertical”
android:layout_marginLeft=”10dp” />

<TextView
android:id=”@+id/dialog_title_content”
android:layout_width=”wrap_content”
android:layout_height=”match_parent”
android:gravity=”center_vertical” />
</LinearLayout>

<TextView
android:id=”@+id/dialog_message_text”
android:layout_width=”match_parent”
android:layout_height=”wrap_content”
android:layout_margin=”10dp”
android:padding=”10dp” />

<LinearLayout
android:layout_width=”match_parent”
android:layout_height=”40dp”
android:orientation=”horizontal”>

<Button
android:id=”@+id/dialog_ensure_button”
android:layout_width=”0dp”
android:layout_height=”match_parent”
android:layout_weight=”1″ />

<Button
android:id=”@+id/dialog_cancel_button”
android:layout_width=”0dp”
android:layout_height=”match_parent”
android:layout_weight=”1″ />
</LinearLayout>

</LinearLayout>
%title插图%num

Flutter项目在 iOS14 启动崩溃

Flutter项目在 iOS14 启动崩溃
崩溃现象
崩溃分析
解决方法
崩溃现象
在iOS14发布之后,运行APP就出现闪退,和机型没关,只要是iOS 14就必闪退

崩溃分析
1、启动就闪退,多起几次可能有一次没有问题。
2、启动后到某个页面卡死(必卡跳不过)
根本原因尚不明确,个人分析Product Name会影响Header Folder Path,可能是代码加载路径中出现中文会出问题。

解决方法
Xcode里,选择当前项目的TARGETS->BuildSetting -> Packaging -> Product Name,将中文的命名改成英文,flutter项目建议直接改成Runner。

%title插图%num

希望以上方案能帮到大家~~~

Android 安卓自定义Dialog工具类封装与使用

Android 安卓Dialog工具类封装与使用
安卓自定义Dialog,分别用了Kotlin和Java两种语言列出!布局可以自定义!

效果图
布局是自定义的

配置
style.xml中配置

<style name=”BoxDialog” parent=”@android:style/Theme.Holo.Dialog”>
<!– 是否有边框 –>
<item name=”android:windowFrame”>@null</item>
<!–是否在悬浮Activity之上 –>
<item name=”android:windowIsFloating”>true</item>
<!– 标题 –>
<item name=”android:windowNoTitle”>true</item>
<!–阴影 –>
<item name=”android:windowIsTranslucent”>true</item>
<!–背景透明–>
<item name=”android:windowBackground”>@android:color/transparent</item>
<!–可加入动画–>
</style>

Java
/**
* @author ThirdGoddess
* @email ofmyhub@gmail.com
* @Github https://github.com/ThirdGoddess
* @date :2019-12-29 01:24
*/
public class BoxDialog extends Dialog {

//Dialog View
private View view;

//Dialog弹出位置
private LocationView locationView = LocationView.CENTER;

/**
* @param context 上下文
* @param view Dialog View
*/
public BoxDialog(Context context, View view) {
super(context, R.style.BoxDialog);
this.view = view;
}

/**
* @param context 上下文
* @param view Dialog View
* @param locationView Dialog弹出位置
*/
public BoxDialog(Context context, View view, LocationView locationView) {
super(context, R.style.BoxDialog);
this.view = view;
this.locationView = locationView;
}

@SuppressLint(“RtlHardcoded”)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (null != view) {
setContentView(view);
setCancelable(isCancelable);//点击外部是否可以关闭Dialog
setCanceledOnTouchOutside(isCanceledOnTouchOutside);//返回键是否可以关闭Dialog
Window window = this.getWindow();
assert window != null;
switch (locationView) {
case TOP:
window.setGravity(Gravity.TOP);
break;
case BOTTOM:
window.setGravity(Gravity.BOTTOM);
break;
case CENTER:
window.setGravity(Gravity.CENTER);
break;
}
WindowManager.LayoutParams params = window.getAttributes();
params.width = WindowManager.LayoutParams.MATCH_PARENT;
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
window.setAttributes(params);
}
}

public enum LocationView {
CENTER, TOP, BOTTOM
}
}

Kotlin
/**
* @author ThirdGoddess
* @email ofmyhub@gmail.com
* @Github https://github.com/ThirdGoddess
* @date :2019-12-29 01:24
*/
class BoxDialog : Dialog {

//Dialog View
private var view: View?

//Dialog弹出位置
private var locationView = LocationView.CENTER

/**
* @param context 上下文
* @param view Dialog View
*/
constructor(context: Context?, view: View?) : super(context!!, R.style.MyDialog) {
this.view = view
}

/**
* @param context 上下文
* @param view Dialog View
* @param locationView Dialog弹出位置
*/
constructor(context: Context?, view: View?, locationView: LocationView) : super(context!!, R.style.MyDialog) {
this.view = view
this.locationView = locationView
}

@SuppressLint(“RtlHardcoded”)
override fun onCreate(savedInstanceState: Bundle) {
super.onCreate(savedInstanceState)
if (null != view) {
setContentView(view!!)
setCancelable(isCancelable) //点击外部是否可以关闭Dialog
setCanceledOnTouchOutside(isCanceledOnTouchOutside) //返回键是否可以关闭Dialog
val window = this.window!!
when (locationView) {
LocationView.TOP -> window.setGravity(Gravity.TOP)
LocationView.BOTTOM -> window.setGravity(Gravity.BOTTOM)
LocationView.CENTER -> window.setGravity(Gravity.CENTER)
}
val params = window.attributes
params.width = WindowManager.LayoutParams.MATCH_PARENT
params.height = WindowManager.LayoutParams.WRAP_CONTENT
window.attributes = params
}
}

enum class LocationView {
CENTER, TOP, BOTTOM
}
}

使用方法
Java 和 Kotlin 的方法

Java
public class MainActivity extends AppCompatActivity {

private BoxDialog boxDialog;

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

private void initView() {
Button dialogButton = findViewById(R.id.dialog);
dialogButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
View inflate = LayoutInflater.from(MainActivity.this).inflate(R.layout.dialog_view2, null, false);
//在这里可以给布局中的按钮加事件,boxDialog.dismiss()可以关闭dialog

boxDialog = new BoxDialog(MainActivity.this, inflate, BoxDialog.LocationView.CENTER);
boxDialog.setCancelable(false);//是否可以点击DialogView外关闭Dialog
boxDialog.setCanceledOnTouchOutside(false);//是否可以按返回按钮关闭Dialog
boxDialog.show();
}
});
}

}

Kotlin
class MainActivity : AppCompatActivity() {
private var boxDialog: BoxDialog? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
initView()
}

private fun initView() {
val dialogButton = findViewById<Button>(R.id.dialog)
dialogButton.setOnClickListener {
val inflate = LayoutInflater.from(this).inflate(R.layout.dialog_view2, null, false)
//可以给布局中的按钮加事件,boxDialog.dismiss();关闭dialog

boxDialog = BoxDialog(this, inflate, BoxDialog.LocationView.CENTER)
boxDialog!!.setCancelable(false) //是否可以点击DialogView外关闭Dialog
boxDialog!!.setCanceledOnTouchOutside(false) //是否可以按返回按钮关闭Dialog
boxDialog!!.show()
}
}
}

Android 自定义Dialog实现步骤及封装

在项目中,我们会遇到各种各样的界面需求,比如对话框和选择框,都是会配合具体项目的UI界面来做,而不是说用自带的弹出框。比如下面在登录界面的二个对话框效果。都是我在做具体项目中所要求实现的:

1.输入有误时弹出的对话框

%title插图%num

2.选择角色登录时的对话框

%title插图%num

这里倒不是说自定义Dialog的教程,因为自定义Dialog大家基本都会。只是我在登录界面写了这二个Dialog之后,我就觉得好烦,然后决定封装了一个类,因为后面不同界面还有很多不同的弹框。为后期节省时间。倒不是说我这个封装类写的有多好,只是写出来,大家可以看下,然后哪里不好可以跟我提下意见。

让我们一步步来看是如何自定这个自定义对话框及如何来进行封装自己的自定义Dialog工具类。我就按照实际项目中,我的开发步骤来说明。

如何生成这种自定义对话框

实际开发中,我看到了*个效果图中的对话框,于是我马上大手一挥,自定义了一个类ErrorDialog,继承了Dialog。

  1. public class ErrorDialog extends Dialog{
  2. public ErrorDialog(Context context) {
  3. super(context);
  4. }
  5. public ErrorDialog(Context context, int themeResId) {
  6. super(context, themeResId);
  7. }
  8. protected ErrorDialog(Context context, boolean cancelable
  9. , OnCancelListener cancelListener) {
  10. super(context, cancelable, cancelListener);
  11. }
  12. }

我们可以看到有三个构造函数,这三个构造函数不是一定要都实现,但至少要实现一个构造函数。我们来具体说明下各个构造函数的作用。

  1. ErrorDialog(Context context):
    单纯传入Context,用的比较多。在代码中通过new ErrorDialog(context);来获得Dialog的实例,然后使用show()方法进行展现。

  2. ErrorDialog(Context context, int themeResId)
    大家可以看到比*个构造函数多了一个themeResId,就是我们可以传入一个主题值,比如R.style.XXX。然后构造函数中会调用super(context, themeResId);等会生成的Dialog就会带有这个R.style.XXX所设置的效果。

  3. ErrorDialog(Context context, boolean cancelable, OnCancelListener cancelListener):
    大家都知道,对话框弹出来后,默认情况下,我们在屏幕上触摸对话框以外的屏幕的界面,对话框会默认消失。我们平时做对话框的时候一般都是让这个对话框点击外面的其他界面地方的时候不让对话框消失,我们一般在代码中会这么写:setCanceledOnTouchOutside(false);。为什么我提这个,没错,这个构造函数里面的那个boolean cancelable控制的就是这个功能,<1>当传入为true的时候,就是可以点击外面来让对话框消失,然后消失的时候会调用后面第三个参数的cancelListener这个listener里面的方法。我们可以在里面做相应的监听事件。<2>当传入false。那么点击外面区域,这个对话框也就不会消失,而且后面的那个listener也不会被调用。

好了,构造函数说好后。我们来具体看如何生成界面Dialog界面。于是我大手再次一挥。写了个对话框所需要的效果的Layout:

  1. <?xml version=”1.0″ encoding=”utf-8″?>
  2. <LinearLayout xmlns:android=“http://schemas.android.com/apk/res/android”
  3. android:layout_width=“200dp”
  4. android:layout_height=“250dp”
  5. android:background=“@drawable/background_loginerror”
  6. android:gravity=“center_horizontal”
  7. android:orientation=“vertical”>
  8. <ImageView
  9. android:layout_marginTop=“30dp”
  10. android:layout_width=“80dp”
  11. android:layout_height=“80dp”
  12. android:src=“@drawable/gong”
  13. />
  14. <TextView
  15. android:layout_marginTop=“20dp”
  16. android:layout_width=“wrap_content”
  17. android:layout_height=“wrap_content”
  18. android:text=“您输入的内容有误”
  19. />
  20. <Button
  21. android:id=“@+id/btn_cancel”
  22. android:layout_marginTop=“20dp”
  23. android:layout_width=“120dp”
  24. android:layout_height=“40dp”
  25. android:text=“@string/confirm”
  26. android:background=“@drawable/background_loginbtn”
  27. />
  28. </LinearLayout>

效果如下图所示(那个感叹号的图片我这边因为切图没有的问题。临时换成了工商的图标。反正不影响我们开发教程):

%title插图%num

然后我们在自定义的ErrorDialog中写oncreate方法:

  1. @Override
  2. protected void onCreate(Bundle savedInstanceState) {
  3. super.onCreate(savedInstanceState);
  4. View view = View.inflate(context,R.layout.dialog_loginerror,null);
  5. setContentView(view);
  6. }

然后这时候我以为就跟继承Activity一样。变成了我自定义的布局界面。然后我满心欢喜的在Activity中调用了:
ErrorDialog dialog = new ErrorDialog(this); dialog.show();

%title插图%num

WTF!!
这是逗我吗,我的自定义布局明明是个圆角啊。怎么变成了个长方形。
所以我就把我们自定义布局的背景色换成其黑色。看下效果:

%title插图%num

这下首先知道了。我们其实自定义的layout类似于是盖在了底部白色的背景上面,恰好我们的自定义布局也是白色。所以我们现在首先要把底部的那个白色背景变为透明,那样,就会出现我们自定义布局的圆角了

那我们下一步的目的就是要设置Dialog自定义的theme。

把Dialog自带的白色背景色改为透明即可,很简单。百度一搜一大把。哈哈。其实说到底就是继承android:style/Theme.Dialog主题,然后再覆写其中的几个相关属性,比如背景设置为透明,去除自带的title等属性。

(我在网上看的时候,网上有人推荐Android4.0后,不要使用Theme.Dialog。改为使用Theme.Holo.DialogWhenLarge。
Android4: 请放弃使用Theme.Dialog
当然对我们这个自定义布局需求,继承哪个都能实现效果。就看大家怎么选择了。
)

好,那我们就自定义继承Theme.Dialog:

  1. <style name=“Dialog” parent=“android:style/Theme.Dialog”>
  2. <item name=“android:background”>@android:color/transparent</item>
  3. <item name=“android:windowBackground”>@android:color/transparent</item>
  4. <item name=“android:windowNoTitle”>true</item>
  5. </style>

(如果有其他需求,再覆写其他的属性即可,本例中就只需要改这三个)

好了。然后在上面我们介绍过的生成Dialog实例中的第二个构造函数,是传入Theme。我们调用:

  1. ErrorDialog dialog = new ErrorDialog(this,R.style.Dialog);
  2. dialog.show();

然后我们看到效果了:

 

%title插图%num

 

起码形状变成我们的自定义布局的形状了。哈哈。但是这个Dialog大小和我们的自定义布局大小不同。

下一步要处理Dialog呈现的自定义布局的大小

还是老样子,百度一搜一大把,好吧。我实在是太懒了。(不服气我懒的话,过来打我哈。O(∩_∩)O)

  1. Window win = getWindow();
  2. WindowManager.LayoutParams lp = win.getAttributes();
  3. lp.gravity = Gravity.CENTER;
  4. lp.height = DensityUtil.dip2px(context,250);
  5. lp.width = DensityUtil.dip2px(context,200);
  6. win.setAttributes(lp);

我来解释下,因为上面我们自定义布局的大小就是

  1. android:layout_width=“200dp”
  2. android:layout_height=“250dp”

所以我们这里也设置这个对话框的大小也设置为相同大小,这样就等于显示出我们自定义布局大小。这里因为高和宽改为我们自己自定义布局大小,所以lp.gravity = Gravity.CENTER;这句也可以不写,因为反正是正好完全填充。


所以我们当前的自定义Dialog代码变为:

  1. @Override
  2. protected void onCreate(Bundle savedInstanceState) {
  3. super.onCreate(savedInstanceState);
  4. View view = View.inflate(context,R.layout.dialog_loginerror,null);
  5. setContentView(view);
  6. Window win = getWindow();
  7. WindowManager.LayoutParams lp = win.getAttributes();
  8. lp.height = DensityUtil.dip2px(context,250);
  9. lp.width = DensityUtil.dip2px(context,200);
  10. win.setAttributes(lp);
  11. }
点击事件
  1. 一般我们项目中跳出了对话框,点击对话框外面的区域,是不能默认让对话框消失的。所以我们需要添加setCanceledOnTouchOutside(false);
  2. 自定义布局上面的按钮点击事件的添加很简单,因为上面已经拿到了自定义布局的view的对象。比如我们上面的自定义布局有个<确定>按钮,我们点击按钮让对话框消失。我们只需要:
  1. view.findViewById(R.id.btn_cancel).setOnClickListener(new Button.OnClickListener() {
  2. @Override
  3. public void onClick(View view) {
  4. dismiss();
  5. }
  6. });

*终的自定义ErrorDialog代码:

  1. public class ErrorDialog extends Dialog {
  2. public Context context;
  3. public ErrorDialog(Context context) {
  4. super(context);
  5. this.context = context;
  6. }
  7. public ErrorDialog(Context context, int theme) {
  8. super(context, theme);
  9. this.context = context;
  10. }
  11. public ErrorDialog(Context context, boolean cancelable, OnCancelListener cancelListener) {
  12. super(context, cancelable, cancelListener);
  13. this.context = context;
  14. }
  15. @Override
  16. protected void onCreate(Bundle savedInstanceState) {
  17. super.onCreate(savedInstanceState);
  18. View view = View.inflate(context, R.layout.dialog_loginerror, null);
  19. setContentView(view);
  20. setCanceledOnTouchOutside(false);
  21. Window win = getWindow();
  22. WindowManager.LayoutParams lp = win.getAttributes();
  23. lp.height = DensityUtil.dip2px(context, 250);
  24. lp.width = DensityUtil.dip2px(context, 200);
  25. win.setAttributes(lp);
  26. view.findViewById(R.id.btn_cancel).setOnClickListener(new Button.OnClickListener() {
  27. @Override
  28. public void onClick(View view) {
  29. dismiss();
  30. }
  31. });
  32. }
  33. }

*后生成的界面如下:

%title插图%num


—————————————-本文正文,封装君正式登场—————————————————–

上面只是介绍了自定义Dialog的基本知识。而且这个ErrorDialog只能用于*个效果图所需的Dialog需求,然后比如我们要第二个效果图的需求。然后自己再写一个ChangeDialog???一个项目有5种不同的界面Dialog。我要写5个自定义Dialog类???答案当然是NO,NO,NO。

我们来看下,上面我们完成ErrorDialog的时候,到底需要哪些东西,才能*后完成一个自定义Dialog。

  1. Context
  2. R.style.XXXX
  3. R.layout.XXXX
  4. setCanceledOnTouchOutside(XXXX);是否允许点击外部区域来让Dialog消失
  5. WindowManager.LayoutParams对象类的height和width。
  6. 自定义布局上各个View的点击事件

基本是上述五个需求。(额外需求,大家就在这基础上封装好的类中添加自己的需求即可)

我们也是模仿Dialog建立的Builder模式,自己写个封装类。
(Builder模式的介绍和用Android Studio插件来快速自动生成代码,大家可以来看下我已经写得文章:经典Builder/变种Builder模式及自动化生成代码插件)

我先上代码再来进行查看:

  1. public class CustomDialog extends Dialog {
  2. private Context context;
  3. private int height, width;
  4. private boolean cancelTouchout;
  5. private View view;
  6. private CustomDialog(Builder builder) {
  7. super(builder.context);
  8. context = builder.context;
  9. height = builder.height;
  10. width = builder.width;
  11. cancelTouchout = builder.cancelTouchout;
  12. view = builder.view;
  13. }
  14. private CustomDialog(Builder builder, int resStyle) {
  15. super(builder.context, resStyle);
  16. context = builder.context;
  17. height = builder.height;
  18. width = builder.width;
  19. cancelTouchout = builder.cancelTouchout;
  20. view = builder.view;
  21. }
  22. @Override
  23. protected void onCreate(Bundle savedInstanceState) {
  24. super.onCreate(savedInstanceState);
  25. setContentView(view);
  26. setCanceledOnTouchOutside(cancelTouchout);
  27. Window win = getWindow();
  28. WindowManager.LayoutParams lp = win.getAttributes();
  29. lp.gravity = Gravity.CENTER;
  30. lp.height = height;
  31. lp.width = width;
  32. win.setAttributes(lp);
  33. }
  34. public static final class Builder {
  35. private Context context;
  36. private int height, width;
  37. private boolean cancelTouchout;
  38. private View view;
  39. private int resStyle = –1;
  40. public Builder(Context context) {
  41. this.context = context;
  42. }
  43. public Builder view(int resView) {
  44. view = LayoutInflater.from(context).inflate(resView, null);
  45. return this;
  46. }
  47. public Builder heightpx(int val) {
  48. height = val;
  49. return this;
  50. }
  51. public Builder widthpx(int val) {
  52. width = val;
  53. return this;
  54. }
  55. public Builder heightdp(int val) {
  56. height = DensityUtil.dip2px(context, val);
  57. return this;
  58. }
  59. public Builder widthdp(int val) {
  60. width = DensityUtil.dip2px(context, val);
  61. return this;
  62. }
  63. public Builder heightDimenRes(int dimenRes) {
  64. height = context.getResources().getDimensionPixelOffset(dimenRes);
  65. return this;
  66. }
  67. public Builder widthDimenRes(int dimenRes) {
  68. width = context.getResources().getDimensionPixelOffset(dimenRes);
  69. return this;
  70. }
  71. public Builder style(int resStyle) {
  72. this.resStyle = resStyle;
  73. return this;
  74. }
  75. public Builder cancelTouchout(boolean val) {
  76. cancelTouchout = val;
  77. return this;
  78. }
  79. public Builder addViewOnclick(int viewRes,View.OnClickListener listener){
  80. view.findViewById(viewRes).setOnClickListener(listener);
  81. return this;
  82. }
  83. public CustomDialog build() {
  84. if (resStyle != –1) {
  85. return new CustomDialog(this, resStyle);
  86. } else {
  87. return new CustomDialog(this);
  88. }
  89. }
  90. }
  91. }

我这边的Builder中对height和width写了三种方式,比如直接写入px的值就调用heightpx(),如果直接写入dp值,就调用heightdp()。不过*多的应该还是调用heightDimenRes()方法。因为一般我们在写自定义layout布局的时候,height和width的数值肯定是去dimen.xml中获取。所以我们在代码中生成这个自定义对话框的时候,也就直接调用了heightDimenRes(R.dimen.XXX)。这样。我们什么时候需求变了,说这个对话框的大小要进行更改,我们不需要更改代码,只需要在demen.xml中将数值修改即可。

然后我们再来写上面的ErrorDialog:

  1. CustomDialog.Builder builder = new CustomDialog.Builder(this);
  2. dialog =
  3. builder.cancelTouchout(false)
  4. .view(R.layout.dialog_loginerror)
  5. .heightDimenRes(R.dimen.dialog_loginerror_height)
  6. .widthDimenRes(R.dimen.dialog_loginerror_width)
  7. .style(R.style.Dialog)
  8. .addViewOnclick(R.id.btn_cancel,new View.OnClickListener() {
  9. @Override
  10. public void onClick(View view) {
  11. dialog.dismiss();
  12. }
  13. })
  14. .build();
  15. dialog.show();

真是简单!!!!!

好了我们现在要第二个效果图的对话框了。比如我现在为了简单。就做了个简单的自定义Layout。

%title插图%num

然后点击“经办人”,“审批人”,“确认”按钮,有不同点击效果。
生成这个对话框代码如下:

  1. View.OnClickListener listener = new View.OnClickListener() {
  2. @Override
  3. public void onClick(View view) {
  4. switch (view.getId()){
  5. case R.id.jbperson :
  6. Toast.makeText(aty, “选择经办人按钮”, Toast.LENGTH_SHORT).show();
  7. break;
  8. case R.id.spperson:
  9. Toast.makeText(aty, “选择审批人按钮”, Toast.LENGTH_SHORT).show();
  10. break;
  11. case R.id.confirmbtn:
  12. Toast.makeText(aty, “点击确定按钮”, Toast.LENGTH_SHORT).show();
  13. break;
  14. }
  15. }
  16. };
  17. CustomDialog.Builder builder = new CustomDialog.Builder(this);
  18. CustomDialog dialog = builder
  19. .style(R.style.Dialog)
  20. .heightDimenRes(R.dimen.dilog_identitychange_height)
  21. .widthDimenRes(R.dimen.dilog_identitychange_width)
  22. .cancelTouchout(false)
  23. .view(R.layout.dialog_identitychange)
  24. .addViewOnclick(R.id.jbperson,listener)
  25. .addViewOnclick(R.id.spperson,listener)
  26. .addViewOnclick(R.id.confirmbtn,listener)
  27. .build();
  28. dialog.show();

 

真是简单!!!!!!!哈哈。当然我只是做了简单的封装。大家可以提出不同的意见。

安卓自定义Dialog的实现

一、Dialog布局文件

<?xml version=”1.0″ encoding=”utf-8″?>
<FrameLayout xmlns:android=”http://schemas.android.com/apk/res/android”
android:layout_width=”fill_parent”
android:layout_height=”fill_parent”
android:clickable=”true”
android:orientation=”vertical”
android:padding=”20.0dip” >

<LinearLayout
android:layout_width=”fill_parent”
android:layout_height=”wrap_content”
android:layout_gravity=”center”
android:background=”#ff7200″
android:orientation=”vertical” >

<TextView
android:id=”@+id/title”
android:textColor=”#ffffff”
android:textSize=”20sp”
android:layout_width=”fill_parent”
android:layout_height=”50dp”
android:gravity=”center”
android:text=”自定义弹窗”
android:visibility=”visible” />

<LinearLayout
android:id=”@+id/content”
android:layout_width=”fill_parent”
android:layout_height=”wrap_content”
android:gravity=”center” >

<TextView
android:background=”#ffffff”
android:id=”@+id/message”
android:textColor=”#b8b8b8″
android:textSize=”16sp”
android:layout_width=”fill_parent”
android:layout_height=”wrap_content”
android:gravity=”left|center”
android:lineSpacingMultiplier=”1.5″
android:paddingBottom=”15.0dip”
android:paddingLeft=”20.0dip”
android:paddingRight=”20.0dip”
android:paddingTop=”15.0dip” />
</LinearLayout>

<LinearLayout
android:layout_width=”fill_parent”
android:layout_height=”50dp”
android:layout_gravity=”bottom”
android:background=”#ffffff”
android:gravity=”center”
android:orientation=”horizontal” >

<TextView
android:layout_weight=”1″
android:id=”@+id/positiveTextView”
android:textColor=”#b8b8b8″
android:textSize=”16sp”
android:layout_width=”match_parent”
android:layout_height=”match_parent”
android:gravity=”center”
android:text=”ok”
android:clickable=”true”/>

<TextView
android:layout_weight=”1″
android:id=”@+id/negativeTextView”
android:textColor=”#ff9138″
android:textSize=”16sp”
android:layout_width=”match_parent”
android:layout_height=”match_parent”
android:gravity=”center”
android:text=”cancel”
android:clickable=”true”/>
</LinearLayout>
</LinearLayout>

</FrameLayout>

二、Style

<style name=”Dialog” parent=”android:style/Theme.Dialog”>
<item name=”android:background”>#00000000</item>
<item name=”android:windowBackground”>@android:color/transparent</item>
<item name=”android:windowNoTitle”>true</item>
<item name=”android:windowIsFloating”>true</item>
</style>

三、MainActivity代码

CustomDialog.Builder builder = new CustomDialog.Builder(MainActivity.this);
builder.setMessage(“这个就是自定义的提示框”);
builder.setTitle(“提示”);
builder.setPositiveButton(“确定”, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
//设置你的操作事项
Toast.makeText(MainActivity.this,”queding”,Toast.LENGTH_SHORT).show();
}
});

builder.setNegativeButton(“取消”,
new android.content.DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(MainActivity.this,”queding”,Toast.LENGTH_SHORT).show();
dialog.dismiss();
}
});

builder.create().show();

四、自定义DialogClass

package com.cavytech.widget;

import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.cavytech.wear2.R;

/**
* Created by LiBin on 2016/6/16.
*/
public class CustomDialog extends Dialog {

public CustomDialog(Context context) {
super(context);
}

public CustomDialog(Context context, int theme) {
super(context, theme);
}

public static class Builder {
private Context context;
private String title;
private String message;
private String positiveButtonText;
private String negativeButtonText;
private View contentView;
private DialogInterface.OnClickListener positiveButtonClickListener;
private DialogInterface.OnClickListener negativeButtonClickListener;

public Builder(Context context) {
this.context = context;
}

public Builder setMessage(String message) {
this.message = message;
return this;
}

/**
* Set the Dialog message from resource
*
* @param
* @return
*/
public Builder setMessage(int message) {
this.message = (String) context.getText(message);
return this;
}

/**
* Set the Dialog title from resource
*
* @param title
* @return
*/
public Builder setTitle(int title) {
this.title = (String) context.getText(title);
return this;
}

/**
* Set the Dialog title from String
*
* @param title
* @return
*/

public Builder setTitle(String title) {
this.title = title;
return this;
}

public Builder setContentView(View v) {
this.contentView = v;
return this;
}

/**
* Set the positive button resource and it’s listener
*
* @param positiveButtonText
* @return
*/
public Builder setPositiveButton(int positiveButtonText,
DialogInterface.OnClickListener listener) {
this.positiveButtonText = (String) context
.getText(positiveButtonText);
this.positiveButtonClickListener = listener;
return this;
}

public Builder setPositiveButton(String positiveButtonText,
DialogInterface.OnClickListener listener) {
this.positiveButtonText = positiveButtonText;
this.positiveButtonClickListener = listener;
return this;
}

public Builder setNegativeButton(int negativeButtonText,
DialogInterface.OnClickListener listener) {
this.negativeButtonText = (String) context
.getText(negativeButtonText);
this.negativeButtonClickListener = listener;
return this;
}

public Builder setNegativeButton(String negativeButtonText,
DialogInterface.OnClickListener listener) {
this.negativeButtonText = negativeButtonText;
this.negativeButtonClickListener = listener;
return this;
}

public CustomDialog create() {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// instantiate the dialog with the custom Theme
final CustomDialog dialog = new CustomDialog(context, R.style.Dialog);
View layout = inflater.inflate(R.layout.dialog_normal_layout, null);
dialog.addContentView(layout, new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
// set the dialog title
((TextView) layout.findViewById(R.id.title)).setText(title);
// set the confirm button
if (positiveButtonText != null) {
((TextView) layout.findViewById(R.id.positiveTextView))
.setText(positiveButtonText);
if (positiveButtonClickListener != null) {
((TextView) layout.findViewById(R.id.positiveTextView))
.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
positiveButtonClickListener.onClick(dialog,
DialogInterface.BUTTON_POSITIVE);
}
});
}
} else {
// if no confirm button just set the visibility to GONE
layout.findViewById(R.id.positiveTextView).setVisibility(
View.GONE);
}
// set the cancel button
if (negativeButtonText != null) {
((TextView) layout.findViewById(R.id.negativeTextView))
.setText(negativeButtonText);
if (negativeButtonClickListener != null) {
((TextView) layout.findViewById(R.id.negativeTextView))
.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
negativeButtonClickListener.onClick(dialog,
DialogInterface.BUTTON_NEGATIVE);
}
});
}
} else {
// if no confirm button just set the visibility to GONE
layout.findViewById(R.id.negativeTextView).setVisibility(
View.GONE);
}
// set the content message
if (message != null) {
((TextView) layout.findViewById(R.id.message)).setText(message);
} else if (contentView != null) {
// if no message set
// add the contentView to the dialog body
((LinearLayout) layout.findViewById(R.id.content))
.removeAllViews();
((LinearLayout) layout.findViewById(R.id.content))
.addView(contentView, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.FILL_PARENT));
}
dialog.setContentView(layout);
return dialog;
}
}
}

设置 Dialog 不显示标题的常用方法

1、通过dialog的window窗口调用requestWindowFeature(int featureId)方法

getWindow().requestFeature(Window.FEATURE_NO_TITLE);

注意需要在 Dialog 中的 setContentView( ) 方法之前调用。

2、通过自定义一个style,添加 <item name=”android:windowNoTitle”>true</item> ,或者直接设置该 style 的 parent 为一个已经包含了 NoTitle 属性的样式,然后在创建 Dialog 实例时使用该样式作为 Theme。

Dialog(@NonNull Context context, @StyleRes int themeResId)

Android自定义Dialog对话框的几种方法(精简版)

自定义对话框是经常使用的功能,我们常用的弹窗操作,除了使用popwindow就是使用dialog来实现,这两种组件都支持之定义布局和功能来满足我们个性化的需求,也可以不采用自定义而直接使用系统封装好的api来实现功能。今天简单总结下在使用dialog做弹窗功能的方法和会遇到的问题与解决方案。
方法一:直接使用系统的,不自定义布局和功能方式

/* @setIcon 设置对话框图标
* @setTitle 设置对话框标题
* @setMessage 设置对话框消息提示
*/
final AlertDialog.Builder normalDialog =
new AlertDialog.Builder(MainActivity.this);
normalDialog.setIcon(R.drawable.icon_dialog);
normalDialog.setTitle(“我是一个普通Dialog”)
normalDialog.setMessage(“你喜欢系统对话框吗?”);
normalDialog.setPositiveButton(“确定”,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//…To-do
}
});
normalDialog.setNegativeButton(“关闭”,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//…To-do
}
});

//如果想自定义三个按钮的对话框,可以把下面的方法注释打开
// normalDialog.setNeutralButton(“第三个按钮”,
// new DialogInterface.OnClickListener() {
// @Override
// public void onClick(DialogInterface dialog, int which) {
// // …To-do
// }
// });
// 显示
normalDialog.show();

方法二:采用自定义布局和功能方式

自定义对话框布局: high_opinion_dialog_layout.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=”wrap_content”
android:paddingTop=”@dimen/dp_20″
android:paddingBottom=”@dimen/dp_10″
android:paddingLeft=”@dimen/dp_15″
android:paddingRight=”@dimen/dp_15″
android:orientation=”vertical”>

<TextView
android:text=”Rate US”
android:gravity=”center”
android:textSize=”@dimen/sp_18″
android:textColor=”@color/black”
android:layout_gravity=”center_horizontal”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content” />
<TextView
android:text=”We’re glad you’re enjoying using our app! Would you mind giving us a review?”
android:gravity=”center”
android:textSize=”@dimen/sp_12″
android:layout_marginTop=”@dimen/dp_5″
android:textColor=”@color/black”
android:layout_gravity=”center_horizontal”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content” />

<LinearLayout
android:layout_width=”match_parent”
android:layout_marginTop=”@dimen/dp_15″
android:layout_height=”@dimen/dp_37″>

<Button
android:id=”@+id/btn_cancel_high_opion”
android:layout_width=”0dp”
android:layout_height=”match_parent”
android:text=”Maybe later”
android:background=”@drawable/btn_cancer_high_opion_shape”
android:textColor=”@color/white”
android:layout_weight=”1″/>

<View
android:layout_width=”@dimen/dp_20″
android:layout_height=”match_parent”
/>
<Button
android:id=”@+id/btn_agree_high_opion”
android:layout_width=”0dp”
android:text=”Sure”
android:textColor=”@color/white”
android:background=”@drawable/btn_agree_high_opinion_shape”
android:layout_height=”match_parent”
android:layout_weight=”1″/>

</LinearLayout>

</LinearLayout>

然后在activity或者fragment中想要加点击弹出对话框的控件的监听事件中调用初始化下面方法

public class HomeActivity extends AppCompatActivity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);

Button btn= findViewById(R.id.btn)
//点击按钮弹出对话框
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showDialog();
}
});

}

//初始化并弹出对话框方法
private void showDialog(){
View view = LayoutInflater.from(this).inflate(R.layout.high_opinion_dialog_layout,null,false);
final AlertDialog dialog = new AlertDialog.Builder(this).setView(view).create();

Button btn_cancel_high_opion = view.findViewById(R.id.btn_cancel_high_opion);
Button btn_agree_high_opion = view.findViewById(R.id.btn_agree_high_opion);

btn_cancel_high_opion.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SharedPreferencesUnitls.setParam(getApplicationContext(),”HighOpinion”,”false”);
//… To-do
dialog.dismiss();
}
});

btn_agree_high_opion.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//… To-do
dialog.dismiss();
}
});

dialog.show();
//此处设置位置窗体大小,我这里设置为了手机屏幕宽度的3/4 注意一定要在show方法调用后再写设置窗口大小的代码,否则不起效果会
dialog.getWindow().setLayout((ScreenUtils.getScreenWidth(this)/4*3),LinearLayout.LayoutParams.WRAP_CONTENT);
}

}

此处附上ScreenUtils工具类代码

public class ScreenUtils {

/**
* 获取屏幕高度(px)
*/
public static int getScreenHeight(Context context) {
return context.getResources().getDisplayMetrics().heightPixels;
}
/**
* 获取屏幕宽度(px)
*/
public static int getScreenWidth(Context context) {
return context.getResources().getDisplayMetrics().widthPixels;
}

}

需要注意的问题总结:系统的dialog的宽度默认是固定的,即使你自定义布局的怎么修改宽高也不起作用,如果想修改弹出窗体大小,可以使用下面这段代码在调用dialog.show()方法之后来实现改变对话框的宽高的需求

//此处设置位置窗体大小,
dialog.getWindow().setLayout(width,height);

Android4.0的Alertdialog对话框,设置点击其他位置不消失

Android4.0以上AlertDialog,包括其他自定义的dialog,在触摸对话框边缘外部,对话框消失。

可以设置这么一条属性,当然必须先AlertDialog.Builder.create()之后才能调用这两个方法

方法一:

setCanceledOnTouchOutside(false);调用这个方法时,按对话框以外的地方不起作用。按返回键还起作用

方法二:

setCancelable(false);调用这个方法时,按对话框以外的地方不起作用。按返回键也不起作用

如果你需要自定义样式日期时间选择对话框控件,可以点击这里传送你过去

改变Android Dialog弹出后的Activity背景亮度:
在代码中修改.lp.alpha大小随自己要求设置

// 设置屏幕背景变暗
private void setScreenBgDarken() {
WindowManager.LayoutParams lp = getWindow().getAttributes();
lp.alpha = 0.5f;
lp.dimAmount = 0.5f;
getWindow().setAttributes(lp);
}
// 设置屏幕背景变亮
private void setScreenBgLight() {
WindowManager.LayoutParams lp = getWindow().getAttributes();
lp.alpha = 1.0f;
lp.dimAmount = 1.0f;
getWindow().setAttributes(lp);
}

如何控制弹窗弹出的位置:
一般都是在屏幕正中间弹出默认,但也可以控制从别的地方弹出,比如从底部弹出,可以这样写

View view = LayoutInflater.from(this).inflate(R.layout.send_dialog, null);
final Dialog dialog = new AlertDialog.Builder(this, R.style.home_dialog)
.setView(view)
.setCancelable(true)
.create();
dialog.show();

Window win = dialog.getWindow();
win.setGravity(Gravity.BOTTOM); // 这里控制弹出的位置
win.getDecorView().setPadding(0, 0, 0, 0);
WindowManager.LayoutParams lp = win.getAttributes();
lp.width = WindowManager.LayoutParams.MATCH_PARENT;
lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
dialog.getWindow().setBackgroundDrawable(null);
win.setAttributes(lp);

view.findViewById(R.id.cancle_dialog).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dialog.dismiss();
}
});

再补充一点爬坑的经验:
有时候会遇到定义dialog布局的时候出现加载出来的弹窗和自己布局里面定义的大小宽高不一致的效果,然后用dialog.getWindow().setLayout(width,height)方法怎么设置调节都不管用,我就遇到过一次,特别坑,后来发现了一点造成这种异常情况的原因:
出现问题时的dialog布局代码:

<?xml version=”1.0″ encoding=”utf-8″?>
<RelativeLayout xmlns:android=”http://schemas.android.com/apk/res/android”
android:layout_width=”@dimen/dp_310″
android:layout_height=”@dimen/dp_236″
android:background=”@drawable/wallpaper_downloadorsace_outside_shape”>

<RelativeLayout
android:id=”@+id/rl_close_dialog”
android:layout_width=”@dimen/dp_40″
android:layout_height=”@dimen/dp_40″>

<ImageView
android:id=”@+id/iv_close_dialog”
android:layout_width=”@dimen/dp_15″
android:layout_height=”@dimen/dp_15″
android:scaleType=”fitXY”
android:layout_marginLeft=”@dimen/dp_14″
android:layout_marginTop=”@dimen/dp_12″
android:src=”@drawable/icon_close” />

</RelativeLayout>

<RelativeLayout
android:layout_marginTop=”@dimen/dp_46″
android:layout_marginBottom=”@dimen/dp_35″
android:layout_centerInParent=”true”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”>

<LinearLayout
android:id=”@+id/ll_localsave_out”
android:layout_width=”@dimen/dp_215″
android:layout_height=”@dimen/dp_53″
android:layout_centerHorizontal=”true”
android:background=”@drawable/wallpaper_downloadorsace_shape”
android:gravity=”center”>

<LinearLayout
android:id=”@+id/ll_localsave”
android:background=”@drawable/local_save_water_selector”
android:clickable=”true”
android:gravity=”center”
android:layout_width=”match_parent”
android:layout_height=”match_parent”>
<!–android:background=”?android:attr/selectableItemBackground” 系统自带水波纹效果 –>

<ImageView
android:layout_width=”@dimen/dp_22″
android:layout_height=”@dimen/dp_28″
android:scaleType=”fitXY”
android:src=”@drawable/icon_phone” />

<com.blossom.ripple.widget.AvenirNextRegularTextView
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:layout_marginLeft=”@dimen/dp_7″
android:text=”Local save”
android:textColor=”@color/white”
android:textSize=”@dimen/sp_17″ />

</LinearLayout>

</LinearLayout>

<LinearLayout
android:layout_alignParentBottom=”true”
android:layout_marginBottom=”@dimen/dp_45″
android:layout_width=”@dimen/dp_215″
android:layout_height=”@dimen/dp_53″
android:layout_centerHorizontal=”true”
android:background=”@drawable/wallpaper_downloadorsace_shape”
android:gravity=”center”>

<LinearLayout
android:id=”@+id/ll_setaswallpaper”
android:background=”@drawable/local_save_water_selector”
android:clickable=”true”
android:gravity=”center”
android:layout_width=”match_parent”
android:layout_height=”match_parent”>

<!–android:background=”?android:attr/selectableItemBackground” 系统自带水波纹效果 –>

<ImageView
android:layout_width=”@dimen/dp_28″
android:layout_height=”@dimen/dp_24″
android:scaleType=”fitXY”
android:src=”@drawable/icon_album” />

<com.blossom.ripple.widget.AvenirNextRegularTextView
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:layout_marginLeft=”@dimen/dp_5″
android:text=”Set as wallpaper”
android:textColor=”@color/white”
android:textSize=”@dimen/sp_17″ />
</LinearLayout>

</LinearLayout>

</RelativeLayout>

</RelativeLayout>

运行效果如下图

%title插图%num

运行出来的效果很头痛,虽然我在布局代码里面写死了弹窗布局的宽高大小,然后想通过window的setlayout方法控制改变弹窗的大小,但无论如何都不行,后来仔细检查布局代码发现了猫腻,在一个子布局LinearLayout的标签下引用了一个android:layout_alignParentBottom=”true”的属性,然后稍微调整了下代码再次运行便解决了上面的问题。下面贴下修改后的正确代码,我在里面加了问题原因的注释还:

<?xml version=”1.0″ encoding=”utf-8″?>
<RelativeLayout xmlns:android=”http://schemas.android.com/apk/res/android”
android:layout_width=”@dimen/dp_310″
android:layout_height=”@dimen/dp_236″
android:background=”@drawable/wallpaper_downloadorsace_outside_shape”>

<RelativeLayout
android:id=”@+id/rl_close_dialog”
android:layout_width=”@dimen/dp_40″
android:layout_height=”@dimen/dp_40″>

<ImageView
android:id=”@+id/iv_close_dialog”
android:layout_width=”@dimen/dp_15″
android:layout_height=”@dimen/dp_15″
android:scaleType=”fitXY”
android:layout_marginLeft=”@dimen/dp_14″
android:layout_marginTop=”@dimen/dp_12″
android:src=”@drawable/icon_close” />

</RelativeLayout>

<RelativeLayout
android:layout_marginTop=”@dimen/dp_46″
android:layout_marginBottom=”@dimen/dp_35″
android:layout_centerInParent=”true”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”>

<LinearLayout
android:id=”@+id/ll_localsave_out”
android:layout_width=”@dimen/dp_215″
android:layout_height=”@dimen/dp_53″
android:layout_centerHorizontal=”true”
android:background=”@drawable/wallpaper_downloadorsace_shape”
android:gravity=”center”>

<LinearLayout
android:id=”@+id/ll_localsave”
android:background=”@drawable/local_save_water_selector”
android:clickable=”true”
android:gravity=”center”
android:layout_width=”match_parent”
android:layout_height=”match_parent”>
<!–android:background=”?android:attr/selectableItemBackground” 系统自带水波纹效果 –>

<ImageView
android:layout_width=”@dimen/dp_22″
android:layout_height=”@dimen/dp_28″
android:scaleType=”fitXY”
android:src=”@drawable/icon_phone” />

<com.blossom.ripple.widget.AvenirNextRegularTextView
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:layout_marginLeft=”@dimen/dp_7″
android:text=”Local save”
android:textColor=”@color/white”
android:textSize=”@dimen/sp_17″ />

</LinearLayout>

</LinearLayout>

<LinearLayout
android:layout_width=”@dimen/dp_215″
android:layout_height=”@dimen/dp_53″
android:layout_centerHorizontal=”true”
android:layout_below=”@+id/ll_localsave_out”
android:layout_marginTop=”@dimen/dp_30″
android:background=”@drawable/wallpaper_downloadorsace_shape”
android:gravity=”center”>
<!–android:layout_alignParentBottom=”true” 这个属性曾经导致过弹窗特别大,会挨着屏幕顶部和底部–>

<LinearLayout
android:id=”@+id/ll_setaswallpaper”
android:background=”@drawable/local_save_water_selector”
android:clickable=”true”
android:gravity=”center”
android:layout_width=”match_parent”
android:layout_height=”match_parent”>

<!–android:background=”?android:attr/selectableItemBackground” 系统自带水波纹效果 –>

<ImageView
android:layout_width=”@dimen/dp_28″
android:layout_height=”@dimen/dp_24″
android:scaleType=”fitXY”
android:src=”@drawable/icon_album” />

<com.blossom.ripple.widget.AvenirNextRegularTextView
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:layout_marginLeft=”@dimen/dp_5″
android:text=”Set as wallpaper”
android:textColor=”@color/white”
android:textSize=”@dimen/sp_17″ />
</LinearLayout>

</LinearLayout>
</RelativeLayout>

</RelativeLayout>

问题解决后感觉又积累了一点弹窗方面的经验,收获满满的,赶紧记录下来吧,省的以后忘记了再犯同样的错误!

还有一个关于弹窗容易遇到的异常:Unable to add window – token android.os.BinderProxy@d80e90e is not valid; is your activity running?android.view.ViewRootImpl.setView(ViewRootImpl.java:688)

该异常表示不能添加窗口,通常是所要依附的view已经不存在导致的。
[解决方案]:Dialog&AlertDialog,WindowManager不能正确使用时,经常会报出该异常,原因比较多,几个常见的场景如下:
1.上一个页面没有destroy的时候,之前的Activity已经接收到了广播。如果此时之前的Activity进行UI层面的操作处理,就会造成crash。UI层面的刷新,一定要注意时机,建议使用set_result来代替广播的形式进行刷新操作,避免使用广播的方式,代码不直观且容易出错。
2.Dialog在Actitivty退出后弹出。在Dialog调用show方法进行显示时,必须要有一个Activity作为窗口的载体,如果Activity被销毁,那么导致Dialog的窗口载体找不到。建议在Dialog调用show方法之前先判断Activity是否已经被销毁。
3.Service&Application弹出对话框或WindowManager添加view时,没有设置window type为TYPE_SYSTEM_ALERT。需要在调用dialog.show()方法前添加dialog.getWindow().SetType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT)。
4.6.0的系统上, (非定制 rom 行为)若没有给予悬浮窗权限, 会弹出该问题, 可以通过Settings.canDrawOverlays来判断是否有该权限.
5.某些不稳定的MIUI系统bug引起的权限问题,系统把Toast也当成了系统级弹窗,android6.0的系统Dialog弹窗需要用户手动授权,若果app没有加入SYSTEM_ALERT_WINDOW权限就会报这个错。需要加入给app加系统Dialog弹窗权限,并动态申请权限,不满足*条会出现没权限闪退,不满足第二条会出现没有Toast的情况。

今天的分享先到这里,后续会不断添加和更新更多更好的学习资料,如果你喜欢可以关注加好友,互相探讨学习,我们互相学习一起成长!

自定义Dialog所遇到的问题总结

自定义Dialog所遇到的问题总结
1. 在extents Dialog 后,对话框左右两边出现大概10dp的margin,通过自定义其style无效后的解决办法
解决方法:
Window window = dialog.getWindow();
WindowManager.LayoutParams params =
window.getAttributes();
params.width = WindowManager.LayoutParams.MATCH_PARENT;
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
params.gravity =Gravity.FILL_HORIZONTAL;
window.setAttributes(params);

说明:主要代码为
params.gravity =Gravity.FILL_HORIZONTAL;

2. extends Dialog 与 extends AlertDialog 引发的问题:前者可以调取软键盘,后者不起作用,这里写一下分析过程,问题虽然还没找到原因。
注意此问题都是通过自定义其style实现。

过程:
1.从extentds AlertDialog 开始向下追踪

public class CustomBottomDialog extends AlertDialog {
public CustomBottomDialog(Context context, int themeResId) {
super(context, themeResId);
}
}

protected AlertDialog(Context context, @StyleRes int themeResId) {
this(context, themeResId, true);
}

AlertDialog(Context context, @StyleRes int themeResId, boolean createContextThemeWrapper) {
super(context, createContextThemeWrapper ? resolveDialogTheme(context, themeResId) : 0,
createContextThemeWrapper);

mWindow.alwaysReadCloseOnTouchAttr();
mAlert = AlertController.create(getContext(), this, getWindow());
}
}

static @StyleRes int resolveDialogTheme(Context context, @StyleRes int themeResId) {
if (themeResId == THEME_TRADITIONAL) {
return R.style.Theme_Dialog_Alert;
} else if (themeResId == THEME_HOLO_DARK) {
return R.style.Theme_Holo_Dialog_Alert;
} else if (themeResId == THEME_HOLO_LIGHT) {
return R.style.Theme_Holo_Light_Dialog_Alert;
} else if (themeResId == THEME_DEVICE_DEFAULT_DARK) {
return R.style.Theme_DeviceDefault_Dialog_Alert;
} else if (themeResId == THEME_DEVICE_DEFAULT_LIGHT) {
return R.style.Theme_DeviceDefault_Light_Dialog_Alert;
} else if (ResourceId.isValid(themeResId)) {
// start of real resource IDs.
return themeResId;
} else {
final TypedValue outValue = new TypedValue();
context.getTheme().resolveAttribute(R.attr.alertDialogTheme, outValue, true);
return outValue.resourceId;
}
}

Dialog(@NonNull Context context, @StyleRes int themeResId, boolean createContextThemeWrapper) {
if (createContextThemeWrapper) {
if (themeResId == ResourceId.ID_NULL) {
final TypedValue outValue = new TypedValue();
context.getTheme().resolveAttribute(R.attr.dialogTheme, outValue, true);
themeResId = outValue.resourceId;
}
mContext = new ContextThemeWrapper(context, themeResId);
} else {
mContext = context;
}
}

如果extends Dialog 直接到*有一步,本质上都一样。

自定义Dialog或者AlertDialog在部分手机上margin失效的问题

*近项目中用到的自定义布局的Dialog比较多,我把宽度写死以后,在一些手机上是没有问题的,但是部分手机上(比如oppo手机)横向的margin不起作用,困扰了很长时间,今天有时间解决了一下。

原来不管是AlertDialog还是Dialog,因为AlertDialog集成于Dialog,他们本身的宽度都是与屏幕的宽度留有距离的,即我们在写自定义布局的时候不用给他设置成Dialog的样式,宽度match_parent,高度wrap_content即可,如果使用的是AlertDialog,ok,就不用管了,但是如果直接用的Dialog还是加上以下代码吧!

Window window=dialog.getWindow();
WindowManager.LayoutParams lp=window.getAttributes();
lp.width=WindowManager.LayoutParams.MATCH_PARENT;
lp.height=WindowManager.LayoutParams.WRAP_CONTENT;
window.setGravity(Gravity.CENTER);
window.setAttributes(lp);
总结:在部分手机上出现边距不起作用的应该是本来Dialog自身与屏幕宽度有边距,而我设置的宽度超出了它本身的宽度,导致margin不起作用。困惑了很久的问题终于豁然开朗了☺。