2012-04-05 81 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