Browse Source

Release 0.6.5.2. Fixed #361. Also fixed MaterialListPreference and some other list dialog logic.

Aidan Follestad 10 years ago
parent
commit
ac5bef0c4a

+ 2 - 2
library/build.gradle

@@ -9,7 +9,7 @@ android {
         minSdkVersion 8
         targetSdkVersion 22
         versionCode 1
-        versionName "0.6.5.1"
+        versionName "0.6.5.2"
     }
     lintOptions {
         abortOnError false
@@ -27,7 +27,7 @@ publish {
     userOrg = 'drummer-aidan'
     groupId = 'com.afollestad'
     artifactId = 'material-dialogs'
-    version = '0.6.5.1'
+    version = '0.6.5.2'
     description = 'A library for implementing Material design styled dialogs across all versions of Android.'
     website = 'https://github.com/afollestad/material-dialogs'
     issueTracker = "${website}/issues"

+ 2 - 0
library/src/main/java/com/afollestad/materialdialogs/MaterialDialog.java

@@ -686,6 +686,8 @@ public class MaterialDialog extends DialogBase implements View.OnClickListener,
                     dismiss();
                     // Don't allow the selection to be updated since the dialog is being dismissed anyways
                     allowSelection = false;
+                    // Update selected index and send callback
+                    mBuilder.selectedIndex = position;
                     sendSingleChoiceCallback(view);
                 } else if (mBuilder.alwaysCallSingleChoiceCallback) {
                     int oldSelected = mBuilder.selectedIndex;

+ 1 - 1
library/src/main/java/com/afollestad/materialdialogs/prefs/MaterialListPreference.java

@@ -55,11 +55,11 @@ public class MaterialListPreference extends ListPreference {
                 .icon(getDialogIcon())
                 .negativeText(getNegativeButtonText())
                 .items(getEntries())
+                .autoDismiss(true) // immediately close the dialog after selection
                 .itemsCallbackSingleChoice(preselect, new MaterialDialog.ListCallbackSingleChoice() {
                     @Override
                     public boolean onSelection(MaterialDialog dialog, View itemView, int which, CharSequence text) {
                         onClick(null, DialogInterface.BUTTON_POSITIVE);
-                        dialog.dismiss();
                         if (which >= 0 && getEntryValues() != null) {
                             String value = getEntryValues()[which].toString();
                             if (callChangeListener(value) && isPersistent())

+ 2 - 2
sample/build.gradle

@@ -8,8 +8,8 @@ android {
         applicationId "com.afollestad.materialdialogssample"
         minSdkVersion 9
         targetSdkVersion 22
-        versionCode 92
-        versionName "0.6.5.1"
+        versionCode 93
+        versionName "0.6.5.2"
     }
     lintOptions {
         abortOnError false

BIN
sample/sample.apk


+ 2 - 1
sample/src/main/java/com/afollestad/materialdialogssample/PreferenceActivity.java

@@ -2,10 +2,11 @@ package com.afollestad.materialdialogssample;
 
 import android.annotation.SuppressLint;
 import android.os.Bundle;
-import android.preference.PreferenceFragment;
 import android.support.v7.app.ActionBarActivity;
 import android.view.MenuItem;
 
+import com.afollestad.materialdialogssample.compat.PreferenceFragment;
+
 @SuppressLint("NewApi")
 public class PreferenceActivity extends ActionBarActivity {
 

+ 334 - 0
sample/src/main/java/com/afollestad/materialdialogssample/compat/PreferenceFragment.java

@@ -0,0 +1,334 @@
+package com.afollestad.materialdialogssample.compat;
+
+import android.content.Intent;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.preference.Preference;
+import android.preference.PreferenceGroup;
+import android.preference.PreferenceManager;
+import android.preference.PreferenceScreen;
+import android.support.v4.app.Fragment;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnKeyListener;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.ListView;
+
+import com.afollestad.materialdialogssample.R;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+public abstract class PreferenceFragment extends Fragment implements
+        PreferenceManagerCompat.OnPreferenceTreeClickListener {
+
+    private static final String PREFERENCES_TAG = "android:preferences";
+
+    private PreferenceManager mPreferenceManager;
+    private ListView mList;
+    private boolean mHavePrefs;
+    private boolean mInitDone;
+
+    /**
+     * The starting request code given out to preference framework.
+     */
+    private static final int FIRST_REQUEST_CODE = 100;
+
+    private static final int MSG_BIND_PREFERENCES = 1;
+    private Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+
+                case MSG_BIND_PREFERENCES:
+                    bindPreferences();
+                    break;
+            }
+        }
+    };
+
+    final private Runnable mRequestFocus = new Runnable() {
+        public void run() {
+            mList.focusableViewAvailable(mList);
+        }
+    };
+
+    /**
+     * Interface that PreferenceFragment's containing activity should
+     * implement to be able to process preference items that wish to
+     * switch to a new fragment.
+     */
+    public interface OnPreferenceStartFragmentCallback {
+        /**
+         * Called when the user has clicked on a Preference that has
+         * a fragment class name associated with it.  The implementation
+         * to should instantiate and switch to an instance of the given
+         * fragment.
+         */
+        boolean onPreferenceStartFragment(PreferenceFragment caller, Preference pref);
+    }
+
+    @Override
+    public void onCreate(Bundle paramBundle) {
+        super.onCreate(paramBundle);
+        mPreferenceManager = PreferenceManagerCompat.newInstance(getActivity(), FIRST_REQUEST_CODE);
+        PreferenceManagerCompat.setFragment(mPreferenceManager, this);
+    }
+
+    @Override
+    public View onCreateView(LayoutInflater paramLayoutInflater, ViewGroup paramViewGroup,
+                             Bundle paramBundle) {
+        return paramLayoutInflater.inflate(R.layout.preference_list_fragment, paramViewGroup,
+                false);
+    }
+
+    @Override
+    public void onActivityCreated(Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+
+        if (mHavePrefs) {
+            bindPreferences();
+        }
+
+        mInitDone = true;
+
+        if (savedInstanceState != null) {
+            Bundle container = savedInstanceState.getBundle(PREFERENCES_TAG);
+            if (container != null) {
+                final PreferenceScreen preferenceScreen = getPreferenceScreen();
+                if (preferenceScreen != null) {
+                    preferenceScreen.restoreHierarchyState(container);
+                }
+            }
+        }
+    }
+
+    @Override
+    public void onStart() {
+        super.onStart();
+        PreferenceManagerCompat.setOnPreferenceTreeClickListener(mPreferenceManager, this);
+    }
+
+    @Override
+    public void onStop() {
+        super.onStop();
+        PreferenceManagerCompat.dispatchActivityStop(mPreferenceManager);
+        PreferenceManagerCompat.setOnPreferenceTreeClickListener(mPreferenceManager, null);
+    }
+
+    @Override
+    public void onDestroyView() {
+        mList = null;
+        mHandler.removeCallbacks(mRequestFocus);
+        mHandler.removeMessages(MSG_BIND_PREFERENCES);
+        super.onDestroyView();
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        PreferenceManagerCompat.dispatchActivityDestroy(mPreferenceManager);
+    }
+
+    @Override
+    public void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+
+        final PreferenceScreen preferenceScreen = getPreferenceScreen();
+        if (preferenceScreen != null) {
+            Bundle container = new Bundle();
+            preferenceScreen.saveHierarchyState(container);
+            outState.putBundle(PREFERENCES_TAG, container);
+        }
+    }
+
+    @Override
+    public void onActivityResult(int requestCode, int resultCode, Intent data) {
+        super.onActivityResult(requestCode, resultCode, data);
+
+        PreferenceManagerCompat.dispatchActivityResult(mPreferenceManager, requestCode, resultCode, data);
+    }
+
+    /**
+     * Returns the {@link PreferenceManager} used by this fragment.
+     * @return The {@link PreferenceManager}.
+     */
+    public PreferenceManager getPreferenceManager() {
+        return mPreferenceManager;
+    }
+
+    /**
+     * Sets the root of the preference hierarchy that this fragment is showing.
+     *
+     * @param preferenceScreen The root {@link PreferenceScreen} of the preference hierarchy.
+     */
+    public void setPreferenceScreen(PreferenceScreen preferenceScreen) {
+        if (PreferenceManagerCompat.setPreferences(mPreferenceManager, preferenceScreen) && preferenceScreen != null) {
+            mHavePrefs = true;
+            if (mInitDone) {
+                postBindPreferences();
+            }
+        }
+    }
+
+    /**
+     * Gets the root of the preference hierarchy that this fragment is showing.
+     *
+     * @return The {@link PreferenceScreen} that is the root of the preference
+     *         hierarchy.
+     */
+    public PreferenceScreen getPreferenceScreen() {
+        return PreferenceManagerCompat.getPreferenceScreen(mPreferenceManager);
+    }
+
+    /**
+     * Adds preferences from activities that match the given {@link Intent}.
+     *
+     * @param intent The {@link Intent} to query activities.
+     */
+    public void addPreferencesFromIntent(Intent intent) {
+        requirePreferenceManager();
+
+        setPreferenceScreen(PreferenceManagerCompat.inflateFromIntent(mPreferenceManager, intent, getPreferenceScreen()));
+    }
+
+    /**
+     * 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) {
+        requirePreferenceManager();
+
+        setPreferenceScreen(PreferenceManagerCompat.inflateFromResource(mPreferenceManager, getActivity(),
+                preferencesResId, getPreferenceScreen()));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen,
+                                         Preference preference) {
+        //if (preference.getFragment() != null &&
+        if (
+                getActivity() instanceof OnPreferenceStartFragmentCallback) {
+            return ((OnPreferenceStartFragmentCallback)getActivity()).onPreferenceStartFragment(
+                    this, preference);
+        }
+        return false;
+    }
+
+    /**
+     * 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);
+    }
+
+    private void requirePreferenceManager() {
+        if (mPreferenceManager == null) {
+            throw new RuntimeException("This should be called after super.onCreate.");
+        }
+    }
+
+    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(getListView());
+        }
+
+        if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1) {
+            // Workaround android bug for SDK 10 and below - see
+            // https://github.com/android/platform_frameworks_base/commit/2d43d283fc0f22b08f43c6db4da71031168e7f59
+            getListView().setOnItemClickListener(new AdapterView.OnItemClickListener() {
+                @Override
+                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+                    // If the list has headers, subtract them from the index.
+                    if (parent instanceof ListView) {
+                        position -= ((ListView)parent).getHeaderViewsCount();
+                    }
+
+                    Object item = preferenceScreen.getRootAdapter().getItem(position);
+                    if (!(item instanceof Preference))
+                        return;
+
+                    final Preference preference = (Preference)item;
+                    try {
+                        Method performClick = Preference.class.getDeclaredMethod(
+                                "performClick", PreferenceScreen.class);
+                        performClick.setAccessible(true);
+                        performClick.invoke(preference, preferenceScreen);
+                    } catch (InvocationTargetException e) {
+                    } catch (IllegalAccessException e) {
+                    } catch (NoSuchMethodException e) {
+                    }
+                }
+            });
+        }
+    }
+
+    public ListView getListView() {
+        ensureList();
+        return mList;
+    }
+
+    private void ensureList() {
+        if (mList != null) {
+            return;
+        }
+        View root = getView();
+        if (root == null) {
+            throw new IllegalStateException("Content view not yet created");
+        }
+        View rawListView = root.findViewById(android.R.id.list);
+        if (!(rawListView instanceof ListView)) {
+            throw new RuntimeException(
+                    "Content has view with id attribute 'android.R.id.list' "
+                            + "that is not a ListView class");
+        }
+        mList = (ListView)rawListView;
+        if (mList == null) {
+            throw new RuntimeException(
+                    "Your content must have a ListView whose id attribute is " +
+                            "'android.R.id.list'");
+        }
+        mList.setOnKeyListener(mListOnKeyListener);
+        mHandler.post(mRequestFocus);
+    }
+
+    private OnKeyListener mListOnKeyListener = new OnKeyListener() {
+
+        @Override
+        public boolean onKey(View v, int keyCode, KeyEvent event) {
+            Object selectedItem = mList.getSelectedItem();
+            if (selectedItem instanceof Preference) {
+                @SuppressWarnings("unused")
+                View selectedView = mList.getSelectedView();
+                //return ((Preference)selectedItem).onKey(
+                //        selectedView, keyCode, event);
+                return false;
+            }
+            return false;
+        }
+
+    };
+
+
+}

+ 214 - 0
sample/src/main/java/com/afollestad/materialdialogssample/compat/PreferenceManagerCompat.java

@@ -0,0 +1,214 @@
+package com.afollestad.materialdialogssample.compat;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.preference.Preference;
+import android.preference.PreferenceManager;
+import android.preference.PreferenceScreen;
+import android.util.Log;
+
+public class PreferenceManagerCompat {
+
+    private static final String TAG = PreferenceManagerCompat.class.getSimpleName();
+
+    /**
+     * Interface definition for a callback to be invoked when a
+     * {@link Preference} in the hierarchy rooted at this {@link PreferenceScreen} is
+     * clicked.
+     */
+    interface OnPreferenceTreeClickListener {
+        /**
+         * Called when a preference in the tree rooted at this
+         * {@link PreferenceScreen} has been clicked.
+         *
+         * @param preferenceScreen The {@link PreferenceScreen} that the
+         *                         preference is located in.
+         * @param preference       The preference that was clicked.
+         * @return Whether the click was handled.
+         */
+        boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference);
+    }
+
+    static PreferenceManager newInstance(Activity activity, int firstRequestCode) {
+        try {
+            Constructor<PreferenceManager> c = PreferenceManager.class.getDeclaredConstructor(Activity.class, int.class);
+            c.setAccessible(true);
+            return c.newInstance(activity, firstRequestCode);
+        } catch (Exception e) {
+            Log.w(TAG, "Couldn't call constructor PreferenceManager by reflection", e);
+        }
+        return null;
+    }
+
+    /**
+     * Sets the owning preference fragment
+     */
+    static void setFragment(PreferenceManager manager, PreferenceFragment fragment) {
+        // stub
+    }
+
+    /**
+     * Sets the callback to be invoked when a {@link Preference} in the
+     * hierarchy rooted at this {@link PreferenceManager} is clicked.
+     *
+     * @param listener The callback to be invoked.
+     */
+    static void setOnPreferenceTreeClickListener(PreferenceManager manager, final OnPreferenceTreeClickListener listener) {
+        try {
+            Field onPreferenceTreeClickListener = PreferenceManager.class.getDeclaredField("mOnPreferenceTreeClickListener");
+            onPreferenceTreeClickListener.setAccessible(true);
+            if (listener != null) {
+                Object proxy = Proxy.newProxyInstance(
+                        onPreferenceTreeClickListener.getType().getClassLoader(),
+                        new Class[]{onPreferenceTreeClickListener.getType()},
+                        new InvocationHandler() {
+                            public Object invoke(Object proxy, Method method, Object[] args) {
+                                if (method.getName().equals("onPreferenceTreeClick")) {
+                                    return Boolean.valueOf(listener.onPreferenceTreeClick((PreferenceScreen) args[0], (Preference) args[1]));
+                                } else {
+                                    return null;
+                                }
+                            }
+                        });
+                onPreferenceTreeClickListener.set(manager, proxy);
+            } else {
+                onPreferenceTreeClickListener.set(manager, null);
+            }
+        } catch (Exception e) {
+            Log.w(TAG, "Couldn't set PreferenceManager.mOnPreferenceTreeClickListener by reflection", e);
+        }
+    }
+
+    /**
+     * Inflates a preference hierarchy from the preference hierarchies of
+     * {@link Activity Activities} that match the given {@link Intent}. An
+     * {@link Activity} defines its preference hierarchy with meta-data using
+     * the {@link #METADATA_KEY_PREFERENCES} key.
+     * <p/>
+     * If a preference hierarchy is given, the new preference hierarchies will
+     * be merged in.
+     *
+     * @param queryIntent     The intent to match activities.
+     * @param rootPreferences Optional existing hierarchy to merge the new
+     *                        hierarchies into.
+     * @return The root hierarchy (if one was not provided, the new hierarchy's
+     * root).
+     */
+    static PreferenceScreen inflateFromIntent(PreferenceManager manager, Intent intent, PreferenceScreen screen) {
+        try {
+            Method m = PreferenceManager.class.getDeclaredMethod("inflateFromIntent", Intent.class, PreferenceScreen.class);
+            m.setAccessible(true);
+            PreferenceScreen prefScreen = (PreferenceScreen) m.invoke(manager, intent, screen);
+            return prefScreen;
+        } catch (Exception e) {
+            Log.w(TAG, "Couldn't call PreferenceManager.inflateFromIntent by reflection", e);
+        }
+        return null;
+    }
+
+    /**
+     * Inflates a preference hierarchy from XML. If a preference hierarchy is
+     * given, the new preference hierarchies will be merged in.
+     *
+     * @param context         The context of the resource.
+     * @param resId           The resource ID of the XML to inflate.
+     * @param rootPreferences Optional existing hierarchy to merge the new
+     *                        hierarchies into.
+     * @return The root hierarchy (if one was not provided, the new hierarchy's
+     * root).
+     * @hide
+     */
+    static PreferenceScreen inflateFromResource(PreferenceManager manager, Activity activity, int resId, PreferenceScreen screen) {
+        try {
+            Method m = PreferenceManager.class.getDeclaredMethod("inflateFromResource", Context.class, int.class, PreferenceScreen.class);
+            m.setAccessible(true);
+            PreferenceScreen prefScreen = (PreferenceScreen) m.invoke(manager, activity, resId, screen);
+            return prefScreen;
+        } catch (Exception e) {
+            Log.w(TAG, "Couldn't call PreferenceManager.inflateFromResource by reflection", e);
+        }
+        return null;
+    }
+
+    /**
+     * Returns the root of the preference hierarchy managed by this class.
+     *
+     * @return The {@link PreferenceScreen} object that is at the root of the hierarchy.
+     */
+    static PreferenceScreen getPreferenceScreen(PreferenceManager manager) {
+        try {
+            Method m = PreferenceManager.class.getDeclaredMethod("getPreferenceScreen");
+            m.setAccessible(true);
+            return (PreferenceScreen) m.invoke(manager);
+        } catch (Exception e) {
+            Log.w(TAG, "Couldn't call PreferenceManager.getPreferenceScreen by reflection", e);
+        }
+        return null;
+    }
+
+    /**
+     * Called by the {@link PreferenceManager} to dispatch a subactivity result.
+     */
+    static void dispatchActivityResult(PreferenceManager manager, int requestCode, int resultCode, Intent data) {
+        try {
+            Method m = PreferenceManager.class.getDeclaredMethod("dispatchActivityResult", int.class, int.class, Intent.class);
+            m.setAccessible(true);
+            m.invoke(manager, requestCode, resultCode, data);
+        } catch (Exception e) {
+            Log.w(TAG, "Couldn't call PreferenceManager.dispatchActivityResult by reflection", e);
+        }
+    }
+
+    /**
+     * Called by the {@link PreferenceManager} to dispatch the activity stop
+     * event.
+     */
+    static void dispatchActivityStop(PreferenceManager manager) {
+        try {
+            Method m = PreferenceManager.class.getDeclaredMethod("dispatchActivityStop");
+            m.setAccessible(true);
+            m.invoke(manager);
+        } catch (Exception e) {
+            Log.w(TAG, "Couldn't call PreferenceManager.dispatchActivityStop by reflection", e);
+        }
+    }
+
+    /**
+     * Called by the {@link PreferenceManager} to dispatch the activity destroy
+     * event.
+     */
+    static void dispatchActivityDestroy(PreferenceManager manager) {
+        try {
+            Method m = PreferenceManager.class.getDeclaredMethod("dispatchActivityDestroy");
+            m.setAccessible(true);
+            m.invoke(manager);
+        } catch (Exception e) {
+            Log.w(TAG, "Couldn't call PreferenceManager.dispatchActivityDestroy by reflection", e);
+        }
+    }
+
+    /**
+     * Sets the root of the preference hierarchy.
+     *
+     * @param preferenceScreen The root {@link PreferenceScreen} of the preference hierarchy.
+     * @return Whether the {@link PreferenceScreen} given is different than the previous.
+     */
+    static boolean setPreferences(PreferenceManager manager, PreferenceScreen screen) {
+        try {
+            Method m = PreferenceManager.class.getDeclaredMethod("setPreferences", PreferenceScreen.class);
+            m.setAccessible(true);
+            return ((Boolean) m.invoke(manager, screen));
+        } catch (Exception e) {
+            Log.w(TAG, "Couldn't call PreferenceManager.setPreferences by reflection", e);
+        }
+        return false;
+    }
+
+}

+ 89 - 0
sample/src/main/res/layout/preference_list_fragment.xml

@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+/*
+** Copyright 2010, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_height="fill_parent"
+    android:layout_width="fill_parent"
+    android:background="@android:color/transparent">
+
+    <ListView
+        android:id="@android:id/list"
+        android:layout_width="fill_parent"
+        android:layout_height="0px"
+        android:layout_weight="1"
+        android:paddingTop="0dip"
+        android:paddingBottom="@dimen/preference_fragment_padding_bottom"
+        android:paddingLeft="@dimen/preference_fragment_padding_side"
+        android:paddingRight="@dimen/preference_fragment_padding_side"
+        android:scrollbarStyle="@integer/preference_fragment_scrollbarStyle"
+        android:clipToPadding="false"
+        android:drawSelectorOnTop="false"
+        android:cacheColorHint="@android:color/transparent"
+        android:scrollbarAlwaysDrawVerticalTrack="true" />
+
+    <TextView
+        android:id="@android:id/empty"
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent"
+        android:padding="@dimen/preference_fragment_padding_side"
+        android:gravity="center"
+        android:visibility="gone" />
+
+    <RelativeLayout
+        android:id="@+id/button_bar"
+        android:layout_height="wrap_content"
+        android:layout_width="fill_parent"
+        android:layout_weight="0"
+        android:visibility="gone">
+
+        <Button
+            android:id="@+id/back_button"
+            android:layout_width="150dip"
+            android:layout_height="wrap_content"
+            android:layout_margin="5dip"
+            android:layout_alignParentLeft="true"
+            android:layout_alignParentStart="true"
+            android:text="@string/back_button_label" />
+
+        <LinearLayout
+            android:orientation="horizontal"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignParentRight="true"
+            android:layout_alignParentEnd="true">
+
+            <Button
+                android:id="@+id/skip_button"
+                android:layout_width="150dip"
+                android:layout_height="wrap_content"
+                android:layout_margin="5dip"
+                android:text="@string/skip_button_label"
+                android:visibility="gone" />
+
+            <Button
+                android:id="@+id/next_button"
+                android:layout_width="150dip"
+                android:layout_height="wrap_content"
+                android:layout_margin="5dip"
+                android:text="@string/next_button_label" />
+
+        </LinearLayout>
+
+    </RelativeLayout>
+
+</LinearLayout>

+ 9 - 0
sample/src/main/res/values-sw320dp/dimens.xml

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+    <!-- Preference fragment padding, bottom -->
+    <dimen name="preference_fragment_padding_bottom">0dp</dimen>
+    <!-- Preference fragment padding, sides -->
+    <dimen name="preference_fragment_padding_side">16dp</dimen>
+
+</resources>

+ 7 - 0
sample/src/main/res/values-v21/dimens.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+    <!-- Preference fragment padding, sides -->
+    <dimen name="preference_fragment_padding_side">8dp</dimen>
+
+</resources>

+ 7 - 0
sample/src/main/res/values-w720dp/dimens.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+    <!-- Preference fragment padding, sides -->
+    <dimen name="preference_fragment_padding_side">32dp</dimen>
+
+</resources>

+ 10 - 0
sample/src/main/res/values/dimens.xml

@@ -1,7 +1,17 @@
 <resources xmlns:tools="http://schemas.android.com/tools">
+
     <dimen name="activity_horizontal_margin" tools:ignore="UnusedResources">16dp</dimen>
     <dimen name="activity_vertical_margin" tools:ignore="UnusedResources">16dp</dimen>
     <dimen name="customTitle">14sp</dimen>
     <dimen name="customEntry">18sp</dimen>
     <dimen name="sample_button_spacing">2dp</dimen>
+
+    <!-- Preference fragment padding, bottom -->
+    <dimen name="preference_fragment_padding_bottom">0dp</dimen>
+    <!-- Preference fragment padding, sides -->
+    <dimen name="preference_fragment_padding_side">16dp</dimen>
+
+    <integer name="preference_fragment_scrollbarStyle">0x02000000</integer>
+    <!-- outsideOverlay -->
+
 </resources>

+ 7 - 0
sample/src/main/res/values/strings.xml

@@ -142,4 +142,11 @@
     <string name="multiChoiceLimited">Multi Choice (Limit Selections)</string>
     <string name="selection_limit_reached">Selection limit reached!</string>
 
+    <!--  Strings for possible PreferenceActivity Back/Next buttons -->
+    <string name="back_button_label">Back</string>
+    <string name="next_button_label">Next</string>
+
+    <!-- Optional button to Skip a PreferenceActivity [CHAR LIMIT=20] -->
+    <string name="skip_button_label">Skip</string>
+
 </resources>