自定义SwitchPreference时遇到的问题

来源:互联网 发布:白凡泄露天机知乎 编辑:程序博客网 时间:2024/05/31 11:03

作为Android的初学者,很多地方理解不深刻,这是自己的第一篇博客,当作是纪念了。


现在的需求是,将CheckBoxPreference中的CheckBox换成一个已经写好的,有动效Switch控件,增加切换时的动效。

虽然在preference.xml中可以指定widgetLayout的样式,也就是CheckBox可换成其他的控件

<pre name="code" class="html"><CheckBoxPreference            android:defaultValue="true"            android:key="pref_key_show_recent_recipents"            android:layout="@layout/cp_layout_preference"            android:summary="@string/smsmms_recent_recipents_summary"            android:title="@string/smsmms_recent_recipents"            android:widgetLayout="@layout/cp_layout_checkbox_switchbtn" />

<pre name="code" class="html">cp_layout_checkbox_switchbtn.xml是Switch的样式,但是这样的修改会出现一个问题,当点击CheckBoxPreference时,可以达到设置的效果,但是当点击Switch这个控件时,不能达到设置的效果。也就是说Switch的点击事件没有与Preference的点击事件关联起来。后来在网上发现Android4.0之后的版本新增了SwitchPreference控件,正好与我的需求相吻合,于是便将布局改成了如下

</pre><pre>
<SwitchPreference            android:defaultValue="true"            android:key="pref_key_show_recent_recipents"            android:layout="@layout/cp_layout_preference"            android:summary="@string/smsmms_recent_recipents_summary"            android:title="@string/smsmms_recent_recipents"            android:widgetLayout="@layout/cp_layout_checkbox_switchbtn" />
这时候点击Switch控件,是能够起到设置效果的,但是新的问题来了,在整个设置页面中,有多个这样的SwitchPreference控件,当点击其中一个Switch时,其他SwitchPreference中的Switch控件的状态会同步的更新一次。

由于切换是有动效的,点击其中一个Switch,会清楚的看到其他的Switch也会有一次动态的切换,虽然其他的Switch最终的开关状态,但是切换的过程还是有了,通过查看SwitchPreference源码,发现在onBingView函数中,每次都会更新按钮的状态。

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);            }            <span style="color:#ff0000;">((Checkable) checkableView).setChecked(mChecked);</span>            if (checkableView instanceof Switch) {                final Switch switchView = (Switch) checkableView;                switchView.setTextOn(mSwitchOn);                switchView.setTextOff(mSwitchOff);                switchView.setOnCheckedChangeListener(mListener);            }        }        syncSummaryView(view);    }
从中发现每次更新状态时,都会重新设置一次mChecked的值,而正好我的动效能够清晰的看到这一次切换的过程。

分析原因,应该是每次更新时,不管Switch的check值与Preference的check值是否一次,都会切换一次Switch状态。后来发现如果切换的过程不采用动效,就看不出来这一过程了,所以我仿照SwitchPreference的实现方式,新建了MySwitchPreference类,同样继承了TwoStatePreference,不同的是在更新时加入一个判断

protected void onBindView(View view) {        super.onBindView(view);        View checkableView = view.findViewById(android.R.id.checkbox);        if (checkableView != null && checkableView instanceof Checkable) {            if (checkableView instanceof Switch) {            <span style="color:#ff0000;">Switch mSwitchView = (Switch) checkableView;                mSwitchView.setOnCheckedChangeListener(null);                if (isChecked() != mSwitchView.isChecked()) {                    mSwitchView.setChecked(isChecked());                } else {                    mSwitchView.setCheckedImmediately(isChecked());//没有动画的切换状态                }</span>                mSwitchView.setOnCheckedChangeListener(mCheckedChangeListener);            }        }    }
只有当状态不一样时,需要动效的切换,状态一样时,直接切换,没有动效。这样在视觉上便觉得只有那一个点击的Switch的状态切换了。


虽然问题解决了,但是仍然有一些疑问:

<span style="color:#ff0000;">mSwitchView.setChecked(boolean b)</span>

这个函数实现时是有判断的,如果新设置的值与原先的值相同,就直接return了,也就是说只有设置不同的值时才会有动态切换的效果。既然我这里的Switch每次都会重新设置值,那么说明每次更新时的值都与原先的值不同,但是为什么不同呢?


经过分析,原因应该是在初始化MySwitchPreference时,没有将Switch与Preference的checked状态进行同步,而Switch的默认状态是false,导致有些Preference的状态被初始化成true,导致每次调用onBindView刷新界面时,会出现Preference为true的控件中的Switch被重新设置了状态true,也就是重新更新了一次。

到底应该如何解决这个问题呢?如何将Preference的初始化状态同时传递给Switch呢,不知道各位看官有没有明白我说的,有没有什么好的建议?


0 0