2015-11-15 53 views
1

我正在嘗試創建一個自定義Preference以顯示在PreferenceFragment中,如下所述:Building a Custom Preference。我的自定義偏好設置應爲SwitchPreference,但有一個額外的TextView用於錯誤報告。Android:具有自定義首選項生命週期不一致性的PreferenceFragment?

我已經實現了一切並且UI看起來很好,但是當我的PreferenceFragment被顯示時,我無法初始化這個首選項!

的文檔Preference.onBindView()指出:

這是爲了搶在佈局 和他們的自定義視圖引用設置屬性的好地方。

所以我做:

@Override 
protected void onBindView(View view) { 
    super.onBindView(view); 
    txtError = (TextView) view.findViewById(R.id.error); 
} 

public void setError(String errorMessage) { 
    txtError.setText(errorMessage); 
    notifyChanged(); 
} 

然而,當我在PreferenceFragment.onResume()CustomSwitchPreference.setError(String),我得到NPE因爲txtError爲空。

我試圖找到一些解決辦法,但它看起來像有在PreferenceFragment沒有生命週期的方法,這是保證被稱爲畢竟底層Preferences有他們Views初始化(我檢查兩個Preference.onBindView(View)Preference.onCreateView(ViewGroup))。

此行爲沒有任何意義 - 當顯示PreferenceFragment時,應該有一些方法來初始化底層Preferences的UI。我怎樣才能做到這一點?

注意:致電customPreference.setTitle(String)customPreference.setSummary(String()CustomPreferenceFragment.onResume()工作正常。這僅僅是額外的TextView我不能搶參考...

CustomSwitchPreference.java:

public class CustomSwitchPreference extends SwitchPreference { 

    private TextView txtError; 

    public CustomSwitchPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 
     super(context, attrs, defStyleAttr, defStyleRes); 
    } 

    public CustomSwitchPreference(Context context, AttributeSet attrs, int defStyleAttr) { 
     super(context, attrs, defStyleAttr); 
    } 

    public CustomSwitchPreference(Context context, AttributeSet attrs) { 
     super(context, attrs); 
    } 

    public CustomSwitchPreference(Context context) { 
     super(context); 
    } 

    @Override 
    protected View onCreateView(ViewGroup parent) { 
     setLayoutResource(R.layout.custom_switch_preference_layout); 
     return super.onCreateView(parent); 
    } 

    @Override 
    protected void onBindView(View view) { 
     super.onBindView(view); 
     txtError = (TextView) view.findViewById(R.id.error); 
    } 

    public void setError(String errorMessage) { 
     txtError.setText(errorMessage); 
     notifyChanged(); 
    } 

} 

CustomPreferenceFragment.java:

public class CustomPreferenceFragment extends PreferenceFragment { 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     getPreferenceManager().setSharedPreferencesName(PREFERENCES_FILE_NAME); 
     addPreferencesFromResource(R.xml.application_settings); 
    } 


    @Override 
    public void onResume() { 
     super.onResume(); 
     Preference preference = findPreference("CUSTOM_PREF"); 
     if (preference == null || 
       !CustomSwitchPreference.class.isAssignableFrom(preference.getClass())) 
      throw new RuntimeException("couldn't get a valid reference to custom preference"); 

     CustomSwitchPreference customPreference = (CustomSwitchPreference) preference; 
     customPreference.setError("error"); 
    } 
} 

custom_switch_preference_layout.xml:

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

    <LinearLayout 
     android:orientation="vertical" 
     android:layout_width="wrap_content" 
     android:layout_height="match_parent" 
     android:layout_centerVertical="true" 
     android:layout_alignParentStart="true" 
     android:layout_toStartOf="@android:id/widget_frame"> 

     <TextView 
      android:id="@android:id/title" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:lines="1"/> 

     <TextView 
      android:id="@android:id/summary" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:maxLines="3"/> 

     <TextView 
      android:id="@+id/error" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:maxLines="3"/> 

    </LinearLayout> 

    <FrameLayout 
     android:id="@android:id/widget_frame" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_centerVertical="true" 
     android:layout_alignParentEnd="true"/> 

</RelativeLayout> 

application_settings.xml:

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

    <com.example.settings.CustomSwitchPreference 
     android:key="CUSTOM_PREF"/> 

</PreferenceScreen> 

回答

1

我找不到合適的解決方案解決這個問題 - 這種不一致感覺像AOSP中的生命週期錯誤,但我對此沒有100%的把握。

作爲一種變通方法,我所定義的回調接口CustomSwitchPreference調用在onBindView方法,以便通知所述含PreferenceFragment,它已被初始化:

@Override 
protected void onBindView(View view) { 
    super.onBindView(view); 
    txtError = (TextView) view.findViewById(R.id.error); 
    initializationListener.onInitialized(CustomSwitchPreference.this); 
} 

,並且所有操作在此CustomSwitchPreference,我想現在在onResume執行onInitialized回調。這是一個醜陋的解決方法,需要大量的樣板,但它似乎工作。