2012-04-05 36 views
6

Tôi cần các mục động trong ListPreference nên tôi không thể sử dụng cách thiết lập XML thông thường trong đó có rất nhiều tài liệu trực tuyến. Cho đến nay tôi đã thiết lập sau đây như bạn có thể thấy dưới đây. Vấn đề là khi tôi chạy, tôi thấy hộp thoại có tiêu đề và tin nhắn nhưng không có mục nào được hiển thị mặc dù tôi biết rằng các mục và giá trị không trống (tôi biết rằng các mục nhập và giá trị của tôi giống nhau nhưng tôi sẽ gặp lỗi nếu tôi không mục đã cung cấp)Custom ListPreference với các mục nhập động


my.preference.DynamicPreference 
      android:title="@string/date_format" 
      android:dialogMessage="@string/profile_info_date_format" 
      android:entryValues="@array/date_format_values" 
      android:entries="@array/date_format_values" 

public class DynamicPreference extends ListPreference { 
    private int index; 

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

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

    @Override 
    protected void onPrepareDialogBuilder(AlertDialog.Builder builder) { 
     builder.setTitle(getTitle()); 
     builder.setMessage(getDialogMessage()); 
     builder.setSingleChoiceItems(entries(), -1, new DialogInterface.OnClickListener() { 
      @Override 
      public void onClick(DialogInterface dialogInterface, int i) { 

      } 
     }); 
     super.onPrepareDialogBuilder(builder); 
    } 

    @Override 
    public void setEntries(CharSequence[] sequence) { 
     CharSequence[] entries = listObjects().toArray(new CharSequence[listObjects().size()]); 
     super.setEntries(entries); 
    } 

    @Override 
    public void setEntryValues(CharSequence[] sequence) { 
     CharSequence[] values = getContext().getResources().getStringArray(R.string.date_format); 
     super.setEntryValues(values); 
    } 
}

Trả lời

14

Android: dialogMessage là điểm khởi đầu tốt ở đây, cảm ơn bạn @MH. để phát hiện ra nó. Bellow được thiết lập đơn giản tôi đã kết thúc với, tôi hy vọng ai đó có thể tìm thấy nó hữu ích

<my.preference.DynamicPreference 
     android:title="@string/local_time" 
     android:key="profile_info_local_time" 
     /> 

public class DynamicPreference extends ListPreference { 


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

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

    @Override 
    protected View onCreateDialogView() { 
     ListView view = new ListView(getContext()); 
     view.setAdapter(adapter()); 
     setEntries(entries()); 
     setEntryValues(entryValues()); 
     setValueIndex(initializeIndex()); 
     return view; 
    } 

    private ListAdapter adapter() { 
     return new ArrayAdapter(getContext(), android.R.layout.select_dialog_singlechoice); 
    } 

    private CharSequence[] entries() { 
     //action to provide entry data in char sequence array for list 
    } 

    private CharSequence[] entryValues() { 
     //action to provide value data for list 
    } 
} 
+0

Đây có phải là cách duy nhất để điền vào 'ListPreference' theo cách có lập trình? – enzom83

+0

@ enzom83 đây là ý tưởng cơ bản về cách thực hiện. Tôi không tuyên bố là tốt nhất, nhưng như xa bạn có thể thấy không có bất kỳ bài viết nào khác liên quan đến nó. Bạn đang gặp một số vấn đề? –

+1

@peter_budo: Không cần phải mở rộng ListPreference, nó là đủ để thiết lập một số giá trị ban đầu trong 'onCreate()' và sau đó ghi đè lên xử lý 'onPreferenceClick()' cho đối tượng cụ thể. Đây là một ví dụ: http://stackoverflow.com/questions/6474707/how-to-fill-listpreference-dynamically-when-onpreferenceclick-is-triggered – ccpizza

3

tôi có thể thấy một số khả năng tiềm tàng cho lý do tại sao nó không hoạt động như mong đợi:

  1. đâu listObjects đến từ đâu? Sự hiện diện của nó cho thấy đó là một biến thành viên, nhưng tôi không thấy nó được thiết lập hoặc khởi tạo ở bất cứ đâu. Kiểm tra xem bạn không sử dụng danh sách 'trống' để điền vào hộp thoại, vì điều đó có thể gây ra sự vắng mặt của bất kỳ mục nào trong đó.

  2. Hoặc, bạn có bao giờ gọi một cách rõ ràng setEntries(...)setEntryValues(...)? Tôi hỏi, vì ListPreference không sử dụng hai bộ định cư này trong nội bộ - nó trực tiếp sử dụng các biến thành viên riêng (mEntriesmEntryValues) cho điều đó. Nói cách khác, nếu bạn không bao giờ tự gọi cả hai hàm, thì sẽ không có ai, điều đó có nghĩa là các mảng sẽ không bao giờ được đặt trên lớp siêu; do đó hộp thoại trống.

  3. Tương tự như quan sát đầu tiên của tôi: entries() là gì? Nó ngồi trong onPrepareDialogBuilder, nhưng nó dường như không được khai báo ở bất cứ đâu.

Có lẽ cách tốt nhất để bắt đầu thêm một số đoạn mã hơn, bởi vì dựa trên tất cả những gì còn thiếu, không có cách nào nói cho mà nguồn gốc chính xác của vấn đề của bạn nằm ...

Edit: rồi , Tôi đã thiết lập một dự án thử nghiệm nhanh để làm theo các bước của bạn. Giải pháp cho vấn đề của bạn thực sự khá đơn giản: loại bỏ thuộc tính android:dialogMessage và các mục danh sách của bạn sẽ hiển thị - Tôi phải thêm rằng tôi chỉ thử nghiệm điều này với một số đơn giản là ListPreference.

Có thể dễ dàng tìm thấy sự cố nếu bạn xem mã nguồn cho ListPreference, với độ dài từ DialogPreference. Trong ShowDialog() sau đây có thể được tìm thấy:

285  View contentView = onCreateDialogView(); 
286  if (contentView != null) { 
287   onBindDialogView(contentView); 
288   mBuilder.setView(contentView); 
289  } else { 
290   mBuilder.setMessage(mDialogMessage); 
291  } 
292   
293  onPrepareDialogBuilder(mBuilder); 

Bây giờ, khi bạn có thể thấy tất cả phụ thuộc vào những gì onCreateDialog lợi nhuận, bởi vì lúc onPrepareDialogBuilder được gọi là, quyết định những gì để hiển thị đã được thực hiện. Vì vậy, chúng ta hãy xem xét điều đó:

336 protected View onCreateDialogView() { 
337  if (mDialogLayoutResId == 0) { 
338   return null; 
339  } 
340   
341  LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(
342    Context.LAYOUT_INFLATER_SERVICE); 
343  return inflater.inflate(mDialogLayoutResId, null); 
344 } 

Có vẻ như nó cố gắng thổi phồng tài nguyên được tham chiếu bởi mDialogLayoutResId. Nếu không được đặt hoặc khả dụng, nó sẽ trả lại null và chỉ khi đó hộp thoại 'tin nhắn' sẽ hiển thị. Nội dung (danh sách với các mục) sẽ chỉ hiển thị nếu có một bố cục hợp lệ được tham chiếu. Nếu bạn muốn cả nội dung và thông báo hiển thị, bạn sẽ cần thêm bố cục hộp thoại tùy chỉnh bằng cách sử dụng thuộc tính android:dialogLayout và thêm TextView với android:id="@android:id/message" làm id. Trong trường hợp của ListPreference, thông báo sau đó sẽ được hiển thị bên dưới danh sách theo mặc định.

Lưu ý rằng bạn thực hiện không cần phải mở rộng ListPreference tích hợp để thêm mục nhập và giá trị theo chương trình. Gọi đơn giản setEntries(...)setEntryValues(...) trên thể hiện ListPreference với dữ liệu bạn muốn hiển thị.

Ngoài ra, trong trường hợp của lớp con DynamicPreference, mọi hành vi bạn thay đổi có thể bị ghi đè khi bạn gọi super.onPrepareDialogBuilder(builder) tất cả các cách ở cuối phương thức của bạn. Như đã đề cập trước đó mặc dù: Tôi vừa thử nghiệm điều này với mặc định ListPreference và có vẻ như hoạt động tốt và làm mọi thứ bạn yêu cầu.

+0

1) Một phần của mã mà tôi đã không được đăng, nhưng tôi có thể đảm bảo với bạn rằng nó trở lại mảng như mong đợi. 2) Nope không gọi chúng ở bất cứ nơi nào, có vẻ như tôi có thể hiểu lầm họ sử dụng. 3) Như trong trường hợp đầu tiên, một phần của mã mà tôi đã không gửi và một lần nữa nó trở về đối tượng hợp lệ –

+0

Xin vui lòng xem xét sửa trong câu trả lời của tôi cho cả nguyên nhân của vấn đề của bạn và giải pháp. Hóa ra bạn không cần phải phân lớp 'ListPreference'. :) –

+0

Có, tính năng này không hoạt động nếu không có thuộc tính đó. Các lớp khác mở rộng DialogPreference tôi cho đến nay được sử dụng không có vấn đề gì với nó. Tôi đã tìm kiếm nhỏ và có vẻ như thuộc tính xml android: dialogMessage cho ListPreference nằm trong danh sách lỗi Android http://code.google.com/p/android/issues/detail?id=4497 –

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