Android 自定义Dialog无法Dismiss

来源:互联网 发布:python进程和线程 编辑:程序博客网 时间:2024/06/05 17:06

写在前面:

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 测试用布局文件

<?xml version = "1.0" encoding="utf-8" ?><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中添加自定义的样式)

    <style name="MyDialog" parent="@android:Theme.Dialog">        <item name="android:windowFrame">@null</item>        <item name="android:windowNoTitle">true</item>        <item name="android:windowIsFloating">true</item>        <item name="android:windowContentOverlay">@null</item>        <item name="android:backgroundDimEnabled">false</item>        <item name="android:windowBackground">@color/transparent</item><!--背景透明-->    </style>

问题分析

现象:现在点击 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

0 0