Android开发碰到了一个很奇怪的问题,同样的自定义View的Dialog 的Code在一个项目中可以dismiss,在另一个项目中却如何也无法dismiss,真心不知道问题在什么地方,查阅了一下网上的资料,找到了自定义Dialog正确且标准的使用方式,在此Mark一下先。
代码so esay,只是用来测试为什么自定义的dialog的不能dismiss。
1.MainActivity.java
public class MainActivity extends Activity
{
private Dialog dialog = null;
private Button testBtn = null;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
public void initView()
{
testBtn = (Button) this.findViewById(R.id.button1);
testBtn.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View arg0)
{
// TODO Auto-generated method stub
showCenterDialog();
}
});
}
public void showCenterDialog()
{
//dialog自定义的样式
dialog = new Dialog(MainActivity.this,R.style.MyDialog);
dialog.setContentView(R.drawable.dialog_layout);
dialog.setCancelable(false);
View vv = LayoutInflater.from(this).inflate(R.drawable.dialog_layout,null);
Button closeBtn = (Button) vv.findViewById(R.id.closeBtn);
closeBtn.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View arg0)
{
// TODO Auto-generated method stub
dialog.dismiss();
}
});
dialog.show();
}
}
2.dialog_layout_xml 测试用布局文件
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/TopRel"
android:layout_width="200dp"
android:layout_height="150dp"
>
<Button
android:layout_width="150dp"
android:layout_height="100dp"
android:text="测试用按钮"
android:textSize="19sp"
android:id="@+id/closeBtn"
android:layout_centerInParent="true"
>Button>
RelativeLayout>
3.自定义Dialog采用的样式 Style
(style.xml中添加自定义的样式)
现象:现在点击 Dialog中出现的 ”测试用按钮“,dialog就是无法dismiss。
分析:调试发现,无论你如何点击”测试用按钮“,就是无法触发它的点击响应事件,感觉Dialog在调用setContentView()后显示在界面的Button和
View vv = LayoutInflater.from(this).inflate(R.drawable.dialog_layout,null);
Button closeBtn = (Button) vv.findViewById(R.id.closeBtn);
上面注册的Button不是同一个Button。
查阅了一下资料,根据有些网友的说法,Dialog在onCreate()的时候,会重新加载布局文件,即是调用下面的代码:
dialog.setContentView(R.drawable.dialog_layout);
重新加载过布局文件的Dialog的Button Id跟注册监听事件时的Button Id不是同一个Id,因此,不会有按键响应。
考虑到Dialog在调用setContentView()之后,已经重新加载过布局,则下面的代码:
View vv = dialog.getWindow().getDecorView();
可以捕捉到已经加载到Dialog的布局元素,即是将inflate加载的布局代码替换为上面列出的代码,即可解决自定义样式的Dialog无法Dismiss的问题。
View vv = LayoutInflater.from(this).inflate(R.drawable.dialog_layout,null);
至于为什么使用getWindow().getDecorView()可以解决这种bug,可以参看老罗的博客Android应用程序窗口(Activity)的视图对象(View)的创建过程分析以及decorView和window之间的层级及关系。两篇博客比较深入的解析了Activity和View的关系,带你从源码的层次理解Android的View布局,应该为必看文章,mark一下。
decorView和window之间的层级及关系:http://blog.csdn.net/guxiao1201/article/details/41744107
老罗的博客Android应用程序窗口(Activity)的视图对象(View)的创建过程分析
http://blog.csdn.net/luoshengyang/article/details/8245546