AndroidX 中的自定义列表首选项

问题描述 投票:0回答:2

我已经自定义了我的Android应用程序设置页面,我使用API 21或26。我添加了一个CustomListPreference java类,它继承自ListPreference并将其集成到SettingActivity中。

但是,我重新列出了系统不起作用,因为SettingActivity具有从androidx.preference.PreferenceFragmentCompat继承的Setting片段,并且用于Setting Activity的包如下:

  • androidx.preference.Preference
  • androidx.preference.ListPreference
  • androidx.preference.PreferenceFragmentCompat

如果我为自定义 ListPreference 使用包 android.preference.Preference 和 android.preference.ListPreference,则当 Android 为设置活动创建对象时,我的所有代码都会停止工作。它在自定义 ListPreference 构造函数之后崩溃,并出现错误“错误膨胀类 com.signatact.doorbell.dialog.preference.AppListPreference”。 深入研究细节,我发现崩溃的原因是为设置活动创建新对象的最后一步是转换为 androidx.preference.Preference:

来自 PreferenceInflater.java

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

很明显,系统因在 android.preference.Preferenceandroidx.preference.Preference 之间进行转换而失败。

但是,如果我将自定义 ListPreference 文件实现移至 androidx,几乎所有我之前用于自定义的方法都不可用,这里列出了不可用的方法,我将自定义逻辑放在其中:

// 错误:方法不会覆盖其超类中的方法

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

看起来 Google 极大地改变了他们的 API,有人能告诉我如何在 AndroidX 中自定义 ListPreference 吗? 一般来说,我需要标准定制的东西如下:

  • 在一行中,我有一组自定义控件(3 个 - 2x 文本框和 1 个复选框) - 我使用列表的自定义 ArrayAdapter 为 onPrepareDialogBuilder 中的每一行构建自定义布局
  • 我需要动态更新 CustomListPreference 值。我在SettingActivity中的onResume中填充这些值
  • 当按下列表并选择新值时,我需要获得回调

我在这里只找到了一个针对我的案例的实用指南,如下:如何更改 ListPreference 对话框的外观,但它有限且简短。我分析了 AndroidX API,看起来我需要更多时间来提出解决方案,因此任何帮助/想法都会受到赞赏......

谢谢,弗拉德。

android-fragments android-activity settings androidx listpreference
2个回答
1
投票

只需重写 onClick() 函数即可弹出具有自定义布局的 AlertDialog。请记住在对话框中选择任何内容时调用 setValue()。

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

}

0
投票
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(getNegativeButtonText(), (dialog, which) -> dialog.dismiss())
            //.setNeutralButton(getNegativeButtonText(), (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;
    }

}
© www.soinside.com 2019 - 2024. All rights reserved.