Skip to content Skip to sidebar Skip to footer

Make A Normal Layout Look Like A Preferencescreen

The PreferenceScreen isn't good enough for me, since I've to add items to a Spinner. Those items need to come from a data list. I've got a custom ArrayAdapter that returns the name

Solution 1:

I tried to collect my first method - I hope I didn't forget to include some parts (aapart color definitions or statelist drawables, which is a trivial task to make your own)

Customizing the standard Preferences

/res/xml/prefs.xml

<?xml version="1.0" encoding="utf-8"?><PreferenceScreenxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"
    ><!-- ... --><PreferenceCategoryandroid:title="@string/pref_vibrate_cat"><CheckBoxPreferenceandroid:persistent="true"android:key="vibrate"android:title="@string/pref_vibrate_title"android:summary="@string/pref_vibrate_summ"android:defaultValue="true"android:layout="@layout/prefs"
        /></PreferenceCategory><!-- ... --><!-- Just to show how to use a custom preference (you must have the corresponding java Class in your project) --><PreferenceCategoryandroid:title="@string/pref_tts_cat"><com.dergolem.abc.CLS_Prefs_Multiandroid:persistent="true"android:key="tts"android:title="@string/pref_tts_title"android:summary="@string/nothing"android:dialogTitle="@string/pref_tts_dlg"android:dialogIcon="@android:drawable/sym_action_chat"android:entries="@array/prefs_tts_titles"android:entryValues="@array/prefs_tts_values"android:defaultValue="@array/prefs_tts_defaults"android:layout="@layout/prefs"android:widgetLayout="@layout/arr_dn"
        /></PreferenceCategory><!-- ... --></PreferenceScreen>

/res/layout/prefs.xml

<?xml version="1.0" encoding="utf-8"?><!-- Layout for a visually child-like Preference in a PreferenceActivity. --><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:baselineAligned="false"android:layout_width="match_parent"android:layout_height="wrap_content"android:minHeight="?android:attr/listPreferredItemHeight"android:gravity="center_vertical"android:paddingStart="16dp"android:paddingEnd="?android:attr/scrollbarSize"
    ><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="match_parent"android:minWidth="16dp"android:gravity="center"android:orientation="horizontal"
        ><ImageViewandroid:id="@+android:id/icon"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center_vertical"
        /></LinearLayout><RelativeLayoutandroid:layout_width="0dp"android:layout_height="wrap_content"android:layout_marginEnd="8dp"android:layout_marginTop="8dp"android:layout_marginBottom="8dp"android:layout_weight="1"
        ><TextViewandroid:id="@+android:id/displayTitle"android:layout_width="wrap_content"android:layout_height="wrap_content"android:singleLine="true"android:textAppearance="?android:attr/textAppearanceMedium"android:textStyle="bold"android:ellipsize="marquee"android:fadingEdge="horizontal"
        /><TextViewandroid:id="@+android:id/title"android:layout_width="wrap_content"android:layout_height="wrap_content"android:singleLine="true"android:textAppearance="?android:attr/textAppearanceMedium"android:textStyle="bold"android:ellipsize="marquee"android:fadingEdge="horizontal"
        /><TextViewandroid:id="@+android:id/summary"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_below="@android:id/title"android:layout_alignStart="@android:id/title"android:textAppearance="?android:attr/textAppearanceSmall"android:textColor="?android:attr/textColorSecondary"android:shadowColor="@color/white"android:shadowDx="1"android:shadowDy="1"android:shadowRadius="1"android:maxLines="4"
        /></RelativeLayout><!-- Preference should place its actual preference widget here. --><LinearLayoutandroid:id="@+android:id/widget_frame"android:layout_width="wrap_content"android:layout_height="match_parent"android:minWidth="48dp"android:gravity="center"android:orientation="vertical"
    /></LinearLayout>

/src/ACT_Prefs

package com.dergolem.abc;

/* ---------------------------------- Imports ------------------------------- */import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.content.res.Configuration;
import android.graphics.PixelFormat;
import android.os.Bundle;
import android.preference.PreferenceActivity;
import android.preference.PreferenceManager;
import android.widget.ListView;

publicfinalclassACT_Prefs// NO_UCD (use default)extendsPreferenceActivityimplementsOnSharedPreferenceChangeListener
{
    /* ------------------------------ Objects ------------------------------- */privateContextctx=null;

    /* ----------------------------- Overrides ------------------------------ */// Reload the Activity on rotation.@OverridepublicfinalvoidonConfigurationChanged(final Configuration cfg)
    {
        super.onConfigurationChanged(cfg);
        reStart();
    }
    /*
    Load the Preference Activity if the API LEvel is less than 11 or else load
    the PreferenceFragment.
    Needed workaround, since unfortunately Google didn't include the
    PreferenceFragment in the support library
    */@OverridepublicfinalvoidonCreate(final Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

        ctx = getApplicationContext();

        if (Build.VERSION.SDK_INT < 11)
        {
            createPreference_Activity();
        }
        else
        {
            createPreference_Fragment();
        }
    }
    @OverrideprotectedvoidonPause()
    {
        // Unregister OnSharedPreferenceChangeListener
        PreferenceManager.getDefaultSharedPreferences(ctx).
        unregisterOnSharedPreferenceChangeListener(this);

        // Call the base methodsuper.onPause();
    }
    @OverrideprotectedvoidonResume()
    {
        // Register OnSharedPreferenceChangeListener
        PreferenceManager.getDefaultSharedPreferences(ctx).
        registerOnSharedPreferenceChangeListener(this);

        // Fire the base methodsuper.onResume();
    }

    /* ------------------------------ Methods ------------------------------- */@SuppressWarnings("deprecation")privatefinalvoidcreatePreference_Activity()
    {
        // Set the Activity layout
        addPreferencesFromResource(R.xml.prefs);

        // Get the PreferenceScreen ListViewfinalListViewlvw= getListView();

        // Set the horizontal separator
        lvw.setDivider(getResources().getDrawable(R.drawable.list_divider));
        lvw.setDividerHeight((1));

        // Set the statelist selector
        lvw.setSelector(R.drawable.list_item_colors);

        // Remove the top and bottom fadings
        lvw.setVerticalFadingEdgeEnabled(false);
    }
    @SuppressLint("NewApi")privatefinalvoidcreatePreference_Fragment()
    {
        // Create the fragment.
        getFragmentManager().beginTransaction().replace
            (android.R.id.content, newFRG_Prefs()).commit();
        getFragmentManager().executePendingTransactions();
    }
}

/src/FRG_Prefs

package com.dergolem.abc;

/* ---------------------------------- Imports ------------------------------- */import android.annotation.SuppressLint;
import android.graphics.PixelFormat;
import android.preference.PreferenceFragment;
import android.view.View;
import android.widget.ListView;

@SuppressLint("NewApi")publicfinalclassFRG_PrefsextendsPreferenceFragment
{
    /* ----------------------------- Overrides ------------------------------ */@OverridepublicfinalvoidonResume()
    {
        super.onResume();
        addPreferencesFromResource(R.xml.prefs);

        init();
    }
    @OverridepublicfinalvoidonStop()
    {
        super.onStop();
        // Kill the prefence screen, so that it won't be recreated DUPLICATE.// HORRIBLE, but it's the only way to avoid the PreferenceScreen copycat.
        getActivity().finish();
    }

    /* ------------------------------ Methods ------------------------------- */privatefinalvoidinit()
    {
        finalViewv= getView();

        v.setPadding(paddingSize, 0, paddingSize, 0);

        // Get the PreferenceScreen ListViewfinalListViewlvw= (ListView) v.findViewById(android.R.id.list);

        // Set the horizontal separator
        lvw.setDivider(getResources().getDrawable(R.drawable.list_divider));
        lvw.setDividerHeight((1));

        // Set the state selector
        lvw.setSelector(R.drawable.list_item_colors);

        // Remove top and bottom fading
        lvw.setVerticalFadingEdgeEnabled(false);
    }
}

To show my Preferences:

startActivity(newIntent(ctx, ACT_Prefs.class));

ctx is defined as

Contextctx= getApplicationContext();

since I use it a lot, I define it once and for all.

[EDIT]

By request, I could add a method to make a Fake PreferenceScreen.

Solution 2:

The answer above is to difficult to implement, so I've designed my own version.

The layout xml

<?xml version="1.0" encoding="utf-8"?><RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:ads="http://schemas.android.com/apk/res-auto"android:layout_width="fill_parent"android:layout_height="fill_parent"android:minHeight="?android:attr/listPreferredItemHeight"android:gravity="center_vertical"><includelayout="@layout/toolbar"/><!-- This is a custom toolbar (or actionbar), and not necessary --><RelativeLayoutandroid:layout_width="fill_parent"android:layout_height="fill_parent"android:layout_below="@+id/toolbar"android:paddingRight="?android:attr/scrollbarSize"><ScrollViewandroid:layout_width="fill_parent"android:layout_height="fill_parent"android:layout_below="@layout/toolbar"android:id="@+id/scrollView" ><LinearLayoutandroid:orientation="vertical"android:layout_width="fill_parent"android:layout_height="fill_parent"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:textAppearance="?android:attr/textAppearanceSmall"android:text="@string/category_battery"android:id="@+id/category_misc"android:layout_marginLeft="@dimen/activity_settings_header_margin" /><ImageViewandroid:layout_width="fill_parent"android:layout_height="2dp"android:id="@+id/divider"android:layout_marginLeft="@dimen/activity_settings_margin"android:layout_below="@+id/category_misc"android:contentDescription="divider"android:scaleType="matrix"android:background="@android:drawable/divider_horizontal_bright"android:src="@android:drawable/divider_horizontal_bright" /><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"android:padding="@dimen/activity_settings_margin"><TextViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:id="@+id/textView"/><TextViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:id="@+id/textView"/><TextViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:id="@+id/textView"/><TextViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:id="@+id/textView"/><TextViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:id="@+id/textView"/><TextViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:id="@+id/textView"/></LinearLayout><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/category_calibration"android:textAppearance="?android:attr/textAppearanceSmall"android:id="@+id/category_subjects"android:layout_marginLeft="@dimen/activity_settings_header_margin"android:layout_below="@+id/batteryChargeState" /><ImageViewandroid:layout_width="fill_parent"android:layout_height="2dp"android:id="@+id/divider2"android:layout_marginLeft="@dimen/activity_settings_margin"android:layout_below="@+id/category_subjects"android:contentDescription="divider"android:scaleType="matrix"android:background="@android:drawable/divider_horizontal_bright"android:src="@android:drawable/divider_horizontal_bright" /><LinearLayoutandroid:layout_width="match_parent"android:layout_below="@+id/category_subjects"android:layout_centerVertical="true"android:layout_height="match_parent"android:padding="@dimen/activity_settings_margin"android:orientation="vertical"android:id="@+id/nextLayout"><TextViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:id="@+id/textView"/></LinearLayout></LinearLayout></ScrollView></RelativeLayout></RelativeLayout>

Toolbar xml:

<?xml version="1.0" encoding="utf-8"?><android.support.v7.widget.Toolbarxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:id="@+id/toolbar"app:theme="@style/ThemeOverlay.AppCompat.ActionBar"android:layout_width="match_parent"android:layout_height="wrap_content"android:minHeight="?attr/actionBarSize"android:background="?attr/colorPrimary"/>

Dimens xml:

<resources><!-- Default screen margins, per the Android Design guidelines. --><dimenname="activity_horizontal_margin">16dp</dimen><dimenname="activity_vertical_margin">16dp</dimen><dimenname="activity_settings_margin">24dp</dimen><dimenname="activity_settings_header_margin">18dp</dimen></resources>

Colors xml:

<?xml version="1.0" encoding="utf-8"?><resources><colorname="orange">#FDA432</color><colorname="orange_dark">#ffd17731</color></resources>

Just use the your way to store the Preferences. I've created a custom preference class that contains private keys so I can't post the code here without breaking it.

The advantage of using a custom layout like this is that you can add your own toolbar with this line as the first element of the first RelativeLayout.

To use the custom toolbar use this piece of code in your onCreate()

@OverrideprotectedvoidonCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);

                mTitle = mDrawerTitle = getTitle(); // This is for the title when you use a drawer

                mToolbar = (Toolbar) findViewById(R.id.toolbar); // This finds the toolbar you've specified using the <include> in the xmlsetSupportActionBar(mToolbar); // This sets the toolbar to be used

                mToolbar.setBackgroundColor(getResources().getColor(R.color.orange)); // This sets the color of the toolbarif (Build.VERSION.SDK_INT >= 21) {
                    getWindow().setStatusBarColor(getResources().getColor(R.color.orange_dark)); // This sets the color of the navigation bar to a darker orange as used for the toolbar, only when this is supported!
                }

                mToolbar.setNavigationIcon(R.mipmap.ic_launcher); // This makes the icon clickable, to open and close a drawer if you have one
    }

Post a Comment for "Make A Normal Layout Look Like A Preferencescreen"