1

Androidの中に環境設定/設定画面を作成しています。 1つの要件は、のカスタム[DialogPreference][1]です。TimePickerを含むカスタムネイティブ(互換性ではない)のダイアログ参照との互換性

DialogPreferenceは「ネイティブ」である必要があります。つまり、herehereのような互換バージョンではありません。

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); 
    } 
} 

ある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); 
      } 
     } 
    } 
} 

preferences_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" /> 

結果は下記のスクリーンショットのようなものです。アンドロイド7.

Screenshot

とモトG5プラス電話で質問: 2人の好みがあるはずです。ただし、カスタムDialogPreferenceが設定リストに表示されていません。 ここで何がうまくいかないのですか? AppCompatActivityは実際には 'ネイティブ' DialogPreferenceで動作しますか?

TimePreferenceクラスは、実際にはコンストラクターから記録される可能性のある設定xmlからインスタンス化されます。コンパイル時エラーもランタイムエラーもありません。

答えて

0

最後に、Android 4から7までの実デバイスでクリーンでテストされ、動作する別のアプローチが見つかりました。[設定]画面に[設定]が表示されています。

また、TimePickerダイアログが横向きで正しく表示されています。これは一部のデバイスの問題です。

設定した時間好みの活動:

... 
public class SettingsActivity extends AppCompatActivity 
{ 
    public static final String KEY_PREF_NOTIFY = "pref_notify"; 
    public static final String KEY_PREF_NOTIFY_TIME = "pref_notify_time"; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) 
    { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_preferences); 
    } 
} 

レイアウトファイルactivity_preferences.xml:

210 SettingsFragmentクラス:

... 
public class SettingsFragment extends PreferenceFragmentCompat 
{ 
    Context mContext; 

    @Override 
    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) 
    { 
     setPreferencesFromResource(R.xml.preferences, rootKey); 
    } 

    // The Context object of this fragment is only available when this fragment is 'attached', so set the Context object inside the onAttach() method 
    @Override 
    public void onAttach(Context context) 
    { 
     super.onAttach(context); 
     mContext = context; 
    } 

    // This method sets the action of clicking the Preference 
    @Override 
    public boolean onPreferenceTreeClick(Preference preference) 
    { 
     switch (preference.getKey()) 
     { 
      case SettingsActivity.KEY_PREF_NOTIFY_TIME: 
       showTimePickerDialog(preference); 
       break; 
     } 

     return super.onPreferenceTreeClick(preference); 
    } 

    private void showTimePickerDialog(Preference preference) 
    { 
     DialogFragment newFragment = new TimePickerFragment(); 
     newFragment.show(getFragmentManager(), "timePicker"); 
    } 
} 

あるpreferences.xmlファイル:

... 
<android.support.v7.preference.PreferenceScreen 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent"> 

    <android.support.v7.preference.SwitchPreferenceCompat 
     android:key="pref_notify" 
     android:title="@string/pref_notify" 
     android:summary="@string/pref_notify_summ" 
     android:defaultValue="false" /> 

    <android.support.v7.preference.Preference 
     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" /> 

</android.support.v7.preference.PreferenceScreen> 

TimePickerFragmentクラスは、説明のためのAndroidの 'ピッカー' ガイド(https://developer.android.com/guide/topics/ui/controls/pickers.html)を参照してください。

... 
public class TimePickerFragment extends DialogFragment 
    implements TimePickerDialog.OnTimeSetListener 
{ 
    private Context mContext; 
    private int mTime; // The time in minutes after midnight 

    // The Context object for this fragment is only available when this fragment is 'attached', so set the Context object inside the onAttach() method 
    @Override 
    public void onAttach(Context context) 
    { 
     super.onAttach(context); 
     mContext = context; 
    } 

    // Getter and setter for the time 
    public int getTime() 
    { 
     SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(mContext); 
     int prefDefault = mContext.getResources().getInteger(R.integer.preferences_time_default); 
     mTime = sharedPref.getInt(SettingsActivity.KEY_PREF_NOTIFY_TIME, prefDefault); 

     return mTime; 
    } 

    public void setTime(int time) 
    { 
     mTime = time; 

     // Save to Shared Preferences 
     SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(mContext); 
     SharedPreferences.Editor editor = sharedPref.edit(); 
     editor.putInt(SettingsActivity.KEY_PREF_NOTIFY_TIME, time); 
     editor.commit(); 
    } 

    public Dialog onCreateDialog(Bundle savedInstanceState) 
    { 
     int minutesAfterMidnight = getTime(); 
     int hour = minutesAfterMidnight/60; 
     int minute = minutesAfterMidnight % 60; 

     Log.i("HermLog", "onCreateDialog(), tijd: " + hour + ":" + minute); 

     // Create a new instance of TimePickerDialog and return it 
     return new TimePickerDialog(
      mContext, 
      this, 
      hour, 
      minute, 
      DateFormat.is24HourFormat(mContext) 
     ); 
    } 

    @Override 
    public void onTimeSet(TimePicker view, int hour, int minute) 
    { 
     int minutesAfterMidnight = (hour * 60) + minute; 
     setTime(minutesAfterMidnight);  
    } 
}