Android 自定義Dialog無法Dismiss
寫在前面:
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一下。