6

I would like to change the RadioButton that appears on ListPreference dialog for a check mark or something different, or none, is there a simple way to do this?

9
  • I tried to find an attribute to change this in the ListPreference definition in xml, also programatically, but I couldn't find any. Probably the only way to do this would be by creating a custom ListPreference... I tried this without success, but I would like to avoid this if there is another way. Commented Jan 18, 2013 at 12:18
  • Hi @Matt Taylor, have you a clue about this, that helps me to answer my question? As I put bellow and in my question, I am looking for a simple way to do this, avoiding create a custom ListPreference. I did a lot of research and didn't find an attribute or parameter for this. But if there's no other way, I will evaluate whether it is worth to create a custom class. Commented Jan 18, 2013 at 15:16
  • I've had a look, and it doesn't appear possible with the current setup of the ListPreference, but I've found a blog that looks promising, but I haven't had time to read through a lot of it. It looks like it should provide what you need. Commented Jan 18, 2013 at 15:31
  • @Matt Taylor, I already saw the link you put before, it doesn't answer my question. Also I don't agree with you that my question is useless. I think it is an important question. Also, the fact I didn't put the effort I did before to put this question doesn't prove that I didn't take it, so, I ask you to reconsider and revert your downgrade vote. Also, now, I think I know the answer of my question: there is no simple way (attribute, etc) to change the radio bottom of ListPreference, so to do this I would need to create a custom class. BTW, I took another approach and already solved my problem. Commented Jan 20, 2013 at 21:36
  • I'm glad that you solved your problem, but I'm standing by my downvote. Whether your did the research or not, you didn't show that you did. You didn't say what you tried, you didn't say what you'd done. I don't dispute the usefulness of your question in that people want to do it. I dispute the way in which you have asked it. Because you didn't say anything you did, I wasted some of my time in looking through the xml attributes to see if there was a way, I wasted my time looking for and reading through the blog which you had "already found". If you had elaborated, it would have saved me time Commented Jan 21, 2013 at 9:20

4 Answers 4

14

If you want to change the whole dialog, maybe to use a replacement dialog library like this material-dialogs package, you can use this replacement ListPreference:

import com.afollestad.materialdialogs.MaterialDialog;

public class MaterialListPreference extends ListPreference {
  private MaterialDialog.Builder mBuilder;
  private Context context;

  public MaterialListPreference(Context context) {
    super(context);
    this.context = context;
  }

  public MaterialListPreference(Context context, AttributeSet attrs) {
    super(context, attrs);
    this.context = context;
  }

  @Override
  protected void showDialog(Bundle state) {
    mBuilder = new MaterialDialog.Builder(context);
    mBuilder.title(getTitle());
    mBuilder.icon(getDialogIcon());
    mBuilder.positiveText(null);
    mBuilder.negativeText(getNegativeButtonText());
    mBuilder.items(getEntries());
    mBuilder.itemsCallback(new MaterialDialog.ListCallback() {
      @Override
      public void onSelection(MaterialDialog dialog, View itemView, int which, CharSequence text) {
        onClick(null, DialogInterface.BUTTON_POSITIVE);
        dialog.dismiss();

        if (which >= 0 && getEntryValues() != null) {
          String value = getEntryValues()[which].toString();
          if (callChangeListener(value))
            setValue(value);
        }
      }
    });

    final View contentView = onCreateDialogView();
    if (contentView != null) {
      onBindDialogView(contentView);
      mBuilder.customView(contentView);
    }
    else
      mBuilder.content(getDialogMessage());

    mBuilder.show();
  }

}

It doesn't do much, just the bare minimum to override the dialog display and selection callback parts. YMMV very slightly if you opt for a different dialog library but not too much, they tend to be more or less direct replacements for AlertDialog.

6
  • Was looking up how to do this with the exact use-case being this library. You are awesome! Just FYI, if you want it to show a radio button, you can figure out the value and find its index in entryValues at the beginning of showDialog, then use itemsCallbackSingleChoice
    – Zac Sweers
    Commented Dec 14, 2014 at 15:26
  • Also note that although this technically works, Google no longer wants us to do this. The design guide (google.com/design/spec/components/menus.html#menus-simple-menus) calls for a simple menu rather than a new modal dialogs in these cases now. That can be solved similarly easily, I have a replacement MenuPreference as well now to use in these situations.
    – Gábor
    Commented Dec 15, 2014 at 12:38
  • Would this be showing a dropdown spinner over the preference instead? Could you maybe share a code example of MenuPreference via gist? I'm very interested to see how that would look!
    – Zac Sweers
    Commented Dec 15, 2014 at 18:36
  • 1
    No, a PopupMenu. It's very simple, see gist.github.com/deakjahn/b12f10e3951cf595664c.
    – Gábor
    Commented Dec 15, 2014 at 18:47
  • you just saved my life....i was searching for last 3 days....n cant find any good solution....thanx a lot...
    – H Raval
    Commented Sep 6, 2016 at 9:08
5

After analyzing the source code of ListPreference in AndroidX I came to the conclusion that the simplest way is to write a Preference that inherits from ListPreference but generates it's own AlertDialog that you can customize in whatever way you want:

import android.app.AlertDialog
import android.content.Context
import android.util.AttributeSet
import androidx.preference.ListPreference
import com.my.app.R

class MyListPreference : ListPreference {

    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) : super(
        context,
        attrs,
        defStyleAttr
    )

    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)

    constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)

    constructor(context: Context?) : super(context)

    override fun onClick() {

        AlertDialog.Builder(context).setSingleChoiceItems(R.array.app_language, getValueIndex())
        { dialog, index->
            if(callChangeListener(entryValues[index].toString())){
                setValueIndex(index)
            }
            dialog.dismiss()
        }
            .setNegativeButton(R.string.cancel) { dialog, _  -> dialog.dismiss() }
            .show()
    }

    private fun getValueIndex() = context.resources.getStringArray(R.array.app_language).indexOf(value)
}

That way you can use your own style, title, icon and whatever else you can configure on an AlertDialog.

1
  • Any idea on how to add a custom view holder? In my specific case, I'd like to replace the text with images Commented Nov 11, 2020 at 15:33
2

Try the following links hope it may help you out

http://developer.android.com/guide/topics/ui/settings.html

Example

3
  • Thanks a lot for your comments and very good links. I studied a lot the developer link and the example2 before I put this question and they don't answer my question. Or are you saying there is no simple way to change this, unless I create a custom ListPreference? This is what I would like to avoid, because I would like to keep it very simple. I just check example3 and 4, although they are very interesting they are related to create a custom class, also I should use them as a base to develop my solution, as they do not show how to change the radio button in the ListPreference dialog. Commented Jan 18, 2013 at 15:09
  • Not that terribly complicated, just grab the original source of ListPreference.java (Google for it, links come and go) and modify it to use your own dialog library. The original one uses AlertDialog but there any many more similar libraries, for example for the new, material design.
    – Gábor
    Commented Dec 11, 2014 at 12:51
  • please fix dead links.
    – User9211
    Commented Jun 11, 2021 at 13:23
0

if you want java code. try to following code.

public class SearchEngineListPreference extends ListPreference {
    private Context mContext;
    public SearchEngineListPreference(Context context) {
        super(context);
        mContext = context;
    }

    public SearchEngineListPreference(Context context, AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
    }

    @SuppressWarnings("New API")
    public SearchEngineListPreference(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mContext = context;
    }

    @SuppressWarnings("New API")
    public SearchEngineListPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        mContext = context;
    }

    @Override
    protected void onClick() {
        AlertDialog.Builder ab = new AlertDialog.Builder(mContext);
        ab.setCancelable(true);
        ab.setTitle(getTitle());
        String value = getValue();
        ab.setSingleChoiceItems(R.array.setting_entries_search_engine,
                findIndexOfValue(value),
                (dialog, index) -> {
                    CharSequence[] entryValues = getEntryValues();
                    if (callChangeListener(entryValues[index].toString())){
                        setValueIndex(index);
                    }
                    dialog.dismiss();
                }).setNeutralButton(mContext.getString(R.string.dialog_button_custom),
                (dialog, whichButton) -> {
                    dialog.dismiss();
                    showEditDialog();
                }).setNegativeButton(mContext.getString(R.string.dialog_button_negative),
                (dialog, whichButton) -> {
                    dialog.dismiss();
                });
        ab.show();
    }

    private void showEditDialog() {
      .......
    }

Not the answer you're looking for? Browse other questions tagged or ask your own question.