In this article we will learn how to build Settings UI in android studio using Preference API. To clarify more, in app setting allows the user to change the functionality and behavior of your app. Furthermore, it can affect the background behavior such as change the app data synchronization. Moreover, settings can affect the app content and user interface.
AndroidX Preference API is the recommended way to integrate user settings in your app. Moreover, this library comes with material theme that provides a consistent user experience across devices and OS versions. In addition, the library manages user interface and interacts with storage.
Screen settings contains a Preference hierarchy which is defined as XML file. In order to build screen setting we need to use Androidx Preference dependency of this version “androidx.preference:preference:1.1.0” or higher.
// add this dependency in module level gradle file.
implementation 'androidx.preference:preference:1.1.1'
How to Create Preference hierarchy
The following image showing simple preference hierarchy in XML file.

This Preference hierarchy contains two Preference. The first is “SwitchPreferenceCompate” that allow the user to toggle the settings on or off. The second is basic preference without widget. In order to build this hierarchy you need to create a new resource layout file. This file must be placed in “res/xml” folder. the following image shows how to create this layout.

After that, you will note that a new folder generated in the “res” folder. Open the generated resource layout file and paste the following code and not that I used “androidx.preference.PreferenceScreen” tag. Moreover, we can not that each preference should have a unique key.
<?xml version="1.0" encoding="utf-8"?>
<androidx.preference.PreferenceScreen
xmlns:app="http://schemas.android.com/apk/res-auto">
<SwitchPreferenceCompat
app:key="notification"
app:title="Enable Message Notification" />
<Preference
app:key="feedback"
app:title="Send Feedback"
app:summary="Report technical issues or suggest new features"/>
</androidx.preference.PreferenceScreen>
After that, we need to inflate the hierarchy from the xml file. In order to do this step we need to create a new java class that inherits the “PreferenceFragmentCompat”. Then, provide the preference xml file in the overrided “onCreatePreferences” method as following.
//please make sure the names of the created files are the same in this code.
public class MyPreferenceAPI extends PreferenceFragmentCompat {
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
setPreferencesFromResource(R.xml.my_preference,rootKey);
}
}
In order to use the Preference fragment open main activity layout file and change the code as the following. I added a fram layout with id to replace the fragment with it.
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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=".MainActivity">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/fragment_Layout"/>
</FrameLayout>
Finally, in main activity java file we need to use the following code. After that run the app, you should see the above preference settings screen.
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.fragment_Layout, new MyPreferenceAPI())
.commit();
}
}
How to Organize Preference Settings Screen?
Large and complex settings can make it hard for a user to find a particular setting they want to modify. So that, the Preference Library can help you organize your settings screens better. You can group them with a Preference Category when you have several related Preferences on a single screen. Moreover, a Preference Category shows the title of the category and divides the category visually. The following XML code show how to use the preference category to organize settings.

<?xml version="1.0" encoding="utf-8"?>
<androidx.preference.PreferenceScreen
xmlns:app="http://schemas.android.com/apk/res-auto">
<PreferenceCategory
app:key="notifications_category"
app:title="Notifications">
<SwitchPreferenceCompat
app:key="notifications"
app:title="Enable message notifications"/>
</PreferenceCategory>
<PreferenceCategory
app:key="help_category"
app:title="Help">
<Preference
app:key="feedback"
app:summary="Report technical issues or suggest new features"
app:title="Send feedback"/>
</PreferenceCategory>
</androidx.preference.PreferenceScreen>
How to Spit your hierarchy into multiple screens?
You can display them separately on separate screens if you have a large number of preferences or different categories. Moreover, each display should have its own separate hierarchy as a PreferenceFragmentCompat. You can then connect the preferences to sub-screens containing corresponding preferences on your first screen.
In order to apply the separation, we need to create and new preference xml file for each sub screen as following.
<!--create a new preference screen xml file, name if notification and add this code-->
<?xml version="1.0" encoding="utf-8"?>
<androidx.preference.PreferenceScreen xmlns:app="http://schemas.android.com/apk/res-auto">
<PreferenceCategory
app:key="notifications_category"
app:title="Notifications">
<SwitchPreferenceCompat
app:key="notifications"
app:title="Enable message notifications"/>
</PreferenceCategory>
</androidx.preference.PreferenceScreen>
<?xml version="1.0" encoding="utf-8"?>
<!--create a new preference screen xml file, name if help and add this code-->
<PreferenceScreen
xmlns:app="http://schemas.android.com/apk/res-auto">
<PreferenceCategory
app:key="help_category"
app:title="Help">
<Preference
app:key="feedback"
app:summary="Report technical issues or suggest new features"
app:title="Send feedback"/>
</PreferenceCategory>
</PreferenceScreen>
Then update the my_preference xml file as following.
<?xml version="1.0" encoding="utf-8"?>
<androidx.preference.PreferenceScreen
xmlns:app="http://schemas.android.com/apk/res-auto">
<Preference
app:title="Notification"
app:key="notifications"
app:fragment="com.androidhands.preferenceapidemo.NotificationFragment"/>
<Preference
app:key="feedback"
app:title="Send feedback"
app:fragment="com.androidhands.preferenceapidemo.HelpFragment"/>
</androidx.preference.PreferenceScreen>
After that, you need to create two PreferenceFragmentCompat fragments.
import androidx.preference.PreferenceFragmentCompat;
public class NotificationFragment extends PreferenceFragmentCompat {
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
setPreferencesFromResource(R.xml.notification,rootKey);
}
}
import androidx.preference.PreferenceFragmentCompat;
public class HelpFragment extends PreferenceFragmentCompat {
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
setPreferencesFromResource(R.xml.help,rootKey);
}
}
The interface method (PreferenceFragmentCompat.OnPreferenceStartFragmentCallback.onPreferenceStartFragment()) is called when a user taps a Preference with the associated fragment. This method is where the new screen is displayed and the surrounding activity should be implemented. Add the implementation in the MyPreference Fragment as the following code.
public class MyPreferenceAPI extends PreferenceFragmentCompat implements PreferenceFragmentCompat.OnPreferenceStartFragmentCallback {
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
setPreferencesFromResource(R.xml.my_preference,rootKey);
}
@Override
public boolean onPreferenceStartFragment(PreferenceFragmentCompat caller, Preference pref) {
// Instantiate the new Fragment
final Bundle args = pref.getExtras();
final Fragment fragment = getActivity().getSupportFragmentManager().getFragmentFactory().instantiate(
getActivity().getClassLoader(),
pref.getFragment());
fragment.setArguments(args);
fragment.setTargetFragment(caller, 0);
// Replace the existing Fragment with the new Fragment
getActivity().getSupportFragmentManager().beginTransaction()
.replace(R.id.fragment_Layout, fragment)
.addToBackStack(null)
.commit();
return false;
}
}

Thank You