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?

CopsOnRoad
  • 237,138
  • 77
  • 654
  • 440
Esthon Medeiros
  • 79
  • 1
  • 2
  • 4
  • 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. – Esthon Medeiros Jan 18 '13 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. – Esthon Medeiros Jan 18 '13 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](http://blog.350nice.com/wp/archives/240) 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. – Matt Taylor Jan 18 '13 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. – Esthon Medeiros Jan 20 '13 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 – Matt Taylor Jan 21 '13 at 09:20
  • OK Matt, I respect your opinion that is different from mine, and I don't want to create controversy, this is not the forum. Simply, I just like to read a question directly and objectively without any other subject. Also, I expected the people to answer know the subject before, so, it is only a matter of answer or do a little research to refine the answer. But you have the power of vote, I don't, you decide. – Esthon Medeiros Jan 21 '13 at 10:01
  • I see what you're saying, but I'm afraid that in that case you also disagree with this: http://stackoverflow.com/questions/how-to-ask – Matt Taylor Jan 21 '13 at 10:57
  • Well, I know and read this text before, and I totally agree with it and in my view my post is totally coherent with it, but as I said before, people are different and think different, I respect your opinion, I think you could open your mind a bit, but let's stop this because this is not the right forum, OK? Thanks a lot. – Esthon Medeiros Jan 21 '13 at 11:45
  • I used the solution posted there: https://stackoverflow.com/a/61424867/3969362 – Slion Oct 26 '21 at 16:28

4 Answers4

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.

Gábor
  • 9,466
  • 3
  • 65
  • 79
  • 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 Dec 14 '14 at 15:26
  • Also note that although this technically works, Google no longer wants us to do this. The design guide (http://www.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 Dec 15 '14 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 Dec 15 '14 at 18:36
  • 1
    No, a PopupMenu. It's *very* simple, see https://gist.github.com/deakjahn/b12f10e3951cf595664c. – Gábor Dec 15 '14 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 Sep 06 '16 at 09:08
  • `context` can be replaced by `getContext()` – LCZ Dec 14 '20 at 12:57
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.

Nantoka
  • 4,174
  • 1
  • 33
  • 36
2

Try the following links hope it may help you out

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

Example

Janmejoy
  • 2,721
  • 1
  • 20
  • 38
  • 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. – Esthon Medeiros Jan 18 '13 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 Dec 11 '14 at 12:51
  • please fix dead links. – User9211 Jun 11 '21 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() {
      .......
    }