Liatoss
Liatoss

Reputation: 41

Custom ListPreference in AndroidX

I have customized my Android Application Setting page, I use API 21 or 26. I have added a CustomListPreference java class which was inherited from ListPreference and integrated it into the SettingActivity.

But, I relisted the system doesn't work, as SettingActivity has Setting fragment inherited from androidx.preference.PreferenceFragmentCompat and packages used for the Setting Activity are as follows:

If I use packages android.preference.Preference and android.preference.ListPreference for my Custom ListPreference, all my code stops working when Android creates objects for the Setting Activity. It crashes just after the custom ListPreference constructorwith error "Error inflating class com.signatact.doorbell.dialog.preference.AppListPreference". Digging into details I found the reason of the crash as the last step for new object creation for Setting Activity is the cast to androidx.preference.Preference:

from PreferenceInflater.java:

import androidx.preference;
...
return (Preference) constructor.newInstance(args); // line 242

It is clear, the system fails with cast between android.preference.Preference and androidx.preference.Preference.

However, if I move my custom ListPreference file implementation to androidx, almost all method I used before for customization are not available, hereby is a list of methods which are not available, where I put my custom logic:

// Error(s): Methods don't override methods from its superclass

@Override
    protected void onPrepareDialogBuilder(AlertDialog.Builder builder)
...
@Override
    protected void onDialogClosed(boolean positiveResult)

It looks like Google dramatically changed their API, can anybody give idea how in AndroidX one can customize ListPreference? In general, I need standard customization things as follows:

I found only one practical guidance here for my case which is as follows: How can I change the appearance of ListPreference Dialog but it is limited and short. I analysed the AndroidX API and it looks like I need more time to come out with a solution and thus any help / idea appreciated...

Thx, Vlad.

Upvotes: 4

Views: 1579

Answers (2)

user1972814
user1972814

Reputation: 181

package your.package.name;

import android.app.AlertDialog;
import android.content.Context;
import android.util.AttributeSet;

import androidx.preference.ListPreference;

public class CustomListPreference extends ListPreference {

    public CustomListPreference (Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onClick() {
        // If you are targeting Material Design 3 supersede AlertDialog.Builder with MaterialAlertDialogBuilder
        AlertDialog.Builder builder = new AlertDialog.Builder(getContext()) // If you want to change the theme pass an R.style as the second argument
            .setSingleChoiceItems(getEntries(), getValueIndex(), (dialog, index) -> {
                if (callChangeListener(getEntryValues()[index].toString())) {
                    setValueIndex(index);
                }
                dialog.dismiss();
            })
            .setNegativeButton(getNegativeButtonText(), (dialog, which) -> dialog.dismiss())
            //.setPositiveButton(getPositiveButtonText(), (dialog, which) -> dialog.dismiss())
            //.setNeutralButton(getNeutralButtonText(), (dialog, which) -> dialog.dismiss())
            .setTitle(getTitle());
        AlertDialog dialog = builder.create();
        dialog.show();
    }

    private int getValueIndex() {
        CharSequence[] entryValues = getEntryValues();
        String value = getValue();
        for (int i = 0; i < entryValues.length; i++) {
            if (entryValues[i].equals(value)) {
                return i;
            }
        }
        return -1;
    }

}   

Upvotes: 0

KevinChung
KevinChung

Reputation: 51

Simply override onClick() function to pop out an AlertDialog with custom layout. Remember to call setValue() when anything selected in the dialog.

public class ColorPreference extends ListPreference {
    
    private CharSequence[] mEntries;
    private CharSequence[] mEntryValues;
    private String mValue;
    private String mSummary;
    
    private AlertDialog mDialog;

    public ColorPreference(Context context) {
        this(context, null);
    }

    public ColorPreference(Context context, AttributeSet attrs) {
        super(context, attrs);
        setDefaultValue(Options.DEFAULT_PRIMARY_COLOR_STRING);
    }


    @Override
    protected void onClick() {
        mEntries = getEntries();
        mEntryValues = getEntryValues();
        mSummary = getSummary().toString();
        mValue = getValue();
        
        mClickedDialogEntryIndex = findIndexOfValue(mValue);

        AlertDialog.Builder builder = new AlertDialog.Builder(getContext());

        builder.setSingleChoiceItems(new ColorAdapter(getContext(), R.layout.pref_color_item),mClickedDialogEntryIndex,null);
             
        mDialog = builder.create();

        mDialog.show();
    }

}

Upvotes: 1

Related Questions