Make a normal layout look like a PreferenceScreen

2019-07-20 19:12发布

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 of the item, and when I click it. It returns the data that is contained within the item.

I want to use that same ArrayAdapter in a ListPreference (that's the spinner in the PreferenceScreen) but the ListPreference doesn't allow me to use a Adapter.

So, I want to recreate the look of the PreferenceScreen (with the PreferenceCategory's) without the use of the actual PreferenceScreen (and PreferenceCategory's)

Is this possible with a library? I haven't found one.

Thanks,

Tim

2条回答
ゆ 、 Hurt°
2楼-- · 2019-07-20 19:48

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"?>
<PreferenceScreen
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    >

    <!-- ... -->

    <PreferenceCategory android:title="@string/pref_vibrate_cat">
        <CheckBoxPreference
            android: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) -->
    <PreferenceCategory android:title="@string/pref_tts_cat">
        <com.dergolem.abc.CLS_Prefs_Multi
            android: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. -->
<LinearLayout
    xmlns: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"
    >
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:minWidth="16dp"
        android:gravity="center"
        android:orientation="horizontal"
        >
        <ImageView
            android:id="@+android:id/icon"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
        />
    </LinearLayout>
    <RelativeLayout
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginEnd="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginBottom="8dp"
        android:layout_weight="1"
        >
        <TextView
            android: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"
        />
        <TextView
            android: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"
        />
        <TextView
            android: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. -->
    <LinearLayout
        android: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;

public final class ACT_Prefs // NO_UCD (use default)
extends PreferenceActivity
implements OnSharedPreferenceChangeListener
{
    /* ------------------------------ Objects ------------------------------- */

    private Context ctx = null;

    /* ----------------------------- Overrides ------------------------------ */

    // Reload the Activity on rotation.
    @Override
    public final void onConfigurationChanged(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
    */
    @Override
    public final void onCreate(final Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

        ctx = getApplicationContext();

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

        // Call the base method
        super.onPause();
    }
    @Override
    protected void onResume()
    {
        // Register OnSharedPreferenceChangeListener
        PreferenceManager.getDefaultSharedPreferences(ctx).
        registerOnSharedPreferenceChangeListener(this);

        // Fire the base method
        super.onResume();
    }

    /* ------------------------------ Methods ------------------------------- */

    @SuppressWarnings("deprecation")
    private final void createPreference_Activity()
    {
        // Set the Activity layout
        addPreferencesFromResource(R.xml.prefs);

        // Get the PreferenceScreen ListView
        final ListView lvw = 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")
    private final void createPreference_Fragment()
    {
        // Create the fragment.
        getFragmentManager().beginTransaction().replace
            (android.R.id.content, new FRG_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")
public final class FRG_Prefs
extends PreferenceFragment
{
    /* ----------------------------- Overrides ------------------------------ */

    @Override
    public final void onResume()
    {
        super.onResume();
        addPreferencesFromResource(R.xml.prefs);

        init();
    }
    @Override
    public final void onStop()
    {
        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 ------------------------------- */

    private final void init()
    {
        final View v = getView();

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

        // Get the PreferenceScreen ListView
        final ListView lvw = (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(new Intent(ctx, ACT_Prefs.class));

ctx is defined as

Context ctx = 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.

查看更多
太酷不给撩
3楼-- · 2019-07-20 19:51

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"?>
<RelativeLayout xmlns: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">

<include layout="@layout/toolbar"/> <!-- This is a custom toolbar (or actionbar), and not necessary -->

    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_below="@+id/toolbar"
        android:paddingRight="?android:attr/scrollbarSize">

        <ScrollView
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:layout_below="@layout/toolbar"
            android:id="@+id/scrollView" >
            <LinearLayout
                android:orientation="vertical"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent">

                <TextView
                    android: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" />

                <ImageView
                    android: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" />

                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:orientation="vertical"
                    android:padding="@dimen/activity_settings_margin">

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:id="@+id/textView"/>

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:id="@+id/textView"/>

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:id="@+id/textView"/>

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:id="@+id/textView"/>

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:id="@+id/textView"/>

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:id="@+id/textView"/>

                </LinearLayout>

                <TextView
                    android: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" />

                <ImageView
                    android: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" />



                <LinearLayout android: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">


                    <TextView
                        android: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.Toolbar
    xmlns: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. -->
    <dimen name="activity_horizontal_margin">16dp</dimen>
    <dimen name="activity_vertical_margin">16dp</dimen>

    <dimen name="activity_settings_margin">24dp</dimen>
    <dimen name="activity_settings_header_margin">18dp</dimen>
</resources>

Colors xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="orange">#FDA432</color>
    <color name="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()

    @Override
        protected void onCreate(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 xml

                setSupportActionBar(mToolbar); // This sets the toolbar to be used

                mToolbar.setBackgroundColor(getResources().getColor(R.color.orange)); // This sets the color of the toolbar

                if (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
    }
查看更多
登录 后发表回答