简体   繁体   中英

Android: ListPreference as font size picker or accessing individual views of ListView items

What is the best way to create a ListPreference to be used as a "font size picker" like this? 字体大小选择器

Is there any way I can access individual views of items of the ListView in that preference and set them font size? Or do I have to create custom ListPreference with custom adapter?

Thanks in advance.

Solved. I needed to create custom ListPreference . I couldn't find a way how to access the ListView of the Dialog. Title area stays the same, only content area of the dialog has been changed. In onPrepareDialogBuilder(builder) I had to create a custom adapter for the ListView where I am able to set different font sizes.

public class FontSizeListPreference extends ListPreference {

    private int mClickedDialogEntryIndex;

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

    public FontSizeListPreference(Context context) {
        super(context);
    }

    @Override
    protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
        if(getEntries() == null || getEntryValues() == null){
            super.onPrepareDialogBuilder(builder);
            return;
        }

        ArrayAdapter<CharSequence> adapter = new ArrayAdapter<CharSequence>(getContext(), R.layout.preference_font_size_checked_tv, getEntries()) {
            @Override
            public View getView(int position, View convertView, ViewGroup parent) {
                float fontSizePx;
                CheckedTextView view = (CheckedTextView) convertView;
                if(view == null){
                    view = (CheckedTextView) View.inflate(getContext(), R.layout.preference_font_size_checked_tv, null);
                }
                switch (position){
                    case 0:
                        fontSizePx = getContext().getResources().getDimension(R.dimen.font_size_small_medium);
                        break;
                    case 2:
                        fontSizePx = getContext().getResources().getDimension(R.dimen.font_size_large_medium);
                        break;
                    case 1:default:
                        fontSizePx = getContext().getResources().getDimension(R.dimen.font_size_medium_medium);
                }
                view.setText(getEntries()[position]);
                view.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSizePx);
                return view;
            }
        };

        mClickedDialogEntryIndex = findIndexOfValue(getValue());
        builder.setSingleChoiceItems(adapter, mClickedDialogEntryIndex, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                mClickedDialogEntryIndex = which;
                FontSizeListPreference.this.onClick(dialog, DialogInterface.BUTTON_POSITIVE);
                dialog.dismiss();
            }
        });
        builder.setPositiveButton(null, null);
    }

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

        if(positiveResult && mClickedDialogEntryIndex >= 0 && getEntryValues() != null){
            String val = getEntryValues()[mClickedDialogEntryIndex].toString();
            if(callChangeListener(val)){
                setValue(val);
            }
        }
    }
}

And the item's layout defined in /res/layout/preference_font_size_checked_tv.xml :

<?xml version="1.0" encoding="utf-8"?>
<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/text1"
    android:layout_width="match_parent"
    android:layout_height="?android:attr/listPreferredItemHeightSmall"
    android:textAppearance="?android:attr/textAppearanceListItemSmall"
    android:gravity="center_vertical"
    android:checkMark="@null"
    android:drawableLeft="?android:attr/listChoiceIndicatorSingle"
    android:paddingLeft="?android:attr/listPreferredItemPaddingLeft"
    android:paddingRight="?android:attr/listPreferredItemPaddingRight"
    android:height="48dp"/>

I also wanted the indicator to be on the left side. That's why checkMark is set to null and drawableLeft to appropriate list choice single indicator.

Best way (without breaking any of the original ListPreference implementation):

@Override
protected void onPrepareDialogBuilder(Builder builder) {            

    ArrayAdapter<CharSequence> adapter = new ArrayAdapter<CharSequence>(getContext(), R.layout.preference_font_size_checked_tv, getEntries()) {
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            float fontSizePx;
            CheckedTextView view = (CheckedTextView) convertView;
            if(view == null){
                view = (CheckedTextView) View.inflate(getContext(), R.layout.preference_font_size_checked_tv, null);
            }
            switch (position){
                case 0:
                    fontSizePx = getContext().getResources().getDimension(R.dimen.font_size_small_medium);
                    break;
                case 2:
                    fontSizePx = getContext().getResources().getDimension(R.dimen.font_size_large_medium);
                    break;
                case 1:default:
                    fontSizePx = getContext().getResources().getDimension(R.dimen.font_size_medium_medium);
            }
            view.setText(getEntries()[position]);
            view.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSizePx);
            return view;
        }
    };
    builder.setAdapter(adapter, this);
    super.onPrepareDialogBuilder(builder);
}

@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
    preference.setSummary(getEntry());
    return true;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM