Как создать пользовательские настройки с помощью библиотеки android.support.v7.preference?
Я хочу поддерживать по крайней мере API 10, я хочу иметь возможность красиво оформить свои предпочтения, я хочу иметь возможность иметь заголовки (или показать PreferenceScreen
с). Кажется, что PreferenceActivity
не полностью поддерживается AppCompat
Окраска не подойдет. Поэтому я пытаюсь использовать AppCompatActivity
а также PreferenceFragmentCompat
,
public class Prefs extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState == null)
getSupportFragmentManager().beginTransaction()
.replace(android.R.id.content, new PreferencesFragment())
.commit();
}
public static class PreferencesFragment extends PreferenceFragmentCompat {
@Override public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
}
@Override
public void onDisplayPreferenceDialog(Preference preference) {
// the following call results in a dialogue being shown
super.onDisplayPreferenceDialog(preference);
}
@Override public void onNavigateToScreen(PreferenceScreen preferenceScreen) {
// I can probably use this to go to to a nested preference screen
// I'm not sure...
}
}
}
Теперь я хочу создать пользовательскую настройку, которая обеспечит выбор шрифта. С PreferenceActivity
Я мог бы просто сделать
import android.preference.DialogPreference;
public class FontPreference extends DialogPreference {
public FontPreference(Context context, AttributeSet attrs) {super(context, attrs);}
@Override protected void onPrepareDialogBuilder(Builder builder) {
super.onPrepareDialogBuilder(builder);
// do something with builder and make a nice cute dialogue, for example, like this
builder.setSingleChoiceItems(new FontAdapter(), 0, null);
}
}
и использовать XML, как это, чтобы отобразить его
<my.app.FontPreference android:title="Choose font" android:summary="Unnecessary summary" />
Но сейчас нет onPrepareDialogBuilder
в android.support.v7.preference.DialogPreference
, Вместо этого он был перемещен в PreferenceDialogFragmentCompat
, Я нашел мало информации о том, как использовать эту вещь, и я не уверен, как перейти от xml к ее отображению. Фрагмент предпочтения v14 имеет следующий код:
public void onDisplayPreferenceDialog(Preference preference) {
...
final DialogFragment f;
if (preference instanceof EditTextPreference)
f = EditTextPreferenceDialogFragment.newInstance(preference.getKey());
...
f.show(getFragmentManager(), DIALOG_FRAGMENT_TAG);
}
Я пробовал создавать подклассы android.support.v7.preference.DialogPreference
и имея onDisplayPreferenceDialog
использовать подобный кусок кода для создания макета FontPreferenceFragment
но это терпит неудачу со следующим исключением.
java.lang.IllegalStateException: Target fragment must implement TargetFragment interface
На данный момент я уже слишком глубоко в беспорядке и не хочу копать дальше. Google ничего не знает об этом исключении. В любом случае, этот метод кажется слишком сложным. Итак, каков наилучший способ создания пользовательских настроек с помощью библиотеки android.support.v7.preference?
4 ответа
Важное примечание: в настоящее время (v23.0.1 из библиотеки v7) все еще есть много проблем с темой PreferenceThemeOverlay (см. Эту проблему). Например, в Lollipop вы получаете заголовки категорий в стиле Holo.
После нескольких разочаровывающих часов мне наконец удалось создать пользовательскую настройку v7. Создание собственного Preference
кажется сложнее, чем вы думаете, что это необходимо. Так что не забудьте занять некоторое время.
Сначала вам может быть интересно, почему вы найдете как DialogPreference
и PreferenceDialogFragmentCompat
для каждого типа предпочтений. Как выясняется, первое фактическое предпочтение, второе DialogFragment
где предпочтение будет отображаться в. К сожалению, вы обязаны разделить их обоих.
Не волнуйтесь, вам не нужно менять какой-либо кусок кода. Вам нужно только переместить некоторые методы:
- Все методы редактирования предпочтений (например,
setTitle()
или жеpersist*()
) можно найти вDialogPreference
учебный класс. - Все диалоговые (-редактирующие) методы (
onBindDialogView(View)
&onDialogClosed(boolean)
) были перемещены вPreferenceDialogFragmentCompat
,
Вы могли бы хотеть, чтобы ваш существующий класс расширил первый, таким образом, вам не нужно менять на многое, я думаю. Автозаполнение должно помочь вам найти недостающие методы.
После того, как вы выполнили вышеуказанные шаги, пришло время связать эти два класса вместе. В вашем XML-файле вы будете ссылаться на preference-part. Тем не менее, Android еще не знает, какой Fragment
он должен надувать, когда ваши предпочтения должны быть. Поэтому вам необходимо переопределить onDisplayPreferenceDialog(Preference)
:
@Override
public void onDisplayPreferenceDialog(Preference preference) {
DialogFragment fragment;
if (preference instanceof LocationChooserDialog) {
fragment = LocationChooserFragmentCompat.newInstance(preference);
fragment.setTargetFragment(this, 0);
fragment.show(getFragmentManager(),
"android.support.v7.preference.PreferenceFragment.DIALOG");
} else super.onDisplayPreferenceDialog(preference);
}
а также ваш DialogFragment
необходимо обработать "ключ":
public static YourPreferenceDialogFragmentCompat newInstance(Preference preference) {
YourPreferenceDialogFragmentCompat fragment = new YourPreferenceDialogFragmentCompat();
Bundle bundle = new Bundle(1);
bundle.putString("key", preference.getKey());
fragment.setArguments(bundle);
return fragment;
}
Это должно делать свое дело. Если вы столкнулись с проблемами, попробуйте взглянуть на существующие подклассы и посмотреть, как Android их решает (в Android Studio: введите имя класса и нажмите Ctrl+b, чтобы увидеть декомпилированный класс). Надеюсь, поможет.
Есть хорошее руководство и проект Github, в котором подробно объясняется, как создать собственный класс предпочтений, расширяющий библиотеку предпочтений поддержки:
https://medium.com/@JakobUlbrich/building-a-settings-screen-for-android-part-3-ae9793fd31ec - "Создание экрана настроек Android (часть 3)", автор: Якоб Ульбрих
https://github.com/jakobulbrich/preferences-demo - Пример проекта Android на Github
Ключевые моменты:
Вам понадобится индивидуальный
DialogPreference
илиListPreference
, который управляет внешним видом и функциями строки предпочтений. (Он также может содержать ссылку на макет, который должен отображаться в запущенном диалоговом окне). Добавь этоDialogPreference
в ваш файл предпочтений XML.Вам понадобится индивидуальный
PreferenceDialogFragmentCompat
, который управляет запуском диалогового окна при щелчке по строке предпочтений. Вы можете настроить вид диалога вonBindDialogView()
.На экране предпочтений, который расширяет PreferenceFragmentCompat, переопределите
onDisplayPreferenceDialog()
запустить свой обычайPreferenceDialogFragmentCompat
.Вы должны расширять только классы поддержки, а не классы платформы. Например, продлить
androidx.preference.EditTextPreference
вместо тогоandroid.preference.EditTextPreference
Исключение возникает, когда ваш FontPreferenceFragment
не реализует DialogPreference.TargetFragment. Вам нужно убедиться, что ваш фрагмент реализует этот интерфейс.
Уведомление об устаревшемfragment.setTargetFragment(this, 0);
К сожалению, пока мы должны оставить этот устаревший метод до тех пор, покаPreferenceDialogFragmentCompat.java
источник устарел getTargetFragment из onCreate().недавняя фиксация исходного кода Google:
Кроме того, вы можете проверить это в последнем источнике:PreferenceDialogFragmentCompat.java