2010-04-12 16 views
8

Tôi có một PreferenceActivity với một bó (Sub) PreferenceScreens. Mỗi PreferenceScreen như vậy (Sub)Screen đại diện cho một tài khoản và có tên tài khoản là tên của nó.Cập nhật mục ưu tiên hiện tại trong một PreferenceActivity khi trở về từ một (sub) PreferenceScreen

PreferenceScreen root = mgr.createPreferenceScreen(this); 
for (MyAccountClass account : myAccounts) { 
    final PreferenceScreen accScreen = mgr.createPreferenceScreen(this); 

    accScreen.setTitle(account.getUsername()); 

    // add Preferences to the accScreen 
    // (for instance a "change username"-preference) 
    ... 

    root.add(accScreen); 
} 

Khi người dùng nhập vào tiểu PreferenceScreen, và chỉnh sửa các sử dụng tên tài khoản, tôi muốn PreferenceScreen ngoài để cập nhật nó PreferenceScreen-tiêu đề cho tài khoản trong câu hỏi.

Tôi đã cố gắng thêm ...

usernamePref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { 
    public boolean onPreferenceChange(Preference preference, Object newValue) { 
     accScreen.setTitle(newValue.toString()); 
     return true; 
    } 
}); 

... nhưng accScreen.setTitle dường như không có hiệu lực trên PreferenceScreen bên ngoài. Tôi đã lưu ý rằng việc gọi onContentChanged(); thực sự làm cho nó hoạt động, nhưng tôi nhận ra rằng điều này có lẽ không phải là cách ưa thích để làm điều đó.

Tôi nghi ngờ tôi nên gọi postInvalidate() trên một số chế độ xem ở đâu đó, nhưng tôi thực sự không thể tìm ra chế độ xem và thời điểm thực hiện.

PreferenceScreen android:summary update ! có thể gặp phải vấn đề tương tự như tôi.

Bất kỳ trợ giúp nào được đánh giá cao.

Trả lời

16

Tôi đã tìm thấy giải pháp cho điều này. Tôi có một hệ thống phân cấp như thế này, mỗi trong số này là một PreferenceScreen:

main settings 
    -> users list 
    -> user1 settings 
    -> user2 settings 
    ... 

Trong danh sách người dùng, tiêu đề của tiểu màn hình phụ thuộc vào các thiết lập người dùng. Bây giờ khi tôi tạo danh sách người dùng, tôi lưu trữ bộ điều hợp danh sách vào một biến trong PreferenceActivity của tôi.

PreferenceScreen usersListScreen = ... 
userScreenListAdapter = (BaseAdapter)usersListScreen.getRootAdapter(); 

Bây giờ khi userX-settings được chỉnh sửa, tôi đặt tiêu đề trong usersListScreen và sau khi cuộc gọi rằng:

userScreenListAdapter.notifyDataSetChanged(); 

mà cập nhật giao diện người dùng danh sách và những thay đổi có thể nhìn thấy.

+0

Wow, nghe có vẻ giống như con đường để đi. Tôi không có SDK Android được cài đặt vào lúc này, nhưng tôi sẽ nhận lời của bạn vì nó hoạt động. Tuyệt quá! – aioobe

+0

Giải pháp tốt cho lỗi - cảm ơn! – James

+0

điều này cũng sẽ đặt lại tất cả các thay đổi được thực hiện cho tùy chọn trong phân đoạn ưu tiên (ví dụ như người nghe) sau khi gọi! (hoặc trong các thay đổi từ khác được thực hiện từ gọi này cho đến khi nó sẽ hoàn thành xây dựng lại xem sẽ bị mất :)) – ceph3us

1

Trải nghiệm cùng một vấn đề này, nhưng onContentChanged() không hoạt động đối với tôi. Vấn đề của tôi là với PreferenceScreens có nhiều hơn một cấp độ sâu từ gốc.

Để làm theo ví dụ của bạn, nếu trước tiên bạn tạo một "Tài khoản" PreferenceScreen, và sau đó thêm mỗi đối tượng PreferenceScreen tài khoản cá nhân của bạn dưới đó. Như thế này:

 
Root Screen 
    -> "Accounts" screen 
    -> "[email protected]" screen 
     -> edit username 
     -> edit password 
     -> etc... 
    -> "[email protected]" screen 
    -> "[email protected]" screen 
    -> etc... 

Nếu người dùng thay đổi nội dung ghi tên người đó và nhấp tiết kiệm, gọi PreferenceActivity.onContentChanged() dường như chỉ ảnh hưởng đến con cháu trực tiếp của PreferenceScreen gốc. Tiêu đề và tóm tắt của màn hình thế hệ thứ ba không được vẽ lại, vẫn phản ánh giá trị cũ.

Nhìn qua mã cho onContentChanged(), có vẻ như nó chỉ tái ràng buộc() s Màn hình gốc vào ListView của ListActivity, mặc dù tôi không nghĩ rằng PreferenceScreens tiếp theo bị ràng buộc vào ListView (phải không?), vì vậy chúng tôi không thể tự ràng buộc lại bất cứ điều gì ...

Cách giải quyết duy nhất tôi có thể nghĩ là tạo các menu con như PreferenceActivitys bị cô lập thay vì PreferenceScreens, vì vậy chúng tôi có thể cố ý gọi onContentChanged() trên tổ tiên trực tiếp của chúng tôi. Nhưng đó còn là một kludge hơn so với cách giải quyết hiện tại. Bất kỳ ý tưởng?

+1

Công việc mà tôi quản lý để làm việc đó là quá tải phương thức onResume và xây dựng lại giao diện người dùng bên trong. – aioobe

+0

aioobe, bạn có thể hiển thị một số mã ví dụ về cách bạn đang làm điều đó không? –

-1

Điều này làm việc cho tôi, bạn phải lấy hộp thoại cơ bản của PreferenceScreen của bạn và đặt tiêu đề từ đó, thực sự dễ dàng.

somePrefScreen.getDialog().setTitle("Whatever you want"); 
0

Source

// Import required classes (Win: CTRL+SHIFT+O & Mac: CMD+SHIFT+O) 
public class YourCustomPreference extends PreferenceActivity { 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     // Load the preferences from an XML resource 
     addPreferencesFromResource(R.xml.preferences); 
    } 

    // some logic goes above, when you want to reset value and update 
    // EditTextPreference value. For convenience, I am going to wrap two 
    // different task in different methods 
    private void resetPreferenceValue() { 
     SharedPreferences sharedPref = PreferenceManager 
       .getDefaultSharedPreferences(this.getApplicationContext()); 
     // Get preference in editor mode 
     SharedPreferences.Editor prefEditor = sharedPref.edit(); 
     // set your default value here (could be empty as well) 
     prefEditor.putString("your_edit_text_pref_key", "DEFAULT-VALUE"); 
     prefEditor.commit(); // finally save changes 
     // Now we have updated shared preference value, but in activity it 
     // still hold the old value 
     this.resetElementValue(); 
    } 

    private void resetElementValue() { 
     // First get reference to edit-text view elements 
     EditTextPreference myPrefText = (EditTextPreference) super 
       .findPreference("your_edit_text_pref_key"); 
     // Now, manually update it's value to default/empty 
     myPrefText.setText("DEFAULT-VALUE"); 
     // Now, if you click on the item, you'll see the value you've just 
     // set here 
    } 
} 
1

PreferenceActivity#onContentChanged() sẽ làm mới toàn bộ màn hình, xuất hiện một số nhấp nháy hiệu lực thi hành.

Tuy nhiên, bạn có thể đạt được cùng một mục tiêu chọn lọc trên tùy chọn đã cho bằng phương pháp PreferenceActivity#onPreferenceTreeClick(...).

Lưu ý rằng phương pháp này hiện không được chấp nhận: hãy xem xét sử dụng fragments dường như giải quyết được nhiều vấn đề với tùy chọn tùy chỉnh (tôi chưa tự kiểm tra). Có a compatibility package cho SDK cũ hơn.

public void onSharedPreferenceChanged(SharedPreferences preferences, String key) { 

Log.v(TAG, "onSharedPreferenceChanged(...," + key + ")"); 

if (key.equals("myPref")) { 
    onPreferenceTreeClick(getPreferenceScreen(), getPreferenceManager().findPreference("myPref")); 
    Log.v(TAG, "Do whatever else you need..."); 
} 

//onContentChanged(); // this could be used but occurs screen flickering 
} 
+0

Vâng, đoán những gì ... họ trái sở thích ** OUT của thư viện hỗ trợ ** !! Vì vậy, đối với các cấp API cũ hơn, bạn vẫn phải đi với PreferenceActivity: ( –

1

Tôi chỉ đặt

((BaseAdapter)getPreferenceScreen().getRootAdapter()).notifyDataSetChanged(); 

ngay sau khi cập nhật bản tóm tắt các mục sở thích của bố mẹ tôi.

+0

không có getRootAdapter trên lib hỗ trợ – Frank

3

thông báoDataSetChanged() là giải pháp phù hợp. Nhưng tôi muốn thêm iterator đệ quy cho tất cả PreferenceScreens, như xa như tôi có một vấn đề để tìm cha mẹ thực sự của một sở thích. Đối với cấu trúc phức tạp của Preferences Tôi khuyên bạn nên này killer-code:

private void updateAll_PrefereneScreens(PreferenceGroup group) { 
    if (group instanceof PreferenceScreen) { 
     BaseAdapter adapter = (BaseAdapter) ((PreferenceScreen) group).getRootAdapter(); 
     adapter.notifyDataSetChanged(); 
    } 
    for (int i=0; i<group.getPreferenceCount(); i++) { 
     Preference pref = group.getPreference(i); 
     if (pref instanceof PreferenceGroup) { 
      updateAll_PrefereneScreens((PreferenceGroup) pref); 
     } 
    } 
} 

Tôi gọi nó là sau mỗi setSummary() để đảm bảo nó hoạt động đúng cách:

findPreference("KEY").setSummary(str); 
updateAll_PrefereneScreens(getPreferenceScreen()); 
1

này có thể là một câu trả lời cuối nhưng vẫn ... tôi đang trên nó ngay bây giờ :)

Con đường tôi đã đạt được điều đó, là bạn có thể móc vào PreferenceFragmentCompat 's onResume() phương pháp vòng đời của nó và cập nhật thủ công trường bắt buộc bằng cách đặt lại giá trị của chúng.

Lưu ý: trong ví dụ này, tôi cũng theo dõi chỉ số của Tùy chọn đã chỉnh sửa, chỉ để tránh đặt lại tất cả các đơn lẻ.

// let's say you need to update title of the parent screen 
    // when back from sub-screen(s) edition 

    private int edited = -1; 

    // this gets called everytime you get back to the parent screen 
    @Override 
    public void onResume() 
    { 
     super.onResume(); 
     if (edited != -1) 
     { 
      PreferenceScreen root = getPreferenceScreen(); 
      Preference preference = root.getPreference(edited); 

      if (preference != null) 
      { 
       String updatedValue = getPreferenceManager() 
       .getSharedPreferences() 
       .getString("your-preference-key", "your-default-value"); 

       preference.setTitle(updatedValue); 
      } 

      edited = -1; 
     } 
    } 

    // everytime you are about to navigate to a sub-screen 
    @Override 
    public boolean onPreferenceTreeClick (Preference preference) 
    { 
     // beware to save it first 
     if (preference instanceof MySubScreenPreference) 
     { 
      edited = preference.getOrder(); 
     } 

     return super.onPreferenceTreeClick(preference); 
    } 

Như quy định trong tài liệu:

onResume

gọi khi phân đoạn được hiển thị cho người sử dụng và tích cực hoạt động. Điều này thường gắn liền với Activity.onResume của vòng đời của Activity có chứa.

nào là tốt là nó cũng làm việc tất nhiên với Giao dịch FragmentManager 's.

Hy vọng điều này sẽ giúp, mã hóa vui vẻ! :)

Các vấn đề liên quan