androidlistviewlistpreference

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? Font size picker

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.


Solution

  • 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.