我正在 Android 中构建首选项/设置屏幕AppCompatActivity
。一个要求是[DialogPreference][1]
带有TimePicker
.
DialogPreference 必须是“本机”,这意味着不是此处和此处描述的兼容版本。
AppCompatActivity 的代码:
...
public class SettingsActivity extends AppCompatActivity
{
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_preferences);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar_settings);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
}
activity_preferences.xml 的布局:
...
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<fragment
android:name="nl.waywayway.broodkruimels.SettingsFragment"
android:id="@+id/settings_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</android.support.v4.widget.NestedScrollView>
SettingsFragment 类:
...
public class SettingsFragment extends PreferenceFragment
{
Context mContext;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
}
}
首选项.xml 文件:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<SwitchPreference
android:key="pref_notify"
android:title="@string/pref_notify"
android:summary="@string/pref_notify_summ"
android:defaultValue="false" />
<nl.waywayway.broodkruimels.TimePreference
android:dependency="pref_notify"
android:key="pref_notify_time"
android:title="@string/pref_notify_time"
android:summary="@string/pref_notify_time_summ"
android:defaultValue="390" />
</PreferenceScreen>
和自定义 TimePreference 类:
public class TimePreference extends DialogPreference
{
private TimePicker mTimePicker = null;
private int mTime;
private int mDialogLayoutResId = R.layout.preferences_timepicker_dialog;
// 4 constructors for the API levels,
// calling each other
public TimePreference(Context context)
{
this(context, null);
}
public TimePreference(Context context, AttributeSet attrs)
{
this(context, attrs, R.attr.preferenceStyle);
}
public TimePreference(Context context, AttributeSet attrs, int defStyleAttr)
{
this(context, attrs, defStyleAttr, defStyleAttr);
}
public TimePreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)
{
super(context, attrs, defStyleAttr, defStyleRes);
}
public int getTime()
{
return mTime;
}
public void setTime(int time)
{
mTime = time;
// Save to Shared Preferences
persistInt(time);
}
@Override
public int getDialogLayoutResource()
{
return mDialogLayoutResId;
}
@Override
protected Object onGetDefaultValue(TypedArray a, int index)
{
// Default value from attribute. Fallback value is set to 0.
return a.getInt(index, 0);
}
@Override
protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue)
{
// Read the value. Use the default value if it is not possible.
setTime(restorePersistedValue ?
getPersistedInt(mTime) : (int) defaultValue);
}
@Override
protected void onBindDialogView(View view)
{
super.onBindDialogView(view);
mTimePicker = (TimePicker) view.findViewById(R.id.preferences_timepicker);
if (mTimePicker == null)
{
throw new IllegalStateException("Dialog view must contain a TimePicker with id 'preferences_timepicker'");
}
// Get the time from the related Preference
Integer minutesAfterMidnight = null;
TimePreference preference = (TimePreference) findPreferenceInHierarchy("pref_notify_time");
minutesAfterMidnight = preference.getTime();
// Set the time to the TimePicker
if (minutesAfterMidnight != null)
{
int hours = minutesAfterMidnight / 60;
int minutes = minutesAfterMidnight % 60;
boolean is24hour = DateFormat.is24HourFormat(getContext());
mTimePicker.setIs24HourView(is24hour);
if (Build.VERSION.SDK_INT >= 23)
{
mTimePicker.setHour(hours);
mTimePicker.setMinute(minutes);
}
else
{
mTimePicker.setCurrentHour(hours);
mTimePicker.setCurrentMinute(minutes);
}
}
}
@Override
protected void onDialogClosed(boolean positiveResult)
{
if (positiveResult)
{
// Get the current values from the TimePicker
int hours;
int minutes;
if (Build.VERSION.SDK_INT >= 23)
{
hours = mTimePicker.getHour();
minutes = mTimePicker.getMinute();
}
else
{
hours = mTimePicker.getCurrentHour();
minutes = mTimePicker.getCurrentMinute();
}
// Generate value to save
int minutesAfterMidnight = (hours * 60) + minutes;
// Save the value
TimePreference timePreference = (TimePreference) findPreferenceInHierarchy("pref_notify_time");
// This allows the client to ignore the user value.
if (timePreference.callChangeListener(minutesAfterMidnight))
{
// Save the value
timePreference.setTime(minutesAfterMidnight);
}
}
}
}
options_timepicker_dialog.xml 文件如下:
...
<TimePicker
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/preferences_timepicker"
android:layout_width="match_parent"
android:layout_height="match_parent" />
结果就像下面的屏幕截图。在装有 Android 7 的 Moto G5 plus 手机上。
问题: 应该有两个偏好。但是,自定义 DialogPreference 未显示在设置列表中。这里出了什么问题?AppCompatActivity 是否真的与“本机”DialogPreference 一起使用?
TimePreference 类实际上是从首选项 xml 中实例化的,可以从构造函数中记录下来。也没有编译时错误,没有运行时错误。