我想支持至少api 10,我希望能够很好地设置我的偏好,我希望能够有标题(或显示PreferenceScreen
s)。似乎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
此时我已经陷入了混乱之中,并且不想再深入挖掘。谷歌对这个例外一无所知。无论如何,这种方法似乎过于复杂。那么,使用android.support.v7.preference库创建自定义首选项的最佳方法是什么?
答案 0 :(得分:36)
重要提示: 目前(v7库的v23.0.1)仍有很多主题问题与“#PreferenceThemeOverlay”#(见this issue)。例如,在棒棒糖上,你最终得到了Holo风格的类别标题。
经过一段令人沮丧的时间后,我终于成功创建了一个自定义的v7 Preference。创建自己的Preference
似乎比您认为需要的更难。所以一定要花些时间。
首先,您可能想知道为什么您会为每种偏好设置类型找到DialogPreference
和PreferenceDialogFragmentCompat
。事实证明,第一个是实际首选项,第二个是DialogFragment
,其中将显示首选项。遗憾的是,您需要继承两者。
setTitle()
或persist*()
)均可在DialogPreference
课程中找到。onBindDialogView(View)
&amp; onDialogClosed(boolean)
)已移至PreferenceDialogFragmentCompat
。您可能希望现有的课程延伸到第一个课程,这样您就不必改变我想的。自动填充应该可以帮助您找到缺失的方法。
完成上述步骤后,就可以将这两个类绑定在一起了。在xml文件中,您将引用首选项部分。但是,当您的自定义偏好需要时,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
需要处理&#39;:
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中:键入一个类&#39;名称并按Ctrl + b查看反编译的类)。希望它有所帮助。
答案 1 :(得分:1)
有一个很好的教程和Github项目,详细解释了如何制作扩展支持首选项库的自定义首选项类:
https://medium.com/@JakobUlbrich/building-a-settings-screen-for-android-part-3-ae9793fd31ec-“构建Android设置屏幕(第3部分)”,作者Jakob Ulbrich
https://github.com/jakobulbrich/preferences-demo-Github上的示例Android项目
关键点是:
您将需要一个自定义ListPreference
或DialogPreference
,以控制首选项行的外观和功能。 (它也可以包含对应该在启动的对话框中显示的布局的引用)。将此PreferenceDialogFragmentCompat
添加到您的XML首选项文件中。
您将需要一个自定义onBindDialogView()
,该自定义onDisplayPreferenceDialog()
用于在单击首选项行时控制对话框的启动。您可以在PreferenceDialogFragmentCompat
中配置对话框的视图。
在扩展了PreferenceFragmentCompat的首选项屏幕中,覆盖androidx.preference.EditTextPreference
以启动您的自定义android.preference.EditTextPreference
。
您只能扩展支持类,而不能扩展平台类。例如,扩展input[type=radio] {
vertical-align: middle;
margin: 0 10px 0 0;
}
而不是<p>Choose your education level:</p>
<input type="radio" name="education" value="1">High School degree
<br>
<input type="radio" name="education" value="2">College degree
<br>
<input type="radio" name="education" value="3">Masters degree
<br>
<input type="radio" name="education" value="4">PhD degree
答案 2 :(得分:0)
当FontPreferenceFragment
未实施DialogPreference.TargetFragment时,会导致异常。您需要确保您的片段实现该接口。