How can I change the appearance of ListPreference Dialog
Asked Answered
M

4

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?

Mika answered 18/1, 2013 at 11:58 Comment(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.Mika
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.Mika
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.Exuviate
@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.Mika
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 timeExuviate
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.Mika
I see what you're saying, but I'm afraid that in that case you also disagree with this: stackoverflow.com/questions/how-to-askExuviate
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.Mika
I used the solution posted there: https://mcmap.net/q/1631321/-materialalertdialogbuilder-for-dialogpreferences-in-preferencefragmentsNaught
S
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.

Springclean answered 11/12, 2014 at 18:29 Comment(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 itemsCallbackSingleChoiceRadiolarian
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.Bugaboo
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!Radiolarian
No, a PopupMenu. It's very simple, see gist.github.com/deakjahn/b12f10e3951cf595664c.Bugaboo
you just saved my life....i was searching for last 3 days....n cant find any good solution....thanx a lot...Heaven
context can be replaced by getContext()Ellita
M
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.

Mattox answered 4/8, 2019 at 16:2 Comment(1)
Any idea on how to add a custom view holder? In my specific case, I'd like to replace the text with imagesMoller
S
2

Try the following links hope it may help you out

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

Example

Summation answered 18/1, 2013 at 12:51 Comment(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.Mika
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.Bugaboo
please fix dead links.Transept
B
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() {
      .......
    }

Bacchae answered 30/8, 2020 at 11:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.