简体   繁体   中英

How to set the font size of the item in dialog when I click ListPreference in android?

I have a ListPreference control in PreferenceScreen, I hope to change the font size of the item in ListPreference dialog, I try to add a style in ListPreference, but it seems it don't work, how can I do ? Thanks!

BTW, I have read the article custom row in a listPreference? , I think that it's too complex, what I need is only to change the font size of listed items in ListPreference dialog.

<ListPreference
style="@style/Text.ListPreference"/>

<style name="Text.ListPreference">
    <item name="android:textSize">15sp</item>
</style>





<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:robobunny="http://robobunny.com"
    android:key="AppPreference"
    android:summary="@string/PreferenceSummary"
    android:title="@string/Preference" >

     <PreferenceCategory android:title="@string/PreferenceCallCategory"
        android:layout="@layout/preference_category_layout">         

       <ListPreference
          android:key="CallOption"
          android:defaultValue="AllNumber"       
          android:entries="@array/CallAndSMSOption"
          android:entryValues="@array/CallAndSMSOption_values"       
          android:title="@string/CallOptionTitle"
          android:summary="@string/CallOptionSummary" 
          style="@style/myTextLarge"    
          android:layout="@layout/preference_layout"  
        /> 

      </PreferenceCategory> 


</PreferenceScreen>

To change the textSize of the title and summary you can simply use a custom layout:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="fill_parent"
              android:layout_height="fill_parent">

    <TextView android:id="@android:id/title"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:textSize="20sp"/>

    <TextView android:id="@android:id/summary"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:textSize="20sp"/>

</LinearLayout>

EDIT:

Customizing a dialog is a whole new story. Dialogs are annoyingly hard to configure.

To change the dialog items text size, unfortunately you'll have to use a custom adapter for the dialog. Here's how you can set it from your PreferenceActivity :

final ListPreference listPreference = (ListPreference) findPreference("CallOption");
if (listPreference == null) {
    Log.e("TAG", "Couldn't find the ListPreference");
    return;
}

listPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
    @Override
    public boolean onPreferenceClick(Preference preference) {
        AlertDialog dialog = (AlertDialog) listPreference.getDialog();
        if (dialog == null) {
            Log.e(TAG, "Couldn't find the dialog");
            return true;
        } else {
            Log.e(TAG, "Dialog found");
        }

        ListView listView = dialog.getListView();
        if (listView == null) {
            Log.e(TAG, "Couldn't find the ListView");
            return true;
        }

        listView.setAdapter(listAdapter);

        return true;
    }
});

Notes:

  • Your adapter will have to use CheckedTextView 's so they are checkable.
  • You'll probably have to make sure the setting is properly saved
    • (Hint: listView.setOnItemClickListener();
  • You might even want to use a custom ListPreference in the first place

Create this custom_pref_layout.xml:

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

    <TextView android:id="@+android:id/title"
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        android:textSize="40px"/>  

    <TextView android:id="@+android:id/summary"
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        android:textSize="26px"/>

</LinearLayout>

And add it into your desired preference object:

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    <PreferenceCategory
        android:title="My Category">             

        <CheckBoxPreference
            android:title="I am a Checkbox Preference"
            android:defaultValue="false"
            android:summary="This is a Checkbox preference"
            android:key="checkboxPref"
            android:layout="@layout/custom_pref_layout"/>

    </PreferenceCategory>
</PreferenceScreen>

I had to use a custom defined class that extends ListPreference. Then inside of that I had to create a custom adapter class just like you would for a ListView and set it to the builder using builder.setAdapter(). I also had to define listeners for both the radio buttons and the ListView rows that handled unchecking of the radio buttons and such. The only issues I still have are, my custom ListPreference has both an OK and a Cancel button where a ListPreference only has the cancel button. I don't know how to remove the OK button. Also, I can't get the rows to highlight when I click on them like they do in a regular ListPreference.

The java code for the custom ListPreference class. Be sure to mind things like your package name, the preference name (key), your entries and values for the ListPreference, and the names of your xml items.

 package your.package.here;

 import java.util.ArrayList;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.SharedPreferences;
 import android.graphics.Color;
 import android.preference.ListPreference;
 import android.preference.PreferenceManager;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.BaseAdapter;
 import android.widget.CompoundButton;
 import android.widget.RadioButton;
 import android.widget.TextView;
 import android.app.Dialog;
 import android.app.AlertDialog.Builder;

public class CustomListPreference extends ListPreference
{   
CustomListPreferenceAdapter customListPreferenceAdapter = null;
Context mContext;
private LayoutInflater mInflater;
CharSequence[] entries;
CharSequence[] entryValues;
ArrayList<RadioButton> rButtonList;
SharedPreferences prefs;
SharedPreferences.Editor editor;

public CustomListPreference(Context context, AttributeSet attrs)
{
    super(context, attrs);
    mContext = context;
    mInflater = LayoutInflater.from(context);
    rButtonList = new ArrayList<RadioButton>();
    prefs = PreferenceManager.getDefaultSharedPreferences(mContext);
    editor = prefs.edit();
}

@Override
protected void onPrepareDialogBuilder(Builder builder)
{
    entries = getEntries();
    entryValues = getEntryValues();

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

    customListPreferenceAdapter = new CustomListPreferenceAdapter(mContext);

    builder.setAdapter(customListPreferenceAdapter, new DialogInterface.OnClickListener()
    {
        public void onClick(DialogInterface dialog, int which)
        {

        }
    });
}

private class CustomListPreferenceAdapter extends BaseAdapter
{        
    public CustomListPreferenceAdapter(Context context)
    {

    }

    public int getCount()
    {
        return entries.length;
    }

    public Object getItem(int position)
    {
        return position;
    }

    public long getItemId(int position)
    {
        return position;
    }

    public View getView(final int position, View convertView, ViewGroup parent)
    {  
        View row = convertView;
        CustomHolder holder = null;

        if(row == null)
        {                                                                   
            row = mInflater.inflate(R.layout.custom_list_preference_row, parent, false);
            holder = new CustomHolder(row, position);
            row.setTag(holder);

            // do whatever you need here, for me I wanted the last item to be greyed out and unclickable
            if(position != 3)
            {
                row.setClickable(true);
                row.setOnClickListener(new View.OnClickListener()
                {
                    public void onClick(View v)
                    {
                        for(RadioButton rb : rButtonList)
                        {
                            if(rb.getId() != position)
                                rb.setChecked(false);
                        }

                        int index = position;
                        int value = Integer.valueOf((String) entryValues[index]);
                        editor.putInt("yourPref", value);

                        Dialog mDialog = getDialog();
                        mDialog.dismiss();
                    }
                });
            }
        }

        return row;
    }

    class CustomHolder
    {
        private TextView text = null;
        private RadioButton rButton = null;

        CustomHolder(View row, int position)
        {    
            text = (TextView)row.findViewById(R.id.custom_list_view_row_text_view);
            text.setText(entries[position]);
            rButton = (RadioButton)row.findViewById(R.id.custom_list_view_row_radio_button);
            rButton.setId(position);

            // again do whatever you need to, for me I wanted this item to be greyed out and unclickable
            if(position == 3)
            {
                text.setTextColor(Color.LTGRAY);
                rButton.setClickable(false);
            }

            // also need to do something to check your preference and set the right button as checked

            rButtonList.add(rButton);
            rButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
            {
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
                {
                    if(isChecked)
                    {
                        for(RadioButton rb : rButtonList)
                        {
                            if(rb != buttonView)
                                rb.setChecked(false);
                        }

                        int index = buttonView.getId();
                        int value = Integer.valueOf((String) entryValues[index]);
                        editor.putInt("yourPref", value);

                        Dialog mDialog = getDialog();
                        mDialog.dismiss();
                    }
                }
            });
        }
    }
}

}

The xml for my PreferenceActivity. This is not my full xml, took out al my other preference items for simplicity. Again, be sure to mind the package name, the custom ListPreference class must be referenced by the package name. Also mind the names of the preference and the array names that hold the entries and values.

<?xml version="1.0" encoding="utf-8"?>

<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android">

    <PreferenceCategory
            android:title="Your Title">

            <your.package.here.CustomListPreference
                android:key="yourPref"
                android:title="Your Title"
                android:dialogTitle="Your Title"
                android:summary="Your Summary"
                android:defaultValue="1"
                android:entries="@array/yourArray"
                android:entryValues="@array/yourValues"/>

    </PreferenceCategory>
    </PreferenceScreen>

My xml for the dialog's list view row. In the getView method be sure to use the name of this xml file in the line that inflates this.

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:paddingBottom="8dip"
android:paddingTop="8dip"
android:paddingLeft="10dip"
android:paddingRight="10dip">

<TableLayout
    android:id="@+id/custom_list_view_row_table_layout"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:stretchColumns="0">

    <TableRow
        android:id="@+id/custom_list_view_row_table_row"
        android:gravity="center_vertical"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">

        <TextView
            android:id="@+id/custom_list_view_row_text_view"
            android:textSize="22sp"
            android:textColor="#000000"  
            android:gravity="center_vertical"
            android:layout_width="160dip" 
            android:layout_height="40dip" />

        <RadioButton
            android:checked="false"
            android:id="@+id/custom_list_view_row_radio_button"/>
    </TableRow>
    </TableLayout>

   </LinearLayout>

Finally, under res/values here is my array.xml that contains the entry names and values for the ListPreference. Again, shortened mine for simplicity.

  <?xml version="1.0" encoding="utf-8"?>
  <resources> 
  <string-array name="yourArray">
    <item>Item 1</item>
    <item>Item 2</item>
    <item>Item 3</item>
    <item>Item 4</item>
  </string-array>

  <string-array name="yourValues">
    <item>0</item>
    <item>1</item>
    <item>2</item>
    <item>3</item>
 </string-array>
 </resources>

Using the FontManager class it is possible to implement a simple and nice font selection dialog on Android platform.

This is also one of the very few ListView implementation which implements the custom ListView by properly subclassing the DialogPreference the same way ListPreference does.

It may also be interesting for anyone who is looking for a way to draw the custom items in the ListPreference style.

To Know More

http://www.ulduzsoft.com/2012/01/fontpreference-dialog-for-android/

import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences.Editor;
import android.graphics.Typeface;
import android.preference.DialogPreference;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.CheckedTextView;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class FontPreference extends DialogPreference implements DialogInterface.OnClickListener {

    // Keeps the font file paths and names in separate arrays
    private List<String> m_fontPaths;
    private List<String> m_fontNames;

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

    @Override
    protected void onPrepareDialogBuilder(Builder builder) {
        super.onPrepareDialogBuilder(builder);
        // Get the fonts on the device
        HashMap<String, String> fonts = FontManager.enumerateFonts();
        m_fontPaths = new ArrayList<String>();
        m_fontNames = new ArrayList<String>();
        // Get the current value to find the checked item
        String selectedFontPath = getSharedPreferences().getString(getKey(), "");
        int idx = 0, checked_item = 0;
        for (String path : fonts.keySet()) {
            if (path.equals(selectedFontPath))
                checked_item = idx;
            m_fontPaths.add(path);
            m_fontNames.add(fonts.get(path));
            idx++;
        }
        // Create out adapter
        // If you're building for API 11 and up, you can pass builder.getContext
        // instead of current context
        FontAdapter adapter = new FontAdapter();
        builder.setSingleChoiceItems(adapter, checked_item, this);
        // The typical interaction for list-based dialogs is to have click-on-an-item dismiss the dialog
        builder.setPositiveButton(null, null);
    }

    public void onClick(DialogInterface dialog, int which) {
        if (which >= 0 && which < m_fontPaths.size()) {
            String selectedFontPath = m_fontPaths.get(which);
            Editor editor = getSharedPreferences().edit();
            editor.putString(getKey(), selectedFontPath);
            editor.commit();
            dialog.dismiss();
        }
    }


    // Font adaptor responsible for redrawing the item TextView with the appropriate font.
    // We use BaseAdapter since we need both arrays, and the effort is quite small.
    public class FontAdapter extends BaseAdapter {
        @Override
        public int getCount() {
            return m_fontNames.size();
        }

        @Override
        public Object getItem(int position) {
            return m_fontNames.get(position);
        }

        @Override
        public long getItemId(int position) {
            // We use the position as ID
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View view = convertView;
            // This function may be called in two cases: a new view needs to be created,
            // or an existing view needs to be reused
            if (view == null) {
                // Since we're using the system list for the layout, use the system inflater
                final LayoutInflater inflater = (LayoutInflater)
                        getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                // And inflate the view android.R.layout.select_dialog_singlechoice
                // Why? See com.android.internal.app.AlertController method createListView()
                view = inflater.inflate(android.R.layout.select_dialog_singlechoice, parent, false);
            }
            if (view != null) {
                // Find the text view from our interface
                CheckedTextView tv = (CheckedTextView) view.findViewById(android.R.id.text1);
                // Replace the string with the current font name using our typeface
                Typeface tface = Typeface.createFromFile(m_fontPaths.get(position));
                tv.setTypeface(tface);
                // If you want to make the selected item having different foreground or background color,
                // be aware of themes. In some of them your foreground color may be the background color.
                // So we don't mess with anything here and just add the extra stars to have the selected
                // font to stand out.
                tv.setText(m_fontNames.get(position));
            }
            return view;
        }
    }
}

end see this answer

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