自定義SwitchPreference時遇到的問題

作爲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呢,不知道各位看官有沒有明白我說的,有沒有什麼好的建議?


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章