Question

I'm using PreferenceFragment with its xml file as following

public class ReaderPreferences extends PreferenceFragment {
 @Override
 public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    addPreferencesFromResource(R.xml.preference);
 }
}

preference.xml:

<PreferenceCategory
    android:key="general"
    android:title="General" >

    <CheckBoxPreference
        android:defaultValue="true"
        android:key="notify_me"
        android:summary="Notify me about quote of the day in notifications"
        android:title="Get notification" />

    <Preference
        android:defaultValue=""
        android:key="time"
        android:summary="Change time to receive quote of the day"
        android:title="Time of Quote of the day" />

</PreferenceCategory>

<PreferenceCategory
    android:key="socials"
    android:title="Socials and sharing" >

    <Preference
        android:defaultValue=""
        android:key="facebook_login"
        android:summary="Sign in with your facebook account"
        android:title="Facebook login" />

    <Preference
        android:defaultValue=""
        android:key="facebook_logout"
        android:summary="Sign out facebook "
        android:title="Facebook logout" />

    <CheckBoxPreference
        android:defaultValue=""
        android:key="facebook_qotd"
        android:summary="Share the quote of the day on facebook once it is updated"
        android:title="Share QOTD on facebook" />

    <Preference
        android:defaultValue=""
        android:key="twitter_login"
        android:summary="Sign in with your twitter account"
        android:title="Twitter login" />

    <Preference
        android:defaultValue=""
        android:key="twitter_logout"
        android:summary="Sign out twitter"
        android:title="Twitter logout" />

    <CheckBoxPreference
        android:defaultValue=""
        android:key="twitter_qotd"
        android:summary="Share the quote of the day on twitter once it is updated"
        android:title="Share QOTD on twitter" />
</PreferenceCategory>

<PreferenceCategory
    android:key="other"
    android:title="Other" >

    <Preference
        android:defaultValue=""
        android:key="about"
        android:title="About" />
</PreferenceCategory>

How can I change the background color of this preference? And how can I set the font from .ttf file?

Hope anyone can help me. Thanks in advance.

Was it helpful?

Solution

This is one approach: you can create your own PrefrenceFragment with custom layout and ListView. Basically its a simple Fragment that returns View that contains ListView. By calling PreferenceScreen bind() method you can inflate PreferenceScreen content to your own ListView

public void bind (ListView listView)

Added in API level 1 Binds a ListView to the preferences contained in this PreferenceScreen via getRootAdapter(). It also handles passing list item clicks to the corresponding Preference contained by this PreferenceScreen. Parameters listView The list view to attach to.

public class CustomPreferenceFragment extends Fragment {
    CustomPreferenceFragment.java

    private PreferenceManager mPreferenceManager;

        /**
         * The starting request code given out to preference framework.
         */
        private static final int FIRST_REQUEST_CODE = 100;

        private static final int MSG_BIND_PREFERENCES = 0;
        private Handler mHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {

                    case MSG_BIND_PREFERENCES:
                        bindPreferences();
                        break;
                }
            }
        };
        private ListView lv;
        private int xmlId;


        //must be provided
        public CustomPreferenceFragment(){

        }



        @Override
        public void onDestroyView(){
            super.onDestroyView();
            ViewParent p = lv.getParent();
            if(p != null)
                ((ViewGroup)p).removeView(lv);
        }


        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup root, Bundle savedInstanceState){
            Bundle bundle = getArguments();
            if(bundle != null){
                xmlId = bundle.getInt("xml");
            }
            View mView = inflater.inflate(R.layout.preference_list_content, null);
            mPreferenceManager = onCreatePreferenceManager();
            lv = (ListView)mView.findViewById(R.id.listView1);
            lv.setBackgroundColor(Color.WHITE);
            lv.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);

            addPreferencesFromResource(xmlId);
            setHasOptionsMenu(true);
            postBindPreferences();
            return mView;
        }

        @Override
        public void onStop(){
            super.onStop();
            try{
                Method m = PreferenceManager.class.getDeclaredMethod("dispatchActivityStop");
                m.setAccessible(true);
                m.invoke(mPreferenceManager);
            }catch(Exception e){
                e.printStackTrace();
            }
        }

        @Override
        public void onDestroy() {
            super.onDestroy();
            lv = null;
            try{
                Method m = PreferenceManager.class.getDeclaredMethod("dispatchActivityDestroy");
                m.setAccessible(true);
                m.invoke(mPreferenceManager);
               }catch(Exception e){
                   e.printStackTrace();
               }
        }

        @Override
        public void onSaveInstanceState(Bundle outState) {
            outState.putInt("xml", xmlId);
            super.onSaveInstanceState(outState);

        }

        @Override
        public void onCreateOptionsMenu (Menu menu, MenuInflater inflater) {
            inflater.inflate(R.menu.main, menu);
            super.onCreateOptionsMenu(menu, inflater);
        }

        @Override
        public void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            try{
                Method m = PreferenceManager.class.getDeclaredMethod("dispatchActivityResult", int.class, int.class, Intent.class);
                m.setAccessible(true);
                m.invoke(mPreferenceManager, requestCode, resultCode, data);
            }catch(Exception e){
                e.printStackTrace();
            }
        }

        /**
         * Posts a message to bind the preferences to the list view.
         * <p>
         * Binding late is preferred as any custom preference types created in
         * {@link #onCreate(Bundle)} are able to have their views recycled.
         */
        private void postBindPreferences() {
            if (mHandler.hasMessages(MSG_BIND_PREFERENCES)) return;
            mHandler.obtainMessage(MSG_BIND_PREFERENCES).sendToTarget();
        }

        private void bindPreferences() {
            final PreferenceScreen preferenceScreen = getPreferenceScreen();
            if (preferenceScreen != null) {
                preferenceScreen.bind(lv);
            }
        }

        /**
         * Creates the {@link PreferenceManager}.
         * 
         * @return The {@link PreferenceManager} used by this activity.
         */
        private PreferenceManager onCreatePreferenceManager() {
            try{
                Constructor<PreferenceManager> c = PreferenceManager.class.getDeclaredConstructor(Activity.class, int.class);
                c.setAccessible(true);
                PreferenceManager preferenceManager = c.newInstance(this.getActivity(), FIRST_REQUEST_CODE);
                return preferenceManager;
            }catch(Exception e){
                e.printStackTrace();
                return null;
            }
        }

        /**
         * Returns the {@link PreferenceManager} used by this activity.
         * @return The {@link PreferenceManager}.
         */
        public PreferenceManager getPreferenceManager() {
            return mPreferenceManager;
        }

        /**
         * Sets the root of the preference hierarchy that this activity is showing.
         * 
         * @param preferenceScreen The root {@link PreferenceScreen} of the preference hierarchy.
         */
        public void setPreferenceScreen(PreferenceScreen preferenceScreen){
            try{
                Method m = PreferenceManager.class.getDeclaredMethod("setPreferences", PreferenceScreen.class);
                m.setAccessible(true);
                boolean result = (Boolean) m.invoke(mPreferenceManager, preferenceScreen);
                if (result && preferenceScreen != null) {
                    postBindPreferences();
                }
            }catch(Exception e){
                e.printStackTrace();
            }
        }

        /**
         * Gets the root of the preference hierarchy that this activity is showing.
         * 
         * @return The {@link PreferenceScreen} that is the root of the preference
         *         hierarchy.
         */
        public PreferenceScreen getPreferenceScreen(){
            try{
                Method m = PreferenceManager.class.getDeclaredMethod("getPreferenceScreen");
                m.setAccessible(true);
                return (PreferenceScreen) m.invoke(mPreferenceManager);
            }catch(Exception e){
                e.printStackTrace();
                return null;
            }
        }



        /**
         * Inflates the given XML resource and adds the preference hierarchy to the current
         * preference hierarchy.
         * 
         * @param preferencesResId The XML resource ID to inflate.
         */
        public void addPreferencesFromResource(int preferencesResId) {   
            try{
                Method m = PreferenceManager.class.getDeclaredMethod("inflateFromResource", Context.class, int.class, PreferenceScreen.class);
                m.setAccessible(true);
                PreferenceScreen prefScreen = (PreferenceScreen) m.invoke(mPreferenceManager, getActivity(), preferencesResId, getPreferenceScreen());
                setPreferenceScreen(prefScreen);
            }catch(Exception e){
                e.printStackTrace();
            }
        }

        /**
         * Finds a {@link Preference} based on its key.
         * 
         * @param key The key of the preference to retrieve.
         * @return The {@link Preference} with the key, or null.
         * @see PreferenceGroup#findPreference(CharSequence)
         */
        public Preference findPreference(CharSequence key) {
            if (mPreferenceManager == null) {
                return null;
            }
            return mPreferenceManager.findPreference(key);
        }




    }

preference_list_content.xml //Your custom ListView/Layout

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <ListView
        android:id="@+id/listView1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true" >

    </ListView>

</RelativeLayout>

Example how to use:

MainActivity.java

public class MainActivity extends Activity implements OnSharedPreferenceChangeListener{
    private SharedPreferences sharedPref;
    private CustomPreferenceFragment frag;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        frag = new CustomPreferenceFragment();
        Bundle bundle = new Bundle();
        bundle.putInt("xml", R.xml.prefs); //Your preference xml that you want to inflate
        frag.setArguments(bundle);
        getFragmentManager().beginTransaction().add(R.id.frameLayout, frag).commit();

        sharedPref = PreferenceManager.getDefaultSharedPreferences(this);


    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }



    @Override
    public void onResume(){
        super.onResume();
        sharedPref.registerOnSharedPreferenceChangeListener(this);
    }

    @Override
    public void onPause(){
        super.onPause();
        sharedPref.unregisterOnSharedPreferenceChangeListener(this);
    }

    @Override
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
            String key) {
        Toast.makeText(this, "Preferences changed, key: " + key, Toast.LENGTH_SHORT).show();

    }

}

prefs.xml goes under res/xml/ folder:

<?xml version="1.0" encoding="utf-8"?>
    <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" android:title="android custom prefs test">
        <Preference android:title="Preference Fragment " android:summary="With custom background" android:key="key_1"/>
        <CheckBoxPreference android:title="CheckBoxPref" android:summary="Preference with checkbox" android:key="key_2"/>
        <SwitchPreference android:title="SwitchPreference" android:summary="Prefrence with switch" android:key="key_3"/>
    </PreferenceScreen>

How can I change the background color of this preference?

In CustomPreferenceFragment.java:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup root, Bundle savedInstanceState){
    lv.setBackgroundColor(Color.WHITE);
}

Result: enter image description here

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top