編輯:關於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一遍,要不然你在第二次點擊對話框時候是無法對該控件影響的。
Hello,大家好,最近好長時間沒有寫博客了,因為我決定辭職了。 廢話不多說,我們還是來看屬性動畫在上一篇 Android 動畫詳解之屬性動畫(Property Anim
在OC中,我們可以通過Category 對已有的類進行擴展,這得益於OC的Runtime機制,讓類可以‘動態’的添加方法以及實現。但是,在Cate
最近項目中需要用到ListView下拉刷新的功能,一開始想圖省事,在網上直接找一個現成的,可是嘗試了網上多個版本的下拉刷新之後發現效果都不怎麼理想。有些是因為功能不完整或
Intent隱式通訊Intent對象可以向操作系統描述我們需要處理的任務。使用顯式intent,我們需明確地告訴操作系統要啟動的activity類名。下面是之前創建過的顯