編輯:關於Android編程
之前自定義了一個AlertDialog對話框,第一次點擊時正常,但第二次調用時會出現錯誤:java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
關於這個錯誤糾結了我好久,在網上百度了也不少,但感覺解決效果都達不到自己想要的效果。網上的解釋說是一個子視圖指定了多個父視圖。由此可以推斷出,在第二次點擊按鈕彈出對話框時,子視圖與第一次點擊時的子視圖是同一個對象,而父視圖已經不再是同一個對象了。但感覺說的雲裡霧裡的,經過我研究之後,發現了我認為的很好的解決方法,想分享給大家交流一下。
代碼如下所示:
builder = new AlertDialog.Builder(MainActivity.this);
builder.setView(null);
builder.setView(dialogview);
builder.setTitle("記賬");
builder.setPositiveButton("確定", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
MySQLiteOpenHelper helper = new MySQLiteOpenHelper(
MainActivity.this);
SQLiteDatabase database = helper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put("sum", editText.getText().toString());
values.put(
"project",
spinner.getItemAtPosition(
(int) spinner.getSelectedItemId())
.toString());
if (checkBox.isChecked()) {
values.put("category", "收入");
}
if (checkBox2.isChecked()) {
values.put("category", "支出");
}
TextView textView = (TextView) view
.findViewById(R.id.textView1);
values.put("date", textView.getText().toString());
database.update("budget", values, "date=?",
new String[] { textView.getText().toString() });
dialogview=null;
if(dialogview==null){
dialogview = getLayoutInflater().inflate(R.layout.add_dialog, null);
editText = (EditText) dialogview.findViewById(R.id.editText1);
spinner = (Spinner) dialogview.findViewById(R.id.spinner1);
checkBox = (CheckBox) dialogview.findViewById(R.id.checkBox1);
checkBox2 = (CheckBox) dialogview.findViewById(R.id.checkBox2);
clock = (DigitalClock) dialogview.findViewById(R.id.digitalClock2);
flag=true;
}
loaderManager.getLoader(1001).onContentChanged();// 若狀態改變,觸發這個方法
}
});
builder.setNegativeButton("取消", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
dialogview=null;
if(dialogview==null){
dialogview = getLayoutInflater().inflate(R.layout.add_dialog, null);
editText = (EditText) dialogview.findViewById(R.id.editText1);
spinner = (Spinner) dialogview.findViewById(R.id.spinner1);
checkBox = (CheckBox) dialogview.findViewById(R.id.checkBox1);
checkBox2 = (CheckBox) dialogview.findViewById(R.id.checkBox2);
clock = (DigitalClock) dialogview.findViewById(R.id.digitalClock2);
flag=true;
}
}
});
builder.create().show();
}
});網友建議呢自定義的view不應該設置為全局變量,應該設置為局部變量,Alert.builder創建一次,view通過getLayoutInflater獲取一次就不會有二次點擊對話框的問題,但這樣就影響了我程序的效果。
根據我自己的不斷探索,發現報錯的原因時,因為我的view設置的為全局變量,在第一次創建對話框的時候,已經綁定了一個builder(也就是上次所說的Parent對象),所以在第二次點擊對話框的時候,再次綁定builder的時候,新的builder就不會接收我們自定義的view,因為它認為你已經綁定過了,此時就算你將之前的builder在對話框消受的同時銷毀掉也是沒用的,因為我們的view仍然會有綁定的過往記錄。
那麼該如何解決呢,我的解決方法是每次對話框完成任務消失時,就將view置為null,重新動態獲取一次布局,其實也就是為了實現近似於局部變量的效果,但要注意自定義布局的控件也要隨之findViewByid一遍,要不然你在第二次點擊對話框時候是無法對該控件影響的。
Android 動畫詳解之屬性動畫(Property Animation)(下)
Hello,大家好,最近好長時間沒有寫博客了,因為我決定辭職了。 廢話不多說,我們還是來看屬性動畫在上一篇 Android 動畫詳解之屬性動畫(Property Anim
Objective-C Runtime 解析(四)—— 在Category中添加屬性
在OC中,我們可以通過Category 對已有的類進行擴展,這得益於OC的Runtime機制,讓類可以‘動態’的添加方法以及實現。但是,在Cate
Android下拉刷新完全解析,教你如何一分鐘實現下拉刷新功能(附源碼)
最近項目中需要用到ListView下拉刷新的功能,一開始想圖省事,在網上直接找一個現成的,可是嘗試了網上多個版本的下拉刷新之後發現效果都不怎麼理想。有些是因為功能不完整或
Android學習之基於隱式的Intent的通訊
Intent隱式通訊Intent對象可以向操作系統描述我們需要處理的任務。使用顯式intent,我們需明確地告訴操作系統要啟動的activity類名。下面是之前創建過的顯