Статьи

Как кодировать экран настроек в приложении для Android

Конечный продукт
Что вы будете создавать

Команда разработчиков материалов в Google дает четкое определение того, что должны делать настройки в вашем приложении для Android:

Настройки приложения позволяют пользователям указать, как приложение должно вести себя.

Google также заявляет, что ваши пользователи должны перейти к настройкам приложения из боковой навигации или из меню панели инструментов — с помощью элемента, помеченного как « Настройки» .

Включение настроек в ваше приложение дает вашим пользователям возможность контролировать некоторые функции вашего приложения. Это делает ваших пользователей счастливыми, а не злыми, потому что теперь они контролируют поведение приложения.

Настоятельно рекомендуется предоставить доступ к настройкам приложения. Это обеспечит лучший пользовательский опыт для ваших пользователей, что приведет к лучшему обзору в магазине Google Play, что в конечном итоге приведет к большему количеству загрузок приложений (что увеличит доход).

Я предполагаю, что вы должны были взаимодействовать с настройками приложения на вашем устройстве, например, выбрав мелодию по умолчанию или контролируя свою конфиденциальность в приложении. Почти все самые популярные приложения, которые вы загрузили или загрузите в магазине Google Play, содержат экран настроек, позволяющий вам контролировать поведение приложения.

Примером популярного приложения с экраном настроек является приложение Chrome Android от Google. На экране настроек этого приложения пользователи могут выбрать поисковую систему по умолчанию, изменить поведение уведомлений, контролировать конфиденциальность пользователей и т. Д. Вы можете сами убедиться в этом, загрузив приложение Chrome из магазина Google Play (если у вас его еще нет). твое устройство). Следующий снимок экрана взят из приложения Chrome и отображает экран настроек приложения.

Снимок экрана: экран настроек приложения Chrome

В этом посте вы узнаете, как создать экран настроек приложения с нуля, а также как прочитать значения, выбранные пользователем в настройках приложения. В качестве дополнительного бонуса вы также узнаете, как использовать функцию шаблонов Android Studio для быстрой загрузки проекта с помощью экрана настроек.

Пример проекта (на Kotlin) для этого учебного руководства можно найти в нашем репозитории GitHub, чтобы вы могли легко следить за ним.

Чтобы следовать этому руководству, вам понадобится:

  • Основное понимание некоторых API Android (таких как SharedPreferences )
  • Android Studio 3.0 или выше
  • Плагин Kotlin 1.1.51 или выше

Запустите Android Studio и создайте новый проект (вы можете назвать его SettingsScreenDemo ) с пустым действием под названием SettingsActivity . Не забудьте также установить флажок Включить поддержку Kotlin .

Android Studio создать экран проекта

Для поддержки API уровня 11 (Honeycomb) и выше мы можем использовать PreferenceFragment . Этот класс является просто Fragment который показывает иерархию объектов Preference виде списков.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import android.os.Bundle
import android.preference.PreferenceFragment
import android.support.v7.app.AppCompatActivity
 
class SettingsActivity : AppCompatActivity() {
 
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
 
        if (fragmentManager.findFragmentById(android.R.id.content) == null) {
            fragmentManager.beginTransaction()
                    .add(android.R.id.content, SettingsFragment()).commit()
        }
    }
 
 
    class SettingsFragment : PreferenceFragment() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            addPreferencesFromResource(R.xml.preferences)
        }
    }
}

В приведенном выше коде мы создали вложенный класс SettingsFragment внутри SettingsActivity (поскольку класс SetttingsFragment очень мал). Обратите внимание, что наш класс SettingsFragment расширяет суперкласс PreferenceFragment и имеет метод addPrerenceFromResource внутри onCreate() . В этом методе мы дали ему идентификатор ресурса R.xml.preference предпочтения XML для запуска — при загрузке Fragment . Наконец, мы размещаем Fragment в onCreate() просто используя FragmentTransaction чтобы добавить его в пользовательский интерфейс — внутри onCreate() в SettingsActivity .

Создайте файл XML и назовите его Preferences.xml . Сохраните этот файл в директории res / xml вашего проекта приложения. Обратите внимание, что вы можете дать этому файлу любое имя, но настоятельно рекомендуется придерживаться общепринятого названия «предпочтения». Кроме того, у вас обычно должен быть только один такой файл в проекте приложения.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?xml version=»1.0″ encoding=»utf-8″?>
<PreferenceScreen xmlns:android=»https://schemas.android.com/apk/res/android»>
    <CheckBoxPreference
            android:key=»checkbox»
            android:summary=»Tap to check if on or off»
            android:title=»Checkbox Preference» />
    <RingtonePreference
            android:key=»ringtone»
            android:showDefault=»true»
            android:showSilent=»true»
            android:summary=»Pick a ringtone you like»
            android:title=»Ringtone Preference» />
    <EditTextPreference
            android:dialogTitle=»Enter a text»
            android:key=»text»
            android:summary=»Click to show a text entry dialog»
            android:title=»EditText Preference» />
    <ListPreference
            android:dialogTitle=»Select duration»
            android:entries=»@array/settings_list_preference_titles»
            android:entryValues=»@array/settings_list_preference_values»
            android:key=»list»
            android:summary=»Click to show a list to choose from»
            android:title=»List Preference» />
    <SwitchPreference
            android:key=»switch»
            android:title=»Switch Preference»
            android:summary=»Click to switch on or off»
            android:defaultValue=»true»/>
</PreferenceScreen>

Корневой узел для наших предпочтений. XML- файл должен быть элементом <PreferenceScreen> . Внутри этого корневого элемента у нас теперь есть наше индивидуальное Preference . Вот общие атрибуты, связанные с Preference :

  • android:key : этот атрибут используется для получения значения в объекте SharedPreferences .
  • android:title : устанавливает заголовок для Preference . Это жирный текст.
  • android:summary : устанавливает сводку для Preference (это не обязательно). Это блеклый текст под заголовком.
  • android:defaultValue : устанавливает значение по умолчанию для Preference .

Мы вскоре рассмотрим все Preference мы определили выше. Обратите внимание, что вы также можете добавить или настроить Preference помощью редактора предпочтений Android Studio — аналогично редактору ресурсов макета, с которым вы уже знакомы. Вы можете либо добавить / отредактировать свой XML-файл настроек непосредственно в режиме «Текст», либо использовать интерфейс перетаскивания в режиме «Дизайн».

Редактор настроек Android Studio

Как вы можете видеть, в этом редакторе вы можете перетаскивать любые Preference в разделе палитры (слева). После удаления вы должны выбрать его и изменить его атрибуты на панели атрибутов (справа) редактора. Обратите внимание, что по умолчанию нам дается несколько атрибутов для изменения. Чтобы просмотреть или изменить все атрибуты, связанные с выбранным Preference , обязательно щелкните ссылку « Просмотреть все атрибуты» в нижней части панели атрибутов. Это очень похоже на редактор макетов, который вы уже знаете.

Теперь давайте пройдемся по всем Preference у нас Preference .

CheckBoxPreference — это просто виджет CheckBox который включен в экран настроек. Этот параметр возвращает значение «true», если установлен флажок, или «false» в противном случае. Другими словами, он возвращает логическое значение в зависимости от состояния виджета.

1
2
3
4
<CheckBoxPreference
           android:key=»checkbox»
           android:summary=»Tap to check if on or off»
           android:title=»Checkbox Preference» />
CheckBoxPreferense

Другие атрибуты, которые вы можете добавить в CheckBoxPreference :

  • android:summaryOff : устанавливает сводку для Preference на экране предпочтений, когда она не отмечена.
  • android:summaryOn : устанавливает сводку для Preference на экране предпочтений, когда она отмечена.
  • android:disableDependentsState : состояние (true для on или false для off), которое приводит к отключению зависимых. Может быть логическим значением, таким как «истина» или «ложь».

SwitchPreference выполняет функции, аналогичные CheckBoxPreference . Он предоставляет возможность переключения в двух состояниях («включено» или «выключено»). При этом используется виджет « Switch который позволяет пользователю скользить влево («выкл») и вправо («вкл»). Это Preference также включает атрибуты, описанные для CheckBoxPreference выше. Кроме того, он имеет следующие атрибуты:

  • android:switchTextOff : устанавливает текст, используемый на самом коммутаторе в выключенном состоянии.
  • android:switchTextOn : устанавливает текст, используемый на самом коммутаторе в состоянии « android:switchTextOn ».
1
2
3
4
5
<SwitchPreference
           android:key=»switch»
           android:title=»Switch Preference»
           android:summary=»Click to switch on or off»
           android:defaultValue=»true»/>
SwitchPreference

При выборе этого параметра отображается диалоговое окно, в котором пользователь может ввести введенный текст. Он использует виджет EditText включая все атрибуты этого виджета, с которым вы уже знакомы.

1
2
3
4
5
6
<EditTextPreference
           android:dialogTitle=»Enter a text»
           android:key=»text»
           android:summary=»Click to show a text entry dialog»
           android:title=»EditText Preference»
           android:inputType=»text»/>

Обратите внимание, что значение, хранящееся в SharedPreferences является строкой.

EditTextPreference

Этот вид Preference будет отображать список записей в диалоговом окне при нажатии. Здесь вы можете указать пару ресурсов строкового массива в своем предпочтительном XML. Этот ресурс строкового массива просто содержит коллекцию строк. Этот ресурс находится по адресу res/values/arrays.xml .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
<?xml version=»1.0″ encoding=»utf-8″?>
<resources>
    <string-array name=»settings_list_preference_titles»>
        <item>15 minutes</item>
        <item>30 minutes</item>
        <item>1 hour</item>
        <item>3 hours</item>
        <item>6 hours</item>
        <item>Never</item>
    </string-array>
    <string-array name=»settings_list_preference_values»>
        <item>15</item>
        <item>30</item>
        <item>60</item>
        <item>180</item>
        <item>360</item>
        <item>-1</item>
    </string-array>
</resources>

Вот наш образец ListPreference с использованием этого ресурса.

1
2
3
4
5
6
7
<ListPreference
       android:dialogTitle=»Select duration»
       android:entries=»@array/settings_list_preference_titles»
       android:entryValues=»@array/settings_list_preference_values»
       android:key=»list»
       android:summary=»Click to show a list to choose from»
       android:title=»List Preference» />

Мы устанавливаем записи и значения android:entries android:entryValues атрибуты android:entryValues и android:entryValues соответственно.

  • android:entries : читабельный массив для представления в виде списка.
  • android:entryValues : массив для поиска значения, которое нужно сохранить для предпочтения при android:entryValues записи из записей.
Диалог ListPreference при нажатии

Например, если мы используем количество минут в каждой продолжительности в качестве значений ввода, когда пользователь выбирает продолжительность (например, 30 минут), соответствующее целочисленное значение будет сохранено в SharedPreferences (например, 30).

Это похоже на ListPreference но вместо переключателей у нас есть флажки. Другими словами, пользователь может выбрать несколько элементов в диалоговом окне. Обратите внимание, что результат сохраняется в «наборе строк» ​​в SharedPreferences . Это можно получить с помощью getStringSet() .

1
2
3
4
5
6
<MultiSelectListPreference
           android:dialogTitle=»Dialog title»
           android:entries=»@array/settings_multi_select_list_preference_titles»
           android:entryValues=»@array/settings_multi_select_list_preference_values»
           android:key=»multi_select_list»
           android:title=»Multiselect title» />

При RingtonePreference отображается диалоговое окно со списком доступных мелодий на устройстве или эмуляторе.

1
2
3
4
5
6
<RingtonePreference
           android:key=»ringtone»
           android:showDefault=»true»
           android:showSilent=»true»
           android:summary=»Pick a ringtone you like»
           android:title=»Ringtone Preference» />
  • android:showDefault : будет ли показана опция мелодии по умолчанию .
  • android:showSilent : будет ли опция Silent отображаться в списке. Пользователь может выбрать эту опцию, если он не хочет воспроизводить мелодию звонка.
RingtonePreference

Обратите внимание, что значение, сохраненное в SharedPreferences для этого предпочтения, является специальной строкой. Эта специальная строка является URI, который указывает на ContentProvider .

Это становится проблемой, когда у вас длинный список предпочтений или настроек, потому что у пользователей могут возникнуть проблемы со сканированием или их пониманием. Чтобы решить эту проблему, мы можем сгруппировать наши предпочтения. Посмотрите на скриншот приложения Chrome, которое я показывал вам в самом начале, и обратите внимание, что оно сгруппировало настройки по двум категориям: Основы и Расширенные . Это облегчает пользователю понимание предпочтений и не делает список слишком громоздким.

Давайте теперь посмотрим, насколько просто выполнить эту задачу.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version=»1.0″ encoding=»utf-8″?>
<PreferenceScreen xmlns:android=»http://schemas.android.com/apk/res/android»>
 
    <PreferenceCategory android:title=»Basic Settings»>
        <CheckBoxPreference
                android:key=»checkbox»
                android:summary=»Tap to check if on or off»
                android:title=»Checkbox Preference»/>
        …
    </PreferenceCategory>
 
    <PreferenceCategory android:title=»Advanced Settings»>
        <ListPreference
                android:dialogTitle=»Select duration»
                android:entries=»@array/settings_list_preference_titles»
                android:entryValues=»@array/settings_list_preference_values»
                android:key=»list»
                android:summary=»Click to show a list to choose from»
                android:title=»List Preference»/>
        …
    </PreferenceCategory>
</PreferenceScreen>

Мы просто окружаем предпочтения, которые мы хотим сгруппировать, в <PreferenceCategory> и присваиваем каждой группе заголовок, используя атрибут android:title .

Предпочтения сгруппированы с PreferenceCategory

Обратите внимание, что можно открыть действие, просто щелкнув элемент предпочтения на экране настроек. Это может пригодиться, когда вы хотите открыть веб-страницу. Вот код для этого:

1
2
3
4
5
6
7
8
<Preference
        android:summary=»Click to start an activity»
        android:title=»Preference»>
    <intent
            android:action=»com.chikeandroid.settingsscreendemo.SETTING_START_ACTIVITY»
            android:targetClass=»com.chikeandroid.settingsscreendemo.MyActivity»
            android:targetPackage=»com.chikeandroid.settingsscreendemo» />
</Preference>

Здесь мы добавили элемент <intent> внутри элемента <Preference> .

  • android:action : устанавливает действие для Intent (это похоже на вызов setAction() для объекта Intent).
  • android:targetClass : устанавливает часть класса имени компонента (аналогично вызову setComponent() для объекта Intent).
  • android:targetPackage : устанавливает часть пакета имени компонента.
  • android:data : устанавливает данные для назначения (аналогично вызову setData() для объекта Intent).

Например, чтобы открыть веб-страницу, вы можете использовать следующее:

1
2
3
4
<Preference android:title=»@string/prefs_web_page» >
    <intent android:action=»android.intent.action.VIEW»
            android:data=»http://www.example.com» />
</Preference>

Давайте теперь посмотрим, как обновить сводку предпочтений значением, выбранным пользователем.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
class SettingsActivity : AppCompatActivity() {
 
    // …
    class SettingsFragment : PreferenceFragment() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            addPreferencesFromResource(R.xml.preferences)
 
            bindPreferenceSummaryToValue(findPreference(«ringtone»))
            bindPreferenceSummaryToValue(findPreference(«text»))
            bindPreferenceSummaryToValue(findPreference(«list»))
        }
    }
    // …
}

В этом классе мы создали вспомогательный метод с именем bindPreferenceSummaryToValue() , который находится внутри нашего сопутствующего объекта , чтобы обновить текст сводки настроек со значением, выбранным пользователем. Мы передали ему объект Preference в качестве аргумента. findPreference() вернет Preference используя ключ Preference .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
class SettingsActivity : AppCompatActivity() {
    // …
    companion object {
         
        /**
         * A preference value change listener that updates the preference’s summary
         * to reflect its new value.
         */
        private val sBindPreferenceSummaryToValueListener = Preference.OnPreferenceChangeListener { preference, value ->
 
            val stringValue = value.toString()
 
            if (preference is ListPreference) {
                // For list preferences, look up the correct display value in
                // the preference’s ‘entries’ list.
                val listPreference = preference
                val index = listPreference.findIndexOfValue(stringValue)
 
                // Set the summary to reflect the new value.
                preference.setSummary(
                        if (index >= 0)
                            listPreference.entries[index]
                        else
                            null)
 
            } else if (preference is RingtonePreference) {
                // For ringtone preferences, look up the correct display value
                // using RingtoneManager.
                if (TextUtils.isEmpty(stringValue)) {
                    // Empty values correspond to ‘silent’ (no ringtone).
                    preference.setSummary(«Silent»)
 
                } else {
                    val ringtone = RingtoneManager.getRingtone(
                            preference.getContext(), Uri.parse(stringValue))
 
                    if (ringtone == null) {
                        // Clear the summary if there was a lookup error.
                        preference.setSummary(null)
                    } else {
                        // Set the summary to reflect the new ringtone display
                        // name.
                        val name = ringtone.getTitle(preference.getContext())
                        preference.setSummary(name)
                    }
                }
            }
            else {
                // For all other preferences, set the summary to the value’s
                // simple string representation.
                preference.summary = stringValue
            }
            true
        }
 
        private fun bindPreferenceSummaryToValue(preference: Preference) {
            // Set the listener to watch for value changes.
            preference.onPreferenceChangeListener = sBindPreferenceSummaryToValueListener
 
            // Trigger the listener immediately with the preference’s
            // current value.
            sBindPreferenceSummaryToValueListener.onPreferenceChange(preference,
                    PreferenceManager
                            .getDefaultSharedPreferences(preference.context)
                            .getString(preference.key, «»))
        }
    }
}

У нас есть переменная sBindPreferenceSummaryToValueListener которая является экземпляром Preference.OnPreferenceChangeListener . Это просто слушатель изменения предпочтений, который поможет нам обновить сводку предпочтений до значения, выбранного пользователем. Мы проверяем наличие особых случаев, например, когда выбранным предпочтением является RingtonePreference или ListPreference . Для этих типов предпочтений мы делаем специальную обработку, чтобы получить итоговую строку. Если предпочтение не одно (например, EditTextPreference ), мы просто устанавливаем в сводке значение строки предпочтения.

Внутри bindPreferenceSummaryToValue() мы устанавливаем прослушиватель изменения предпочтений, вызывая onPreferenceChangeListener (в Java это вместо этого setOnPreferenceChangeListener ) объекта Preference .

Теперь запустите проект еще раз, чтобы увидеть, как все это работает!

Экран настроек, показывающий измененную сводку в ответ на выбор

Чтобы начать получать значения предпочтений для экрана настроек, мы вызываем getDefaultSharedPreference() который находится внутри класса PreferenceManager — передавая ему объект Context предпочтений, значения которых требуются. Обратите внимание, что мы получаем значения из SharedPreferences по умолчанию для нашего приложения.

1
2
3
4
5
val prefs = PreferenceManager.getDefaultSharedPreferences(this)
prefs.getBoolean(«checkbox», false).toString()
prefs.getString(«ringtone», «<unset>»)
prefs.getString(«text», «<unset>»)
prefs.getString(«list», «<unset>»)

Вы вызываете соответствующий метод получения для типа, из которого мы хотим получить значение в SharedPreferences . Вы передаете ему ключ в качестве первого аргумента, а значением по умолчанию является второй аргумент.

Теперь, когда вы узнали об API, которые используются для создания экрана настроек с нуля в Android, я покажу вам ярлык, который сделает его быстрее в следующий раз. Вы можете использовать шаблон вместо того, чтобы кодировать экран настроек с нуля.

Android Studio предоставляет шаблоны кода, которые соответствуют рекомендациям по проектированию и разработке Android. Эти существующие шаблоны кода (доступные на Java и Kotlin) могут помочь вам быстро запустить ваш проект. Один такой шаблон можно использовать для создания экрана настроек.

Чтобы использовать эту удобную функцию для нового проекта, сначала запустите Android Studio.

Android Studios Диалог создания проекта Android

Введите имя приложения и нажмите кнопку « Далее» . Вы можете оставить настройки по умолчанию такими, как они есть в диалоговом окне « Целевые устройства Android ».

Нажмите кнопку Далее еще раз.

Android-студии Добавить диалоговое окно «Активность на мобильный»

В диалоговом окне « Добавить мероприятие на мобильный » прокрутите вниз и выберите « Настройки». Нажмите кнопку Далее после этого.

Студии Android Настройка диалога активности

В последнем диалоговом окне вы можете переименовать имя действия, имя макета или заголовок, если хотите. Наконец, нажмите кнопку Готово , чтобы принять все конфигурации.

Android Studio теперь помогла нам создать проект с настройкой активности. Очень круто! Вам настоятельно рекомендуется изучить сгенерированный код.

Вы также можете использовать шаблоны для уже существующего проекта Android Studio. Просто зайдите в File> New> Activity> Настройки Activity .

Навигация по созданию новых настроек в Android Studio

Обратите внимание, что шаблоны, поставляемые с Android Studio, хороши для простых макетов и создания базовых приложений, но если вы хотите действительно запустить свое приложение, вы можете рассмотреть некоторые шаблоны приложений, доступные на Envato Market .

Они значительно экономят время опытных разработчиков, помогая им сократить время создания приложения с нуля и сосредоточить свои таланты вместо этого на уникальных и настраиваемых частях создания нового приложения.

Из этого урока вы узнали, как создавать настройки приложения в Android с нуля. Мы также узнали, как легко и быстро использовать шаблоны Android Studio для создания настроек приложения.

Я настоятельно рекомендую ознакомиться с официальными рекомендациями по дизайну материалов для настроек, чтобы узнать больше о том, как правильно проектировать и использовать настройки в Android. Кроме того, ознакомьтесь с официальным руководством по API, чтобы узнать больше о других API для создания действий по настройке.

Чтобы узнать больше о кодировании для Android, ознакомьтесь с другими нашими курсами и учебными пособиями здесь, на Envato Tuts +!

  • Android SDK
    Отображение диалогов дизайна материала в приложении для Android
  • Android SDK
    Отправка данных с помощью HTTP-клиента Retrofit 2 для Android
  • Шаблоны приложений
    20 лучших шаблонов для Android-приложений 2019 года
    Нона Блэкман
  • Android SDK
    Как создать приложение для Android-чата с помощью Firebase
    Ашраф Хатхибелагал