Settings or Preferences Fragment

How to set up a settings Activity with a PreferenceFragment.

Create an Activity named SettingsActivity (including the activity_settings.xml layout file) with the following code:

public class SettingsActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_settings);
        ActionBar actionBar = this.getSupportActionBar();

        if (actionBar != null) {
            actionBar.setDisplayHomeAsUpEnabled(true); // Enables the up button in the Action Bar
        }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        if (id == android.R.id.home) {
            NavUtils.navigateUpFromSameTask(this); // Navigates up to parent activity (add supporting code to AndroidManifest.xml) OR...
            onBackPressed(); // ...replicates the function of the Back button (i.e. returns to last Activity) DO NOT ADD BOTH
        }
        return super.onOptionsItemSelected(item);
    }
}

To construct a menu with the option to enter the Settings fragment, create a new resource folder called 'menu' (if it doesn't already exist) and create 'xxxxx_menu.xml' (customise) as follows:

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

<menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto">

    <item android:id="@+id/action_settings" // Rename the id as necessary
     android:title="Settings" // Text that will appear in the menu listing - move to strings.xml
     android:orderInCategory="100" // Order of item in menu
     app:showAsAction="never" /> // Determine whether it will appear in the action bar (if room) as opposed to the dropdown menu

</menu>

Add the following code to your Activity to add the menu:

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.xxxxx_menu, menu); // Customise according to xml name
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if(item.getItemId() == R.id.action_settings) {
            Intent startSettingsActivity = new Intent(this, SettingsActivity.class);
            startActivity(startSettingsActivity);
            return true; // Deliver explicit Intent to start Settings Activity on click
        }
        return super.onOptionsItemSelected(item);
    }

Within the AndroidManifest.xml file, make the SettingsActivity a child of the main activity (DO NOT do this if you intend to access your Settings screen from multiple Activities as this will lock it to one parent Activity. Instead, leave out lines 12-15 and use the onBackPressed() option is your Settings Activity) and also make the main activity launch mode 'singleTop' to prevent the Activity being remade on returning:

        <activity
         android:name=".xxxxxActivity" // Customise
         android:launchMode="singleTop"> // Stops parent activity being remade on exiting Settings
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity // Register
         android:name=".SettingsActivity"
         android:label="Settings" // ADD THESE LINES. Move text value to strings.xml
         android:parentActivityName=".xxxxxActivity"> // ADD THESE LINES ONLY IF NAVIGATING TO PARENT. Customise
            <meta-data // ADD THESE LINES ONLY IF NAVIGATING TO PARENT
             android:name="android.support.PARENT_ACTIVITY" // ADD THESE LINES ONLY IF NAVIGATING TO PARENT
             android:value=".xxxxxActivity" /> // ADD THESE LINES ONLY IF NAVIGATING TO PARENT. Customise
        </activity>

In the res -> xml folder create a file called pref_xxxxx.xml (customise) to define the options within the Settings Fragment:

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

    <CheckBoxPreference // In this example we have a tickbox option android:defaultValue="true" // Default value of true/ticked
     android:key="show_text" // The reference of the value which can be changed
     android:summaryOff="@string/hidden" // Text to be shown when tickbox is not checked
     android:summaryOn="@string/shown" // Text to be shown when tickbox is checked
     android:title="@string/show_text" // Title of option
     />

</PreferenceScreen>

Create a class called SettingsFragment as follows (may require the addition of: implementation 'com.android.support:preference-v7:28.0.0' to your gradle file):

public class SettingsFragment extends PreferenceFragmentCompat {
    @Override
    public void onCreatePreferences(Bundle bundle, String s) {
        addPreferencesFromResource(R.xml.pref_xxxxx); // Add the preferences xml to display the options (customise)
    }
}

Adjust the activity_settings.xml file to reflect a Fragment layout:

<?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/activity_settings"
android:name="xxx.xxxxx.xxx.xxxxx.SettingsFragment" // Customise xxxxx with app name e.g. android.com.example.app
android:layout_width="match_parent"
android:layout_height="match_parent">
</fragment>

Add a theme in the styles.xml file:

        <item name="preferenceTheme">@style/PreferenceThemeOverlay</item> // App will crash without this addition

To make user changes to the Settings Fragment take effect, follow this post: Settings or Preferences - Making Changes In App

ud851-Exercises-student\Lesson06-Visualizer-Preferences\T06.01 & 02

Create Menu in ActionBar

Create a menu in the ActionBar. Can be in the main bar or under the menu icon.

Create 'main.xml' in 'menu' folder in 'res' if does not exist.
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <item android:id="@+id/action_search" // Add an item tag for each item in the menu
        android:title="@string/search"
        android:orderInCategory="1" // Order item will show in menu list
        app:showAsAction="ifRoom" // "ifRoom" will display menu item in ActionBar if room
        />

</menu>

Override onCreateOptionsMenu in Activity Java file.

@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}

Override onOptionsItemSelectedin Activity Java file.

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    int menuItem = item.getItemId();
    if (menuItem == R.id.action_search) { // Change 'action_search' to id of menu layout item
        Context context = MainActivity.this; // Change 'MainActivity' to current Activity
        CharSequence text = "Click handled"; // What happens when menu item is clicked
        int duration = Toast.LENGTH_SHORT; // What happens when menu item is clicked
        Toast toast = Toast.makeText(context, text, duration); // What happens when menu item is clicked
        toast.show(); // What happens when menu item is clicked
        return true;
    }
    return super.onOptionsItemSelected(item);
}

ud851-Exercises-student\Lesson02-GitHub-Repo-Search\T02.06-Exercise-AddPolish