PreferenceFragmentCompat

Для спрощення роботи з групою налаштувань Android надає спеціальний тип фрагмента - PreferenceFragmentCompat. Розглянемо як її використовувати.

Створимо новий проєкт і спочатку визначимо у файлі build.gradle потрібні залежності для роботи з PreferenceFragmentCompat:

implementation "androidx.fragment:fragment:1.3.6"
implementation "androidx.preference:preference:1.1.1"

Для визначення налаштувань додамо в папку res підпапку xml.

Потім у папку res/xml додамо новий файл, який назвемо settings.xml. І змінимо його таким чином.

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    <EditTextPreference
        android:key="login"
        android:summary="Введіть логін"
        android:title="Логін" />
    <CheckBoxPreference
        android:key="enabled"
        android:summary="Відображати логін"
        android:title="Відображати" />
</PreferenceScreen>

Налаштування в Android

В кореневому елементі PreferenceScreen встановлюються елементи EditTextPreference і CheckBoxPreference. Через кожен з цих елементів ми можемо взаємодіяти з певною налаштуванням.

Взагалі в даному випадку ми можемо використовувати ряд різних типів налаштувань:

  • EditTextPreference: використовується елемент EditText для введення текстового значення.
  • CheckBoxPreference: використовується елемент CheckBox для встановлення логічних значень true або false.
  • SwitchPreference: використовується елемент Switch для встановлення логічних значень true або false ("on" і "off").
  • RingtonePreference: використовує діалогове вікно для встановлення рінгтону зі списку рінгтонів для встановлення логічних значень true або false.
  • ListPreference: використовує список для вибору одного з попередньо визначених значень.
  • MultiSelectListPreference: також використовує список для вибору значень, але дозволяє вибирати кілька елементів.

Для кожного елемента налаштування необхідно визначити, як мінімум, три атрибути:

  • android:key: встановлює ключ налаштування в SharedPreferences.
  • android:title: назва налаштування для користувача.
  • android:summary: короткий опис цього налаштування для користувача.

Далі додамо новий клас Java, який назвемо SettingsFragment:

Фрагмент SettingsFragment успадковується від класу PreferenceFragmentCompat. У його методі onCreatePreferences викликається метод addPreferencesFromResource(), до якого передається id ресурсу xml з налаштуваннями (у цьому випадку раніше визначений ресурс R.xml.settings).

І тепер додамо в проєкт спеціальну activity для встановлення налаштувань. Назвемо її SettingsActivity. У підсумку проєкт матиме такий вигляд:

У файлі layout для SettingsActivity - activity_settings.xml пропишемо такий інтерфейс:

<?xml version="1.0" encoding="utf-8"?>
<androidx.fragment.app.FragmentContainerView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/settings_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

Тут визначено FragmentContainerView з id = settings_container - саме той елемент, у який завантажуватиметься фрагмент SettingsFragment.

У коді SettingsActivity визначимо завантаження фрагмента:

package com.example.settingsapp;
 
import androidx.appcompat.app.AppCompatActivity;
 
import android.os.Bundle;
 
public class SettingsActivity extends AppCompatActivity {
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_settings);
 
        getSupportFragmentManager()
                .beginTransaction()
                .replace(R.id.settings_container, new SettingsFragment())
                .commit();
    }
}

SettingsActivity як розмітку інтерфейсу використовуватиме ресурс R.layout.activity_settings.

Під час запуску SettingsActivity завантажуватиме фрагмент SettingsFragment в елемент з id.settings_container.

Далі перейдемо до головної activity - MainActivity. У файлі activity_main.xml визначимо текстове поле і кнопку:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
 
    <TextView
        android:id="@+id/settingsText"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:textSize="18sp"
        app:layout_constraintBottom_toTopOf="@id/settingsButton"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    <Button
        android:id="@+id/settingsButton"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="Налаштування"
        android:onClick="setPrefs"
        app:layout_constraintTop_toBottomOf="@id/settingsText"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent" />
 
</androidx.constraintlayout.widget.ConstraintLayout>

І змінимо клас MainActivity:

package com.example.settingsapp;
 
import androidx.appcompat.app.AppCompatActivity;
import androidx.preference.PreferenceManager;
 
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
 
public class MainActivity extends AppCompatActivity {
 
    TextView settingsText;
    boolean enabled;
    String login;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        settingsText = findViewById(R.id.settingsText);
    }
 
    @Override
    public void onResume() {
        super.onResume();
        SharedPreferences prefs= PreferenceManager.getDefaultSharedPreferences(this);
        enabled = prefs.getBoolean("enabled", false);
        login = prefs.getString("login", "не встановлено");
        settingsText.setText(login);
        if(enabled)
            settingsText.setVisibility(View.VISIBLE);
        else
            settingsText.setVisibility(View.INVISIBLE);
    }
 
    public void setPrefs(View view){
        Intent intent = new Intent(this, SettingsActivity.class);
        startActivity(intent);
    }
}

У методі onResume() отримуємо всі налаштування. Якщо налаштування enabled дорівнює true, то відображаємо текстове поле з логіном.

У методі setPrefs(), який спрацьовує при натисканні на кнопку, виконується перехід до SettingsActivity.

Під час першого запуску налаштувань не буде, і логін не відображатиметься. Перейдемо на сторінку налаштувань і встановимо там логін і ввімкнемо його відображення, а потім повернемося на головну activity: При цьому вручну нам нічого не треба зберігати, всі налаштування автоматично зберігаються функціоналом PreferenceFragmentCompat.