Custom ListPreference with Dynamic Inputs

I need dynamic entries in a ListPreference, so I cannot use the usual way of setting up XML, which has a lot of material on the Internet. So far I have the following setting, as you can see below. The problem is that when I run this, I see a dialog with a title and a message, but no entries are displayed, although I know that the entries and values ​​are not empty (I know that my entries and values ​​are the same, but I would get an error if I hadn’t made the attached notes)

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); } } 
+6
source share
2 answers

Android: dialogMessage was a good starting point here, thanks @MH. to define it. Bellow is a simple setup that I ended up with, hope someone finds it useful.

 <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 } } 
+14
source

I see some potential possibilities for why it does not work as expected:

  • Where listObjects come listObjects ? Its presence indicates a member variable, but I do not see it being set or initialized anywhere. Make sure that you are not using an "empty" list to populate the dialog box, as this may cause it to be missing any items.

  • Alternatively, do you ever explicitly call setEntries(...) and setEntryValues(...) ? I ask because ListPreference does not use these two setters internally - it directly uses private member variables ( mEntries and mEntryValues ) for this. In other words, if you never call both functions yourself, no one will, meaning that arrays will never be set in a superclass; therefore, an empty dialogue.

  • As in my first observation: what is entries() ? It sits in onPrepareDialogBuilder , but it doesn't seem to be announced anywhere.

It might be better to start adding a few more code snippets, because based on everything that is missing, there is no way to tell where the exact cause of your problem is ...

Edit: Well, I created a quick test project to complete your steps. The solution to your problem is actually quite simple: get rid of the android:dialogMessage , and your list items should appear - I should add that I only tested this with the usual ListPreference .

The problem is easy to find if you look at the source of the ListPreference , with the extension from DialogPreference . In ShowDialog() you can find the following:

 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); 

Now, as you can see, it all depends on what onCreateDialog returns, because at the time onPrepareDialogBuilder is onPrepareDialogBuilder , the decision on what to display is already made. So let's look at this:

 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 } 

It seems to be trying to inflate the resource referenced by mDialogLayoutResId . If it is not installed or not available, it will return null , and only then a dialog message will be displayed. Content (list with items) will only be displayed if there is a valid layout. If you want both the content and the message to be displayed, you need to add a custom dialog using the android:dialogLayout , and add a TextView with android:id="@android:id/message" as id. In the case of ListPreference message will be shown below the default list.

Note that you do not need to extend the built-in ListPreference function to programmatically add records and values. A simple call to setEntries(...) and setEntryValues(...) on the ListPreference instance with the data you want to display.

Also, in the case of your DynamicPreference subclass, any behavior that you change can be overridden when you call super.onPrepareDialogBuilder(builder) completely at the end of your method. As mentioned earlier: I just tested this by default with ListPreference and it seems to work just fine and does whatever you request.

+3
source

Source: https://habr.com/ru/post/912532/


All Articles