2012-03-10 36 views
8

Tôi đang tạo menu cài đặt cho phiên bản ứng dụng miễn phí của mình. Tôi có một số ListPreference hiển thị nhiều tùy chọn khác nhau. Tuy nhiên, chỉ một số tùy chọn này được cung cấp trong phiên bản miễn phí (tôi muốn tất cả các tùy chọn hiển thị - nhưng bị vô hiệu hóa, vì vậy người dùng biết những gì họ đang thiếu).Vô hiệu hóa các hàng trong ListPreference

Tôi đang cố gắng vô hiệu hóa một số hàng trong số ListPreference của mình. Có ai biết làm thế nào điều này có thể đạt được?

Trả lời

6

Giải quyết.

Tôi đã tạo một lớp tùy chỉnh mở rộng ListPreference. Sau đó, tôi đã sử dụng tùy chỉnh ArrayAdapter và các phương pháp đã sử dụng areAllItemsEnabled()isEnabled(int position).

public class CustomListPreference extends ListPreference { 

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


    protected void onPrepareDialogBuilder(Builder builder) { 
     ListAdapter listAdapter = new CustomArrayAdapter(getContext(), R.layout.listitem, getEntries(), resourceIds, index); 

     builder.setAdapter(listAdapter, this); 
     super.onPrepareDialogBuilder(builder); 
    } 
} 

public class CustomArrayAdapter extends ArrayAdapter<CharSequence> { 

public CustomArrayAdapter(Context context, int textViewResourceId, 
     CharSequence[] objects, int[] ids, int i) { 
    super(context, textViewResourceId, objects); 

} 

    public boolean areAllItemsEnabled() { 
     return false; 
    } 

    public boolean isEnabled(int position) { 
     if(position >= 2) 
      return false; 
     else 
      return true; 
    } 

public View getView(int position, View convertView, ViewGroup parent) { 
      ... 
    return row; 
} 
0

Tôi đã tìm kiếm thông qua và thông qua khắp nơi trên web, và không thể tìm thấy một cách để đạt được điều này. Câu trả lời ở trên không giúp tôi. Tôi thấy toàn bộ phương pháp "ArrayAdapter" rất không trực quan, vô ích và khó thực hiện. Cuối cùng, tôi thực sự đã phải xem xét bên trong mã nguồn cho "ListPreference", để xem những gì họ đã làm ở đó, và tìm ra cách để ghi đè lên hành vi mặc định một cách sạch sẽ và hiệu quả.

Tôi đang chia sẻ giải pháp của mình bên dưới. Tôi đã tạo lớp "SelectiveListPreference" để kế thừa hành vi của "ListPreference", nhưng thêm một nút tích cực, và ngăn chặn đóng khi một tùy chọn được nhấn. Ngoài ra còn có một thuộc tính xml mới để xác định các tùy chọn có sẵn trong phiên bản miễn phí.

Bí quyết của tôi không phải là gọi phiên bản của OnPrepareDialogBuilder của ListPreference, mà thay vào đó, thực hiện của riêng tôi, với trình xử lý nhấp chuột tùy chỉnh. Tôi không phải viết mã của riêng tôi để duy trì giá trị đã chọn, vì tôi đã sử dụng mã của ListPreference (đó là lý do tại sao tôi đã mở rộng "ListPreference" chứ không phải "Tùy chọn").

Trình xử lý tìm kiếm tài nguyên boolean "free_version" và nếu đúng, nó chỉ cho phép các tùy chọn được chỉ định trong thuộc tính xml "entry_values_free". Nếu "free_version" là sai, tất cả các tùy chọn đều được cho phép. Ngoài ra còn có một phương pháp trống cho người kế thừa, nếu một cái gì đó sẽ xảy ra khi một tùy chọn được chọn.

Thưởng thức,

Tal

public class SelectiveListPreference extends ListPreference 
{ 
    private int mSelectedIndex; 
    private Collection<CharSequence> mEntryValuesFree; 
    private Boolean mFreeVersion; 


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

    //CTOR: load members - mEntryValuesFree & mFreeVersion 
    public SelectiveListPreference(Context context, AttributeSet attrs) 
    { 
     super(context, attrs); 

     TypedArray a = context.obtainStyledAttributes(attrs, 
       R.styleable.SelectiveListPreference); 

     try 
     { 
      CharSequence[] entryValuesFree = a 
        .getTextArray(R.styleable.SelectiveListPreference_entryValuesFree); 

      mEntryValuesFree = new ArrayList<CharSequence>(
        Arrays.asList(entryValuesFree)); 
     } 
     finally 
     { 
      a.recycle(); 
     } 

     Resources resources = context.getResources(); 
     mFreeVersion = resources.getBoolean(R.bool.free_version); 
    } 

    //override ListPreference's implementation - make our own dialog with custom click handler, keep the original selected index 
    @Override 
    protected void onPrepareDialogBuilder(android.app.AlertDialog.Builder builder) 
    { 
     CharSequence[] values = this.getEntries(); 

     mSelectedIndex = this.findIndexOfValue(this.getValue()); 

     builder.setSingleChoiceItems(values, mSelectedIndex, mClickListener) 
       .setPositiveButton(android.R.string.ok, mClickListener) 
       .setNegativeButton(android.R.string.cancel, mClickListener); 
    }; 

    //empty method for inheritors 
    protected void onChoiceClick(String clickedValue) 
    { 
    } 

    //our click handler 
    OnClickListener mClickListener = new OnClickListener() 
    { 
     public void onClick(DialogInterface dialog, int which) 
     { 
      if (which >= 0)//if which is zero or greater, one of the options was clicked 
      { 
       String clickedValue = (String) SelectiveListPreference.this 
         .getEntryValues()[which]; //get the value 

       onChoiceClick(clickedValue); 

       Boolean isEnabled; 

       if (mFreeVersion) //free version - disable some of the options 
       { 
        isEnabled = (mEntryValuesFree != null && mEntryValuesFree 
          .contains(clickedValue)); 
       } 
       else //paid version - all options are open 
       { 
        isEnabled = true; 
       } 

       AlertDialog alertDialog = (AlertDialog) dialog; 

       Button positiveButton = alertDialog 
         .getButton(AlertDialog.BUTTON_POSITIVE); 

       positiveButton.setEnabled(isEnabled); 

       mSelectedIndex = which;//update current selected index 
      } 
      else //if which is a negative number, one of the buttons (positive or negative) was pressed. 
      { 
       if (which == DialogInterface.BUTTON_POSITIVE) //if the positive button was pressed, persist the value. 
       { 
        SelectiveListPreference.this.setValueIndex(mSelectedIndex); 

        SelectiveListPreference.this.onClick(dialog, 
          DialogInterface.BUTTON_POSITIVE); 
       } 

       dialog.dismiss(); //close the dialog 
      } 
     } 
    }; 
} 

EDIT: chúng ta cũng cần phải ghi đè lên các thiết kế chức onDialogClosed từ ListPreference (và không làm gì cả), nếu không, mọi thứ có giá trị không được tồn.Địa chỉ:

protected void onDialogClosed(boolean positiveResult) {} 
0

lẽ bạn có thể làm điều đó bằng cách overrding mặc định getView:

bước:

  1. Mở rộng ListPreference

  2. Override onPrepareDialogBuilder và thay thế mBuilder trong DialogPreference với ProxyBuilder

  3. Xử lý getView trong ProxyBuilder-> AlertDialog-> onShow-> getListView-> Adaptor

mẫu mã đang custom row in a listPreference?

0

Có cùng một vấn đề tôi tìm thấy một giải pháp (có thể "hack" là thích hợp hơn) . Chúng tôi có thể đăng ký OnPreferenceClickListener cho số ListPreference. Bên trong người nghe này, chúng tôi có thể nhận được hộp thoại (vì sở thích được nhấp vào, chúng tôi khá an toàn vì nó không phải là null). Có hộp thoại, chúng tôi có thể đặt OnHierarchyChangeListener trên ListView của hộp thoại trong đó chúng tôi được thông báo khi chế độ xem con mới được thêm vào. Với chế độ xem con trong tầm tay, chúng tôi có thể vô hiệu hóa nó. Giả sử rằng các mục nhập ListView được tạo theo thứ tự giống như giá trị mục nhập của ListPreference, chúng tôi thậm chí có thể nhận được giá trị mục nhập.

Tôi hy vọng ai đó thấy điều này hữu ích.

public class SettingsFragment extends PreferenceFragment { 


    private ListPreference devicePreference; 
    private boolean hasNfc; 

    @Override 
    public void onCreate(android.os.Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

    // load preferences 
    addPreferencesFromResource(R.xml.preferences); 

    hasNfc = getActivity().getPackageManager().hasSystemFeature(PackageManager.FEATURE_NFC); 

    devicePreference = (ListPreference) getPreferenceScreen().findPreference(getString(R.string.pref_device)); 

    // hack to disable selection of internal NFC device when not available 
    devicePreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { 

     public boolean onPreferenceClick(Preference preference) { 
      final ListPreference listPref = (ListPreference) preference; 
      ListView listView = ((AlertDialog)listPref.getDialog()).getListView(); 
      listView.setOnHierarchyChangeListener(new OnHierarchyChangeListener() { 

       // assuming list entries are created in the order of the entry values 
       int counter = 0; 

       public void onChildViewRemoved(View parent, View child) {} 

       public void onChildViewAdded(View parent, View child) { 
        String key = listPref.getEntryValues()[counter].toString(); 
        if (key.equals("nfc") && !hasNfc) { 
         child.setEnabled(false); 
        } 
        counter++; 
       } 
      }); 
      return false; 
     } 
    }); 
    } 
} 
+0

Không thể giải quyết phương thức getDialog(). – t0m

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