Two Pane layout for tablets and single pane full list for phones

One Pref — For Android’s pride

Saurabh Arora
AndroidPub
Published in
3 min readNov 27, 2016

--

The Android SDK provides PreferenceActivity as a way to arrange all your preferences/settings. It offers two approaches:

On a small screen it may display only the headers as a single list when first launched. Selecting one of the header items will re-launch the activity with it only showing the PreferenceFragment of that header.

On a large screen in may display both the headers and current PreferenceFragment together as panes. Selecting a header item switches to showing the correct PreferenceFragment for that item.

But sometimes we do not have enough headers to warrant displaying a single list of headers on the phone. Instead we might prefer to have a single list of all the preferences on the phone without the two-step header and detail approach followed by the Android SDK. For tablets, a two pane approach is good.

Last weekend I spent some time trying to address this issue. The result was the OnePreference Library

Approach

Since Android recommends using PreferenceFragment (and it has huge benefits), I decided that it was something that I would need to build on. Also, fragments are essential in two pane layouts and so my approach uses the same fragments as well (to encourage code reusability) for the single list on phones.

Here I made a critical assumption:

The Header title and the PreferenceCategory title are generally the same.

Hence, I removed the Header title from the phone list and only used the PreferenceCategory from the PreferenceFragment. For phones, the approach then boiled down to using a vertically orientated LinearLayout to house all the PreferenceFragments.

<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fillViewport="true">

<LinearLayout
android:id="@+id/llContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" />

</android.support.v4.widget.NestedScrollView>

For tablets, I followed the approach used by AOSP and have a two pane layout for Header and the corresponding PreferenceFragment

<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">

<ListView
android:id="@+id/lvHeader"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginTop="8dp"
android:layout_weight="0.3" />

<FrameLayout
android:id="@+id/flContainer"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.7" />

</LinearLayout>

Usage

For basic usage, the library provides a OnePreferenceActivity out of the box. This activity works on both tablets and phones and provides a standard toolbar. The library is available on jcenter. You can include it in your project by including the following in your build.gradle

compile 'com.sa90.onepreference:library:1.0.1'

The first thing to do is include the activity in your manifest file.

<activity android:name="com.sa90.onepreference.OnePreferenceActivity" />

Next make sure that the theme for the OnePreferenceActivity is setup. Since OnePreference relies on support:preference-v14, you need to setup the default preference theme for the OnePreferenceActivity. You can also style the toolbar provided by the OnePreferenceActivity by using the onePref_toolbarStyle attribute.

<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
<item name="onePref_toolbarStyle">@style/AppTheme.AppBarOverlay</item>
</style>

Here I am using the PreferenceThemeOverlay.v14.Material to make sure that the preferences follow the Material Design guidelines.

Next you need a headers.xml file (just like the PreferenceActivity) along with their corresponding fragments.

The preference fragments should extend from BaseOnePreferenceFragment

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

<preference-headers xmlns:onepref="http://schemas.android.com/apk/res-auto">

<header onepref:fragment="com.sa90.onepreferencedemo.fragment.Header1Fragment"
onepref:title="@string/header1" />

<header onepref:fragment="com.sa90.onepreferencedemo.fragment.Header2Fragment"
onepref:title="@string/header2" />

<header onepref:fragment="com.sa90.onepreferencedemo.fragment.AboutFragment"
onepref:title="@string/header3" />

</preference-headers>

Lastly you can start the OnePreferenceActivity by using the OnePreferenceHelper

OnePreferenceHelper.startActivity(@XmlRes int headerRes, String title, Activity callingActivity)

For other scenarios such as using your own layout file, or manipulating headers layout, or adding and removing headers and fragments programatically, head over to the Github Repo and check out the Wiki. I’ll continue to support this library and add more features such as providing the option to use headers on phones as well.

--

--