2012-04-05 82 views
6

我需要ListPreference中的動態條目,所以我不能使用其中有大量在線材料的XML設置的傳統方式。到目前爲止,我已經進行了以下設置,如下圖所示。問題是,當我運行這個時,我看到標題和消息對話框,但沒有條目顯示,即使我知道條目和值不是空的(我知道我的條目和值是相同的,但如果我沒有,我會得到錯誤提供的條目)帶動態條目的自定義ListPreference


my.preference.DynamicPreference 
      android:title="@string/date_format" 
      android:dialogMessage="@string/profile_info_date_format" 
      android:entryValues="@array/date_format_values" 
      android:entries="@array/date_format_values" 

public class DynamicPreference extends ListPreference { 
    private int index; 

    public DynamicPreference(Context context, AttributeSet attrs) { 
     super(context, attrs); 
    } 

    public DynamicPreference(Context context) { 
     super(context); 
    } 

    @Override 
    protected void onPrepareDialogBuilder(AlertDialog.Builder builder) { 
     builder.setTitle(getTitle()); 
     builder.setMessage(getDialogMessage()); 
     builder.setSingleChoiceItems(entries(), -1, new DialogInterface.OnClickListener() { 
      @Override 
      public void onClick(DialogInterface dialogInterface, int i) { 

      } 
     }); 
     super.onPrepareDialogBuilder(builder); 
    } 

    @Override 
    public void setEntries(CharSequence[] sequence) { 
     CharSequence[] entries = listObjects().toArray(new CharSequence[listObjects().size()]); 
     super.setEntries(entries); 
    } 

    @Override 
    public void setEntryValues(CharSequence[] sequence) { 
     CharSequence[] values = getContext().getResources().getStringArray(R.string.date_format); 
     super.setEntryValues(values); 
    } 
}

回答

14

android:dialogMessage在這裏是個不錯的出發點,謝謝@MH。發現它。貝婁是簡單的設置我結束了,我希望有人會發現它有用

<my.preference.DynamicPreference 
     android:title="@string/local_time" 
     android:key="profile_info_local_time" 
     /> 

public class DynamicPreference extends ListPreference { 


    public DynamicPreference(Context context, AttributeSet attrs) { 
     super(context, attrs); 
    } 

    public DynamicPreference(Context context) { 
     super(context); 
    } 

    @Override 
    protected View onCreateDialogView() { 
     ListView view = new ListView(getContext()); 
     view.setAdapter(adapter()); 
     setEntries(entries()); 
     setEntryValues(entryValues()); 
     setValueIndex(initializeIndex()); 
     return view; 
    } 

    private ListAdapter adapter() { 
     return new ArrayAdapter(getContext(), android.R.layout.select_dialog_singlechoice); 
    } 

    private CharSequence[] entries() { 
     //action to provide entry data in char sequence array for list 
    } 

    private CharSequence[] entryValues() { 
     //action to provide value data for list 
    } 
} 
+0

這是唯一的方法來填補'ListPreference'以編程方式? – enzom83 2012-04-24 22:17:54

+0

@ enzom83這是基本的想法如何去做。我並不認爲自己是最好的,但就目前而言,你可以看到沒有任何其他職位關於它。你有問題嗎? – 2012-04-26 11:39:48

+1

@peter_budo:不需要擴展ListPreference,只需在'onCreate()'中設置一些初始值就可以了,然後重寫特定對象的'onPreferenceClick()'處理程序。下面是一個例子:http://stackoverflow.com/questions/6474707/how-to-fill-listpreference-dynamically-when-onpreferenceclick-is-triggered – ccpizza 2012-12-11 22:07:19

3

我能看到爲什麼預期它不工作的一些潛在的可能性:

  1. 來自哪裏listObjects?它的存在表明它是一個成員變量,但我沒有看到它在任何地方被設置或初始化。檢查你是否使用「空白」列表來填充對話框,因爲這可能導致其中沒有任何項目。

  2. 或者,您是否曾明確致電setEntries(...)setEntryValues(...)?我問,因爲ListPreference在內部不使用這兩個設置器 - 它直接使用私有成員變量(mEntriesmEntryValues)。換句話說,如果你不曾自己調用這兩個函數,那麼沒有人會這樣做,這意味着數組也不會被設置在超類上;因此是空的對話框。

  3. 與我第一次觀察相似:什麼是entries()?它坐在onPrepareDialogBuilder,但它似乎並沒有在任何地方宣佈。

也許這是最好的開始添加一些代碼片段,因爲根據該缺少的一切,有沒有辦法告訴您的問題的確切根源在於...

編輯:好吧,我建立了一個快速測試項目來跟蹤你的步驟。解決您的問題實際上相當簡單:擺脫android:dialogMessage屬性,並且您的列表項應顯示出來 - 我必須補充一點,我只用簡單的ListPreference進行了測試。

如果您查看ListPreference的源文件,並且從DialogPreference延伸,則可以輕鬆找到該問題。在ShowDialog()以下,可以發現:

285  View contentView = onCreateDialogView(); 
286  if (contentView != null) { 
287   onBindDialogView(contentView); 
288   mBuilder.setView(contentView); 
289  } else { 
290   mBuilder.setMessage(mDialogMessage); 
291  } 
292   
293  onPrepareDialogBuilder(mBuilder); 

現在,你可以看到這一切取決於什麼onCreateDialog回報,因爲當時onPrepareDialogBuilder被調用時,顯示已作出什麼決定。因此,讓我們看看這個:

336 protected View onCreateDialogView() { 
337  if (mDialogLayoutResId == 0) { 
338   return null; 
339  } 
340   
341  LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(
342    Context.LAYOUT_INFLATER_SERVICE); 
343  return inflater.inflate(mDialogLayoutResId, null); 
344 } 

看來它試圖通過膨脹引用mDialogLayoutResId資源。如果沒有設置或可用,它將返回null,只有這樣纔會顯示對話框「消息」。內容(包含項目的列表)只有在引用了有效的佈局時纔會顯示。如果要同時顯示內容和消息,則需要使用android:dialogLayout屬性添加自定義對話框佈局,並添加TextViewandroid:id="@android:id/message"作爲ID。在ListPreference的情況下,默認情況下,該消息將顯示在列表下方。

請注意,您需要而不是需要擴展內置ListPreference以便以編程方式添加條目和值。在ListPreference實例上簡單地調用setEntries(...)setEntryValues(...)並將其顯示出來。

此外,就您的DynamicPreference子類而言,在您的方法結束時一直調用super.onPrepareDialogBuilder(builder),您更改的任何行爲都可能會被覆蓋。正如前面提到的:我剛剛測試了這個默認ListPreference,這似乎工作正常,並做你所要求的一切。

+0

1)我沒有發佈的代碼的一部分,但我可以向你保證,它並返回數組的預期。 2)不要在任何地方打電話給他們,似乎我可能會誤解他們的用法。 3)與第一種情況一樣,我沒有發佈的代碼的一部分,並且它確實返回有效的對象 – 2012-04-05 23:00:01

+0

請查看我的答案中的編輯,以找出問題的原因和解決方案。原來你不需要繼承'ListPreference'。 :) – 2012-04-06 00:21:36

+0

是的,這確實沒有這個屬性。擴展DialogPreference的其他類到目前爲止使用沒有問題。我做了小搜索,似乎xml屬性android:dialogMessage ListPreference是在Android的bug列表http://code.google.com/p/android/issues/detail?id=4497 – 2012-04-07 08:01:48