/**
* Makes sure the view (and any children) get the enabled state changed.
*/
private void setEnabledStateOnViews(View v, boolean enabled) {
v.setEnabled(enabled);
if (v instanceof ViewGroup) {
final ViewGroup vg = (ViewGroup) v;
for (int i = vg.getChildCount() - 1; i >= 0; i--) {
setEnabledStateOnViews(vg.getChildAt(i), enabled);
}
}
}
方法很简单,就是通过递归来改变Preference中所有子控件的enabled属性,本来可以直接通过重新这个方法就实现,但是这个方法是private,所以无法再子类中重写该方法,接着看到Preference类中onBindView(View view)方法:
protected void onBindView(View view) {
final TextView titleView = (TextView) view.findViewById(com.android.internal.R.id.title);
if (titleView != null) {
final CharSequence title = getTitle();
if (!TextUtils.isEmpty(title)) {
titleView.setText(title);
titleView.setVisibility(View.VISIBLE);
} else {
titleView.setVisibility(View.GONE);
}
}
final TextView summaryView = (TextView) view.findViewById(
com.android.internal.R.id.summary);
if (summaryView != null) {
final CharSequence summary = getSummary();
if (!TextUtils.isEmpty(summary)) {
summaryView.setText(summary);
summaryView.setVisibility(View.VISIBLE);
} else {
summaryView.setVisibility(View.GONE);
}
}
final ImageView imageView = (ImageView) view.findViewById(com.android.internal.R.id.icon);
if (imageView != null) {
if (mIconResId != 0 || mIcon != null) {
if (mIcon == null) {
mIcon = getContext().getDrawable(mIconResId);
}
if (mIcon != null) {
imageView.setImageDrawable(mIcon);
}
}
imageView.setVisibility(mIcon != null ? View.VISIBLE : View.GONE);
}
final View imageFrame = view.findViewById(com.android.internal.R.id.icon_frame);
if (imageFrame != null) {
imageFrame.setVisibility(mIcon != null ? View.VISIBLE : View.GONE);
}
if (mShouldDisableView) {
setEnabledStateOnViews(view, isEnabled());
}
}
也就是在绑定视图的方法的最后调用了setEnabledStateOnViews(View view,boolean enabled)方法,再看看SwitchPreference类重写了onBindView(View view)
方法:
@Override
protected void onBindView(View view) {
super.onBindView(view);
View checkableView = view.findViewById(com.android.internal.R.id.switchWidget);
if (checkableView != null && checkableView instanceof Checkable) {
if (checkableView instanceof Switch) {
final Switch switchView = (Switch) checkableView;
switchView.setOnCheckedChangeListener(null);
}
((Checkable) checkableView).setChecked(mChecked);
if (checkableView instanceof Switch) {
final Switch switchView = (Switch) checkableView;
switchView.setTextOn(mSwitchOn);
switchView.setTextOff(mSwitchOff);
switchView.setOnCheckedChangeListener(mListener);
}
}
syncSummaryView(view);
}
通过代码可以看到SwitchPreference重写该方法就是将Switch控件添加到Preference的视图当中。
所以要实现Switch控件的Enabled属性跟SwitchPreference的Enabled属性解绑,可以这样:自定义一个BeamSwitchPreference类继承于SwitchPreference,重写
onBindView(View view)方法,然后自己在BeamSwitchPreference类自己的setEnabledStateOnViews(View view,boolean enabled)方法,在onBindView(View view)方法最后调用它。自定义的BeamSwitchPreference类如下
public class BeamSwitchPreference extends SwitchPreference{
public BeamSwitchPreference(Context context) {
super(context);
}
public BeamSwitchPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public BeamSwitchPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public BeamSwitchPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onBindView(View view) {
//必须要调用onBindView,因为我们只需要在后面添加相应的方法
super.onBindView(view);
//如果是Switch,当enabled为false,通过调用自定义的setEnabledStateOnViews使其enabled不受影响
if(!isEnabled()){
setEnabledStateOnViews(view, isEnabled());
}
}
private void setEnabledStateOnViews(View v, boolean enabled) {
v.setEnabled(enabled);
if (v instanceof ViewGroup) {
final ViewGroup vg = (ViewGroup) v;
for (int i = vg.getChildCount() - 1; i >= 0; i--) {
//判断是否为Switch控件
if(vg.getChildAt(i) instanceof Switch){
setEnabledStateOnViews(vg.getChildAt(i), !enabled);
}else {
setEnabledStateOnViews(vg.getChildAt(i), enabled);
}
}
}
}
}
在PreferenceScreen中调用自定义的BeamSwitchPreference即可
在代码中设置相关属性:
SwitchPreference sp = (SwitchPreference) findPreference("switch_preference");
sp.setChecked(true);
sp.setEnabled(false);
最后看看自定义的BeamSwitchPreference的效果,已经达到了预期效果,并且因为整体的SwitchPreference已经是disable,所以这时候的Switch控件也是不能点击的: