Saturday, November 11, 2017

Android Settings Series (part 1)

Welcome to this Series post.
In this series post, we are going to create a complete Settings for a productive app.

Basic overview of our final settings?

Our final settings contains-
  •  multiple preference screen 
In a previous post, I  cover android settings with a single preference screen (Android App Settings with Preference Fragment Compat).

we create 3 screen that's are-
  • General
  • Backup 
  • Advance
So we create multiple preference screen in the same XML file and after user click, we replace the fragment.
That's the deal,
Lets Start-



First Create an Activity name it Settings Activity.
SettingsActivity.java :
public class SettingsActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        ThemeUtils.initialize(this);

        setContentView(R.layout.activity_settings);
        Toolbar toolbar = (Toolbar) findViewById(R.id.settings_toolbar);
        setSupportActionBar(toolbar);

        if (getSupportActionBar() != null) {
            getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        }
    }
}

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

<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.blogspot.shudiptotrafder.soilscience.settings.SettingsActivity">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android:id="@+id/settings_toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/AppTheme.PopupOverlay" />

    </android.support.design.widget.AppBarLayout>


    <fragment
        android:layout_marginTop="?attr/actionBarSize"
        android:id="@+id/settings_fragment"
        android:name="com.blogspot.shudiptotrafder.soilscience.settings.SettingsFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</android.support.design.widget.CoordinatorLayout>

Now create a Settings Fragment. (I just provide the code, details you will find in this post " Android App Settings with Preference Fragment Compat )
public class SettingsFragment extends PreferenceFragmentCompat implements
        SharedPreferences.OnSharedPreferenceChangeListener {

    @Override
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {

        Preference preference = findPreference(key);

        if (preference != null) {

            if (!(preference instanceof CheckBoxPreference)) {
                String value = sharedPreferences.getString(preference.getKey(), "");
                setPreferenceSummery(preference, value);
            }
        }
    }

    @Override
    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {

        // Add 'general' preferences, defined in the XML file
        addPreferencesFromResource(R.xml.pref_general);

        SharedPreferences sharedPreferences = getPreferenceScreen().getSharedPreferences();

        PreferenceScreen preferenceScreen = getPreferenceScreen();

        int count = preferenceScreen.getPreferenceCount();

        for (int i = 0; i < count; i++) {
            Preference p = preferenceScreen.getPreference(i);
            if (!(p instanceof CheckBoxPreference)) {
                String value = sharedPreferences.getString(p.getKey(), "");
                setPreferenceSummery(p, value);
            }
        }
    }

    private void setPreferenceSummery(Preference preference, Object value) {

        String stringValue = value.toString();

        if (preference instanceof ListPreference) {
            // For list preferences, look up the correct display value in
            // the preference's 'entries' list (since they have separate labels/values).
            ListPreference listPreference = (ListPreference) preference;
            int prefIndex = listPreference.findIndexOfValue(stringValue);
            //same code in one line
            //int prefIndex = ((ListPreference) preference).findIndexOfValue(value);

            //prefIndex must be is equal or garter than zero because
            //array count as 0 to ....
            if (prefIndex >= 0) {
                listPreference.setSummary(listPreference.getEntries()[prefIndex]);
            }
        } else {
            // For other preferences, set the summary to the value's simple string representation.
            preference.setSummary(stringValue);
        }
    }

    //register and unregister on lifecycle
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getPreferenceScreen().getSharedPreferences()
                .registerOnSharedPreferenceChangeListener(this);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        getPreferenceScreen().getSharedPreferences()
                .unregisterOnSharedPreferenceChangeListener(this);
    }

}

pref_general.xml
<PreferenceScreen
    xmlns:android="http://schemas.android.com/apk/res/android">

    <PreferenceCategory android:title="Increase text size">

        <ListPreference
            android:defaultValue="@string/sTextModerateValue"
            android:entries="@array/textSizeLabel"
            android:entryValues="@array/textSizeValue"
            android:key="@string/textSizeKey"
            android:title="@string/textSizeLabel" />
    </PreferenceCategory>


    <PreferenceCategory
        android:summary="Your added word will be share with others."
        android:title="Share Data">

        <CheckBoxPreference
            android:defaultValue="true"
            android:key="@string/switchShare"
            android:summaryOff="@string/switchShareOFF"
            android:summaryOn="@string/switchShareON"
            android:title="@string/switchShareLabel" />

    </PreferenceCategory>

</PreferenceScreen>

arrays.xml
<resources>

  <string-array name="textSizeLabel">
  <item>@string/sTextSmallLabel</item>
  <item>@string/sTextMediumLabel</item>
  <item>@string/sTextModerateLabel</item>
  <item>@string/sTextLargeLabel</item>
  <item>@string/sTextExtraLargeLabel</item>
  </string-array>

  <string-array name="textSizeValue">
  <item>@string/sTextSmallValue</item>
  <item>@string/sTextMediumValue</item>
  <item>@string/sTextModerateValue</item>
  <item>@string/sTextLargeValue</item>
  <item>@string/sTextExtraLargeValue</item>
  </string-array>
</resources>

add the strings to your Strings.xml
 <!-- for settings -->
    <!-- ***************START************* -->

    <!-- ***************General Preference Screen************* -->
    <!-- text size -->
    <string name="sTextSmallLabel">Small</string>
    <string name="sTextMediumLabel">Medium</string>
    <string name="sTextModerateLabel">Moderate</string>
    <string name="sTextLargeLabel">Large</string>
    <string name="sTextExtraLargeLabel">Extra Large</string>

    <!-- text size value-->
    <string name="sTextSmallValue">15</string>
    <string name="sTextMediumValue">17</string>
    <string name="sTextModerateValue">20</string>
    <string name="sTextLargeValue">23</string>
    <string name="sTextExtraLargeValue">26</string>

    <string name="textSizeKey" translatable="false">textSize</string>
    <string name="textSizeLabel">Text Size</string>

    <!-- data share -->
    <string name="switchShare">ShareData</string>
    <string name="switchShareLabel">Share you added word</string>
    <string name="switchShareON">data will share</string>
    <string name="switchShareOFF">Data keep private</string>
    <string name="title_activity_about">About</string>

    <!-- ***************Backup Preference Screen************* -->
    <string name="bps_title">Backup data</string>
    <string name="bps_summery">Backup your data into your SD card</string>
    <string name="bps_key">backup</string>

    <!-- export -->
    <string name="bps_ex_fav_key">export_favourite</string>
    <string name="bps_ex_fav_title">Export Favourite List</string>
    <string name="bps_ex_fav_summery">Export your favourite list on your sd card</string>

    <string name="bps_ex_add_key">export_add</string>
    <string name="bps_ex_add_title">Export added word List</string>
    <string name="bps_ex_add_summery">Export your added word list on your sd card</string>

    <!-- Import -->
    <string name="bps_im_fav_key">import_favourite</string>
    <string name="bps_im_fav_title">Import Favourite List</string>
    <string name="bps_im_fav_summery">Import your favourite list on your sd card</string>

    <string name="bps_im_add_key">import_add</string>
    <string name="bps_im_add_title">Import added word List</string>
    <string name="bps_im_add_summery">Import your added word list on your sd card</string>

    <!-- ***************FINISH************* -->
Note: add all screen that will require other parts of this post.

add this method to your SettingsActivity.java class
@Override
    public boolean onOptionsItemSelected(MenuItem item) {

        //buy calling android.R.id.home

        int id = item.getItemId();

        if (id == android.R.id.home){
            onBackPressed();
        }

        return super.onOptionsItemSelected(item);
    }

Now our Settings will  work with only two element That is
  • list preference
  • check reference
Now add another preference Screen on the pref_general.xml
for backup screen
<PreferenceCategory
        android:summary="Import and export your data.
        You can backup your data into your SD Card"
        android:title="Backup Data">

        <PreferenceScreen android:key="@string/bps_key"
            android:title="@string/bps_title"
            android:summary="@string/bps_summery">
            <Preference
                android:key="favouriteBackup"
                android:summary="Export your favourite list on your sd card"
                android:title="Export Favourite List" />
        </PreferenceScreen>

    </PreferenceCategory>

for advance
 <PreferenceCategory android:title="Advance Settings"
        android:key="advance">

        <PreferenceScreen android:title="Advance"
            android:key="Advance"
            android:summary="some advance settings">
            <Preference
                android:key="favouriteBackup"
                android:summary="Import your added word list from your sd card"
                android:title="Import Favourite List" />

        </PreferenceScreen>

    </PreferenceCategory>

A bonus for you
if you want to launch an activity from your settings, you can do it by this way
<PreferenceCategory android:title="Links">

        <Preference android:title="About">

            <intent
                android:action="android.intent.action.VIEW"
                android:targetClass="com.blogspot.shudiptotrafder.soilscience.AboutActivity"
                android:targetPackage="com.blogspot.shudiptotrafder.soilscience" />

        </Preference>

    </PreferenceCategory>

in this case, I launch the about activity. So you need to change just targetClass and targetPackage
That launches the activity.

Full pref_general.xml
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
    xmlns:android="http://schemas.android.com/apk/res/android">

    <PreferenceCategory android:title="Increase text size">

        <ListPreference
            android:defaultValue="@string/sTextModerateValue"
            android:entries="@array/textSizeLabel"
            android:entryValues="@array/textSizeValue"
            android:key="@string/textSizeKey"
            android:title="@string/textSizeLabel" />

    </PreferenceCategory>


    <PreferenceCategory
        android:summary="Your added word will be share with others."
        android:title="Share Data">

        <CheckBoxPreference
            android:defaultValue="true"
            android:key="@string/switchShare"
            android:summaryOff="@string/switchShareOFF"
            android:summaryOn="@string/switchShareON"
            android:title="@string/switchShareLabel" />

    </PreferenceCategory>

    <PreferenceCategory
        android:summary="Import and export your data.
        You can backup your data into your SD Card"
        android:title="Backup Data">

        <PreferenceScreen android:key="@string/bps_key"
            android:title="@string/bps_title"
            android:summary="@string/bps_summery">
            <Preference
                android:key="favouriteBackup"
                android:summary="Export your favourite list on your sd card"
                android:title="Export Favourite List" />
        </PreferenceScreen>

    </PreferenceCategory>

    <PreferenceCategory android:title="Advance Settings"
        android:key="advance">

        <PreferenceScreen android:title="Advance"
            android:key="Advance"
            android:summary="some advance settings">
            <Preference
                android:key="favouriteBackup"
                android:summary="Import your added word list from your sd card"
                android:title="Import Favourite List" />

        </PreferenceScreen>

    </PreferenceCategory>

    <PreferenceCategory android:title="Links">

        <Preference android:title="About">

            <intent
                android:action="android.intent.action.VIEW"
                android:targetClass="com.blogspot.shudiptotrafder.soilscience.AboutActivity"
                android:targetPackage="com.blogspot.shudiptotrafder.soilscience" />

        </Preference>

</PreferenceScreen>

That's it:
In the next post, we will modify the fragment code and add also other fragment class.

Part 2: Android Settings Series (part 2)

Happy coding.

About Author:

I am Shudipto Trafder,
Since 2015, I write android code. I love to implement new ideas. I use java and also kotlin. Now I am learning Flutter. I love to learn new things and also love to share. And that is the main reason to run this blog.


Let's Get Connected: Facebook Twitter Linkedin Github

No comments :