android4.1上去除SwitchPreference中Switch控件与Preference的绑定响应

    SwitchPreferenceandroid4.0新加的一个控件,类似于CheckBoxPreference,继承自TwoStatePreference类,顾名思义,有两种状态,并含有一个Switch控件。

    当我们直接调用SwitchPreference控件时,会发现无论我们点击SwitchPreference控件的任何区域,Switch状态都会改变。所以,当我们想要一种效果:只是点击SwitchPreference中的Switch控件才能改变其状态时,直接调用SwitchPreference显然行不通。这里有两种方法。

方法一:继承并改写SwitchPreference

查看SwitchPreference.java源码,发现其中并没有多少内容,其中值得关注的也就是布局时会自动调用的onBindView()方法:

@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) {

        ((Checkable) checkableView).setChecked(mChecked);

        sendAccessibilityEvent(checkableView);

        if (checkableView instanceof Switch) {

            final Switch switchView = (Switch) checkableView;

            switchView.setTextOn(mSwitchOn);

            switchView.setTextOff(mSwitchOff);

            switchView.setOnCheckedChangeListener(mListener);

        }

    }

    syncSummaryView(view);

}

可以发现其中就是对Switch控件的布局和监听。想要找到整个SwitchPreference的点击事件,还要追溯到其父类TwoStatePreference中,对应方法如下:

    @Override

    protected void onClick() {

        super.onClick();

        boolean newValue = !isChecked();

        mSendClickAccessibilityEvent = true;

        if (!callChangeListener(newValue)) {

            return;

        }

        setChecked(newValue);

}

可以看出只要点击SwitchPreference就会导致isCheck()改变从而改变Switch状态。

既然知道原因,我们写一个类继承自SwitchPreference,然后重写其onClick()方法,即可。如下:

public class HftSwitchPreference extends SwitchPreference {

    ... ...

        @Override

        protected void onClick() {

    }

}

如果没有其他需要,其他方法直接调用super即可。这样,当我们再次点击SwitchPreference中除Switch意外的区域时,Switch状态就不会随之变更。至于点击这些区域想要做什么处理(如跳转等),自己在onClick()中添加相应代码即可。

方法二:重写Preference类。

SwitchPreferenceCheckBoxPreference等类似的空间,都是Preference类的延伸。查看Preference类对于的布局文件preference.xml,可以发现最后有这么一段:

    <LinearLayout android:id="@+android:id/widget_frame"

        android:layout_width="wrap_content"

        android:layout_height="match_parent"

        android:gravity="center_vertical"

        android:orientation="vertical" />

也就是Preference视图最右边的部分。这部分的布局对应Preferenceandroid:widgetLayout属性。如下,我自写一个HftPreference类继承自Preference

    public class HftPreference extends Preference {

        ... ...

    }

假设该类包名为com.hft.preference,那么在相应的xml布局文件中可这样定义该控件:

        <com.hft.preference.HftPreference

            android:key="wifi_settings"

            android:fragment="com.android.settings.wifi.WifiSettings"

            android:title="@string/wifi_settings_title"

            android:icon="@drawable/ic_settings_wireless"

            android:widgetLayout="@layout/hft_switch"/>

这里主要看android:widgetLayout属性,其对应的hft_switch.xml仅定义了一个Switch控件,当然这里是讲关于SwitchPreference的,如果想定义成其他布局文件同样完全可以。hft_switch.xml内容如下:

<?xml version="1.0" encoding="utf-8"?>

<Switch xmlns:android="http://schemas.android.com/apk/res/android"

    android:id="@+id/hft_switch"

    android:layout_width="wrap_content"

    android:layout_height="match_parent"

    android:focusable="false">

</Switch>

如果其他什么都不做修改,现在这个HftPreference控件外表已经和SwitchPreference控件一样。特别注意,这里一定要添加android:focusable="false"属性,否则Switch控件一直处于聚焦状态,将屏蔽Preference的点击事件。

至于Switch控件的点击事件,应在HftPreferenceonBindView()中处理,而Preference点击事件则在onClick()中处理。如下:

@Override

protected void onBindView(View view) {

super.onBindView(view);

Switch hftSwitch = (Switch) view.findViewById(R.id.hft_switch);

hftSwitch.setOnCheckedChangeListener(new OnCheckedChangeListener() {

@Override

public void onCheckedChanged(CompoundButton buttonView, 

                boolean isChecked)  {

              .. ...

}

});

}

@Override

protected void onClick() {

super.onClick();

    //Preference的点击事件

}

你可能感兴趣的:(android4.1上去除SwitchPreference中Switch控件与Preference的绑定响应)