2017-09-26 2 views
0

よりも優先画面に別々に示し百聞は一見にしかずで、これは私の問題です:カスタムプリファレンスは、ネイティブ環境設定

My settings preference screen

最後の三つの好みは、分、秒 のカスタム時間ピッカーです他の設定は、通常のSwitchPreferenceは、RingTonePreference、ListPreferenceとEditTextPreference

これは私の好みのXMLである

<?xml version="1.0" encoding="utf-8"?> 
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> 

    <PreferenceCategory android:title="@string/pref_header_general"> 

     <SwitchPreference 
      android:defaultValue="true" 
      android:key="@string/pref_key_turbo" 
      android:summaryOff="@string/pref_summaryOff_turbo" 
      android:summaryOn="@string/pref_summaryOn_turbo" 
      android:title="@string/pref_title_turbo" /> 

     <ListPreference 
      android:defaultValue="1" 
      android:entries="@array/pref_distance_units_list_titles" 
      android:entryValues="@array/pref_distance_units_list_values" 
      android:key="@string/pref_key_distance_units" 
      android:negativeButtonText="@null" 
      android:positiveButtonText="@null" 
      android:title="@string/pref_title_distance_units" /> 

    </PreferenceCategory> 

    <PreferenceCategory android:title="@string/pref_header_advanced"> 

     <EditTextPreference 
      android:defaultValue="100" 
      android:dialogMessage="@string/pref_distance_dialog_msg" 
      android:dialogTitle="@string/pref_distance_dialog_title" 
      android:inputType="number|numberDecimal" 
      android:key="@string/pref_key_distance" 
      android:summary="@string/pref_summary_distance" 
      android:title="@string/pref_title_distance" /> 

     <!-- Allows the user to choose a ringtone --> 
     <RingtonePreference 
      android:defaultValue="content://settings/system/notification_sound" 
      android:key="@string/pref_key_default_ringtone" 
      android:ringtoneType="notification" 
      android:showDefault="true" 
      android:showSilent="true" 
      android:title="@string/pref_title_default_ringtone" /> 

     <com.test.birenbaum.TimePickerPreference 
      android:defaultValue="@string/pref_default_first" 
      android:dialogMessage="@string/pref_default_first_dialog_msg" 
      android:dialogTitle="@string/pref_default_first_dialog_title" 
      android:key="@string/pref_key_default_first" 
      android:summary="@string/pref_summary_default_first" 
      android:title="@string/pref_title_default_first" /> 

     <com.test.birenbaum.TimePickerPreference 
      android:defaultValue="@string/pref_default_value_retry" 
      android:dialogMessage="@string/pref_default_retry_dialog_msg" 
      android:dialogTitle="@string/pref_default_retry_dialog_title" 
      android:key="@string/pref_key_default_retry" 
      android:summary="@string/pref_summary_default_retry" 
      android:title="@string/pref_title_default_retry" /> 

     <com.test.birenbaum.TimePickerPreference 
      android:defaultValue="@string/pref_default_value_off" 
      android:dialogMessage="@string/pref_default_off_dialog_msg" 
      android:dialogTitle="@string/pref_default_off_dialog_title" 
      android:key="@string/pref_key_default_off" 
      android:summary="@string/pref_summary_default_off" 
      android:title="@string/pref_title_default_off" /> 

     <ListPreference 
      android:defaultValue="1" 
      android:entries="@array/pref_default_algo_list_titles" 
      android:entryValues="@array/pref_default_algo_list_values" 
      android:key="@string/pref_key_default_algo_mode" 
      android:negativeButtonText="@null" 
      android:positiveButtonText="@null" 
      android:summary="@string/pref_summary_default_algo" 
      android:title="@string/pref_title_default_algo_mode" /> 
    </PreferenceCategory> 
</PreferenceScreen> 

長めですのでTimePickerPreferenceコードは入れません。
私はコード内の任意の場所にレイアウトを設定していませんので、組み込みの設定と同じように表示されることを期待していますが、上記の図のように異なります。

カスタム設定項目が通常の設定と異なる理由は何ですか?

MORE INFO要求

public class TimePickerPreference extends DialogPreference { 
    private static final String TAG = "TimePickerPreference"; 
    public static boolean DEBUG = true; 

    private static final String DEFAULT_VALUE = "0m0s"; 
    private static final String DEFAULT_SUMMARY = "%s"; 
    private static final String SPLIT_REGEX = "m|s"; 
    private static final String MATCH_REGEX = "\\d+m[0-5]?\\ds"; 
    private static final String TIME_FORMAT = "%dm%ds"; 

    private static final int MAX_MINUTES = 30; 
    private static final int MIN_MINUTES = 0; 
    private static final int MAX_SECONDS = 59; 
    private static final int MIN_SECONDS = 0; 

    private int mSeconds; 
    private int mMinutes; 

    private NumberPicker mSecondsPicker; 
    private NumberPicker mMinutesPicker; 

    private String mDefaultValue; 
    private String mSummary; 
    private String mSummaryFormat; 


    public TimePickerPreference(Context context, AttributeSet attrs, int defStyleAttr) { 
     super(context, attrs, defStyleAttr); 
     MyLog.pe(DEBUG, TAG, "+ Constructor TimePickerPreference(context:%s, attrs:%s, defStyleAttr:%d)", context, attrs, defStyleAttr); 

     TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.TimePickerPreference, 0, 0); 

     setTitle(a.getString(R.styleable.TimePickerPreference_android_title)); 
     if (getTitle() == null) { 
      setTitle(TimePickerPreference.class.getSimpleName()); 
     } 

     mSummary = a.getString(R.styleable.TimePickerPreference_android_summary); 
     if (mSummary == null) { 
      mSummary = DEFAULT_SUMMARY; 
     } 
     setSummary(mSummary); 
     // At this stage the summary is virgin, still in skeleton format (with %s) 
     setSummaryFormat(mSummary); 

     mDefaultValue = a.getString(R.styleable.TimePickerPreference_android_defaultValue); 
     if (mDefaultValue == null) { 
      mDefaultValue = DEFAULT_VALUE; 
     } 

     setDefaultValue(mDefaultValue); 

     a.recycle(); 

     setDialogLayoutResource(R.layout.preference_dialog_timepicker); 
     setPositiveButtonText(R.string.save_button); 
     setNegativeButtonText(android.R.string.cancel); 

     MyLog.px(DEBUG, TAG, "- Constructor TimePickerPreference()"); 
    } 

    public TimePickerPreference(Context context, AttributeSet attrs) { 
     this(context, attrs, 0); 
    } 

    public TimePickerPreference(Context context) { 
     this(context, null, 0); 
    } 

    @Override 
    protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) { 
     MyLog.pe(DEBUG, TAG, "+ onSetInitialValue(restorePersistedValue:%s, defaultValue:%s)", restorePersistedValue, defaultValue); 
     String[] time; 
     if (restorePersistedValue) { 
      time = getPersistedString((String) defaultValue).split(SPLIT_REGEX); 
      // Assume persisted value is kosher 
      mMinutes = Integer.valueOf(time[0]); 
      mSeconds = Integer.valueOf(time[1]); 

     } else { 
      time = ((String) defaultValue).split(SPLIT_REGEX); 
      if (time.length == 2) { 
       // Enforce MIN-MAX boundaries 
       mMinutes = Math.max(MIN_MINUTES, Math.min(MAX_MINUTES, (Integer.valueOf(time[0])))); 
       mSeconds = Math.max(MIN_SECONDS, Math.min(MAX_SECONDS, (Integer.valueOf(time[1])))); 
       defaultValue = getTime(); 
       persistString((String) defaultValue); 
      } else { 
       // Picker system default value, definitely kosher 
       time = DEFAULT_VALUE.split(SPLIT_REGEX); 
       mMinutes = Integer.valueOf(time[0]); 
       mSeconds = Integer.valueOf(time[1]); 
       persistString(DEFAULT_VALUE); 
      } 
     } 
     MyLog.px(DEBUG, TAG, "- onSetInitialValue()"); 
    } 

    @Override 
    protected Object onGetDefaultValue(TypedArray a, int index) { 
     MyLog.pe(DEBUG, TAG, "* onGetDefaultValue(a:%s, index:%s)", a, index); 
     return a.getString(index); 
    } 

// @Override 
// protected View onCreateDialogView() { 
//  return super.onCreateDialogView(); 
// } 

    @Override 
    protected void onBindDialogView(View view) { 
     MyLog.pe(DEBUG, TAG, "+ onBindDialogView(view:%s)", view); 
     super.onBindDialogView(view); 

     TextView tvMessage = view.findViewById(R.id.tvMessage); 
     String message = (String) getDialogMessage(); 
     if (message == null || message.isEmpty()) { 
      tvMessage.setVisibility(View.GONE); 
     } else { 
      tvMessage.setText(message); 
     } 

     mMinutesPicker = view.findViewById(R.id.minutesPicker); 
     mMinutesPicker.setMaxValue(MAX_MINUTES); 
     mMinutesPicker.setMinValue(MIN_MINUTES); 

     mSecondsPicker = view.findViewById(R.id.secondsPicker); 
     mSecondsPicker.setMaxValue(MAX_SECONDS); 
     mSecondsPicker.setMinValue(MIN_SECONDS); 

     mMinutesPicker.setValue(mMinutes); 
     mSecondsPicker.setValue(mSeconds); 


     MyLog.px(DEBUG, TAG, "- onBindDialogView()"); 
    } 

    @Override 
    protected void onDialogClosed(boolean positiveResult) { 
     MyLog.pe(DEBUG, TAG, "+ onDialogClosed(positiveResult:%s)", positiveResult); 
     super.onDialogClosed(positiveResult); 

     if (positiveResult) { 
      String newValue = new StringBuilder() 
        .append(mMinutesPicker.getValue()) 
        .append('m') 
        .append(mSecondsPicker.getValue()) 
        .append('s') 
        .toString(); 
      if (callChangeListener(newValue)) { 
       //noinspection ConstantConditions 
       setTime(newValue); 
      } 
     } 
     MyLog.px(DEBUG, TAG, "- onDialogClosed()"); 
     super.onDialogClosed(positiveResult); 
    } 

    @Override 
    public void setDefaultValue(Object defaultValue) { 
     MyLog.pe(DEBUG, TAG, "* setDefaultValue(defaultValue:%s)", defaultValue); 
     super.setDefaultValue(defaultValue); 
    } 

    @Override 
    protected void onRestoreInstanceState(Parcelable state) { 
     MyLog.pe(DEBUG, TAG, "+ onRestoreInstanceState(state:%s)",state); 
     if (state == null || !state.getClass().equals(SavedState.class)) { 
      // Didn't save state for us in onSaveInstanceState 
      super.onRestoreInstanceState(state); 
     } 
     MyLog.px(DEBUG, TAG, "- onRestoreInstanceState()"); 
    } 

    /** 
    * Save the instance state so that it will survive events like 
    * screen orientation change that may temporarily destroy it. 
    */ 
    @Override 
    protected Parcelable onSaveInstanceState() { 
     MyLog.pe(DEBUG, TAG, "+ onSaveInstanceState()"); 
     final Parcelable superState = super.onSaveInstanceState(); 
     Parcelable result; 
     if (isPersistent()) { 
      // No need to save instance state since it's persistent 
      result = superState; 
     } else { 
      final SavedState myState = new SavedState(superState); 
      myState.seconds = mSeconds; 
      myState.minutes = mMinutes; 
      result = myState; 
     } 
     MyLog.px(DEBUG, TAG, "- onSaveInstanceState()"); 
     return result; 
    } 

    //---------------------------------------------------------------------------- 

    public int getSeconds() { 
     return mSeconds; 
    } 

    public void setSeconds(int seconds) { 
     mSeconds = seconds; 
    } 

    public int getMinutes() { 
     return mMinutes; 
    } 

    public void setMinutes(int minutes) { 
     mMinutes = minutes; 
    } 

    public String getSummaryFormat() { 
     return mSummaryFormat; 
    } 

    public void setSummaryFormat(String summaryFormat) { 
     mSummaryFormat = summaryFormat; 
    } 

    @SuppressLint("DefaultLocale") 
    public String getTime() { 
     return String.format(TIME_FORMAT, mMinutes, mSeconds); 
    } 

    /** 
    * Saves the value to the {@link android.content.SharedPreferences SharedPreferences}. 
    * 
    * @param newTime A value to save. Must be in the correct format otherwise the save 
    *    operation is not executed 
    */ 
    public void setTime(String newTime) { 
     MyLog.pe(DEBUG, TAG, "+ setTime(newTime:%s)", newTime); 
     final boolean wasBlocking = shouldDisableDependents(); 

     if (newTime.matches(MATCH_REGEX)) { 
      String[] time = newTime.split(SPLIT_REGEX); 
      // No need to check for MAX and MIN values 
      // The values come from the spinners, therefore are within boundaries 
      mMinutes = Integer.valueOf(time[0]); 
      mSeconds = Integer.valueOf(time[1]); 
      persistString(newTime); 
      notifyChanged(); 
     } 

     final boolean isBlocking = shouldDisableDependents(); 
     if (isBlocking != wasBlocking) { 
      notifyDependencyChange(isBlocking); 
     } 
     MyLog.px(DEBUG, TAG, "- setTime()"); 
    } 

    @Override 
    public String toString() { 
     return getTime(); 
    } 

//---------------------------------------------------------------------------- 

    /** 
    * Returns the summary of this TimePickerPreference. If the summary 
    * has a {@linkplain java.lang.String#format String formatting} 
    * marker in it (i.e. "%s" or "%1$s"), then the current minutes and seconds 
    * value will be substituted in its place. 
    * 
    * @return the summary with appropriate string substitution 
    */ 
    @Override 
    public CharSequence getSummary() { 
     MyLog.pe(DEBUG, TAG, "+ getSummary()"); 
     CharSequence result; 
     if (mSummary == null) { 
      result = super.getSummary(); 
     } else { 
      result = String.format(mSummary, getTime()); 
     } 
     MyLog.px(DEBUG, TAG, "- getSummary()"); 
     return result; 
    } 

    /** 
    * Sets the summary for this Preference with a CharSequence. 
    * If the summary has a {@linkplain java.lang.String#format String formatting} 
    * marker in it (i.e. "%s" or "%1$s"), then the current entry value will be substituted 
    * in its place when it's retrieved. 
    * 
    * @param summary The summary for the preference. 
    */ 
    @Override 
    public void setSummary(CharSequence summary) { 
     MyLog.pe(DEBUG, TAG, "+ setSummary(summary:%s)", summary); 
     super.setSummary(summary); 
     if (summary == null && mSummary != null) { 
      mSummary = null; 
     } else if (summary != null && !summary.equals(mSummary)) { 
      mSummary = summary.toString(); 
     } 
     MyLog.px(DEBUG, TAG, "- setSummary()"); 
    } 


    //---------------------------------------------------------------------------- 

    private static class SavedState extends BaseSavedState { 
     int seconds; 
     int minutes; 

     public SavedState(Parcelable superState) { 
      super(superState); 
     } 

     public SavedState(Parcel source) { 
      super(source); 
      MyLog.pe(DEBUG, TAG, "+ SavedState(source:%s)", source); 

      seconds = source.readInt(); 
      minutes = source.readInt(); 

      MyLog.px(DEBUG, TAG, "- SavedState()"); 
     } 

     @Override 
     public void writeToParcel(Parcel dest, int flags) { 
      MyLog.pe(DEBUG, TAG, "+ writeToParcel(dest:%s, flags:%s)", dest, flags); 
      super.writeToParcel(dest, flags); 

      dest.writeInt(seconds); 
      dest.writeInt(minutes); 

      MyLog.px(DEBUG, TAG, "- writeToParcel()"); 
     } 

     @SuppressWarnings("unused") 
     public static final Parcelable.Creator<SavedState> CREATOR = new Parcelable.Creator<SavedState>() { 
      @Override 
      public SavedState createFromParcel(Parcel in) { 
       return new SavedState(in); 
      } 

      @Override 
      public SavedState[] newArray(int size) { 
       return new SavedState[size]; 
      } 
     }; 
    } 
} 
+0

'TimePickerPreference'が' android.preference.Preference'の子孫であることを確認してください。 – azizbekian

+0

@azizbekian 'TimePickerPreference'は、' Preference'(android.preference.Preference)を拡張する 'DialogPreference'を拡張します – ilomambo

+0

私は、あなたがカスタム・プリファレンス・クラスの1つを投稿し、ビジネス・ロジックを除外しなければならないと思います。 – azizbekian

答えて

0

ような問題は/嗜好コンストラクタに第三引数(defStyleAtttr)になりました。

整数ですが、0はデフォルト値ではありません。com.android.internal.R.attr.dialogPreferenceStyleです。

私は3番目のコンストラクタを削除しました。基底クラスDialogPreferencedefStylAttrの値を扱います。そして今、それは他の組み込み設定と同じスタイルを示しています。