Android 自定义 ListPreference 只允许 5 个项目

Android Custom ListPreference only allow 5 items

我正在 this 示例的后面创建自定义 ListPreference。

我已经实现了它并且有效。但我最多只能向 ListPreference 添加 5 个项目。如果我添加 7 个项目,它们会出现在列表中,但当我单击它时,它什么也不做,只是关闭 ListPref 对话框并 return 到 pref 屏幕

public class IconPickerPreference extends ListPreference {

private class CustomListPreferenceAdapter extends ArrayAdapter<IconItem> {

    private Context context;
    private List<IconItem> icons;
    private int resource;

    public CustomListPreferenceAdapter(Context context, int resource, List<IconItem> objects) {
        super(context, resource, objects);
        this.context = context;
        this.resource = resource;
        this.icons = objects;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        ViewHolder holder;

        if (convertView == null) {
            LayoutInflater inflater = (LayoutInflater) context
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = inflater.inflate(resource, parent, false);

            holder = new ViewHolder();
            holder.iconName = (TextView) convertView
                    .findViewById(R.id.iconName);
            holder.iconImage = (ImageView) convertView
                    .findViewById(R.id.iconImage);
            holder.radioButton = (RadioButton) convertView
                    .findViewById(R.id.iconRadio);
            holder.position = position;

            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        holder.iconName.setText(icons.get(position).name);

        int identifier = context.getResources().getIdentifier(
                icons.get(position).file, "drawable",
                context.getPackageName());
        holder.iconImage.setImageResource(identifier);

        holder.radioButton.setChecked(icons.get(position).isChecked);

        convertView.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                ViewHolder holder = (ViewHolder) v.getTag();
                for (int i = 0; i < icons.size(); i++) {
                    if (i == holder.position)
                        icons.get(i).isChecked = true;
                    else
                        icons.get(i).isChecked = false;
                }
                getDialog().dismiss();
            }
        });

        return convertView;
    }

}

private static class IconItem {

    private String file;
    private boolean isChecked;
    private String name;

    public IconItem(CharSequence name, CharSequence file, boolean isChecked) {
        this(name.toString(), file.toString(), isChecked);
    }

    public IconItem(String name, String file, boolean isChecked) {
        this.name = name;
        this.file = file;
        this.isChecked = isChecked;
    }

}

private static class ViewHolder {
    protected ImageView iconImage;
    protected TextView iconName;
    protected int position;
    protected RadioButton radioButton;
}

private Context context;
private ImageView icon;

private CharSequence[] iconFile;
private CharSequence[] iconName;
private List<IconItem> icons;
private SharedPreferences preferences;
private Resources resources;
private String selectedIconFile, defaultIconFile;
private TextView summary;

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

    resources = context.getResources();
    preferences = PreferenceManager.getDefaultSharedPreferences(context);

    TypedArray a = context.getTheme().obtainStyledAttributes(attrs,
            R.styleable.attrs_icon, 0, 0);

    try {
        defaultIconFile = a.getString(R.styleable.attrs_icon_iconFile);
    } finally {
        a.recycle();
    }
}

private String getEntry(String value) {
    String[] entries = resources.getStringArray(R.array.iconName);
    String[] values = resources.getStringArray(R.array.iconFile);
    int index = Arrays.asList(values).indexOf(value);
    return entries[index];
}

@Override
protected void onBindView(View view) {
    super.onBindView(view);

    selectedIconFile = preferences.getString(
            resources.getString(R.string.custom_icon_key), defaultIconFile);

    icon = (ImageView) view.findViewById(R.id.iconSelected);
    updateIcon();

    summary = (TextView) view.findViewById(R.id.summary);
    summary.setText(getEntry(selectedIconFile));

}

@Override
protected void onDialogClosed(boolean positiveResult) {
    super.onDialogClosed(positiveResult);

    if (icons != null) {
        for (int i = 0; i < icons.size(); i++) {
            IconItem item = icons.get(i);
            if (item.isChecked) {

                Editor editor = preferences.edit();
                editor.putString(
                        resources.getString(R.string.custom_icon_key),
                        item.file);
                editor.apply();

                selectedIconFile = item.file;
                updateIcon();

                summary.setText(item.name);

                break;
            }
        }
    }

}

@Override
protected void onPrepareDialogBuilder(Builder builder) {

    builder.setNegativeButton("Cancel", null);
    builder.setPositiveButton(null, null);

    iconName = getEntries();
    iconFile = getEntryValues();

    if (iconName == null || iconFile == null
            || iconName.length != iconFile.length) {
        throw new IllegalStateException(
                "ListPreference requires an entries array "
                        + "and an entryValues array which are both the same length");
    }

    String selectedIcon = preferences.getString(
            resources.getString(R.string.custom_icon_key),
            resources.getString(R.string.icon_default));

    icons = new ArrayList<IconItem>();

    for (int i = 0; i < iconName.length; i++) {
        boolean isSelected = selectedIcon.equals(iconFile[i]) ? true
                : false;
        IconItem item = new IconItem(iconName[i], iconFile[i], isSelected);
        icons.add(item);
    }

    CustomListPreferenceAdapter customListPreferenceAdapter = new CustomListPreferenceAdapter(
            context, R.layout.item_picker, icons);
    builder.setAdapter(customListPreferenceAdapter, null);

}

private void updateIcon() {
    int identifier = resources.getIdentifier(selectedIconFile, "drawable",
            context.getPackageName());

    icon.setImageResource(identifier);
    icon.setTag(selectedIconFile);
}

字符串值

 <string-array name="iconName">
    <item>CHESTNUT</item>
    <item>POMEGRANATE</item>
    <item>OLD BRICK</item>
    <item>FLAMINGO</item>
    <item>SNUFF</item>
    <item>RAZZMATAZZ</item>
    <item>NEW YORK PINK</item>
</string-array>

<string-array name="iconFile">
    <item>ic_chestnut</item>
    <item>ic_pomegranate</item>
    <item>ic_old_brick</item>
    <item>ic_flamingo</item>
    <item>ic_snuff</item>
    <item>ic_razzmatazz</item>
    <item>ic_new_york_pink</item>
</string-array>

7 个 ic_ png 用于可绘制的上述项目...

日志未显示任何索引错误...

难倒:P

感谢任何帮助

提前致谢

我认为问题可能是因为您正在将位置保存在 ViewHolder 中,为什么要这样做?

将位置字段标记为最终,并直接在您的 OnClickListener 中使用它。

    @Override
        public View getView(final int position, View convertView, ViewGroup parent) {

   ... 

    @Override
        public void onClick(View v) {
            ViewHolder holder = (ViewHolder) v.getTag();
            for (int i = 0; i < icons.size(); i++) {
                if (i == position)
                    icons.get(i).isChecked = true;
                else
                    icons.get(i).isChecked = false;
            }
            getDialog().dismiss();
        }