Android自定义开关小部件用于SwitchPreference

3

我在stackoverflow上搜索,并找到了以下相关话题:

  1. 如何为Android Switch添加样式?
  2. 如何自定义Android 4中的Switch小部件?
  3. 设置switchStyle时出现错误提示未找到资源,为什么?

我也在Google Group上发现了一个bug报告:问题36636:无法覆盖switchStyle样式,最后还发现了Switch小部件的新问题:

  • I tried to make my own Preference.SwitchPreference and define layout with Switch widget

    android:id="@+android:id/switchWidget"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:thumb="@drawable/switch_thumb"
    android:layout_gravity="center"
    android:padding="16dip"
    android:focusable="false" />
    
但是我遇到了编译错误: 错误: 资源不是公共的。 (在'value'为'@+android:id/switchWidget'的'id'处)。所以我不能使用这种方式。
第二种方法是我尝试扩展Switch类并从代码中设置资源。但我发现setThumbResource方法仅适用于API 16及以上版本。但我仍然无法应用@+android:id/switchWidget,因为它不是公开的。
那么,我如何在SDK API 15中获得自定义Switch Preference?或者我如何在Preferences中自定义Switch?

你应该使用 android:id="@android:id/switchWidget"(不带 + 字符)吧? - curioustechizen
错误:资源不是公共的(在具有值“@android:id/switchWidget”的“id”处)。 - Borys
我对解决同样的问题非常感兴趣。你找到什么了吗? - Romain Pellerin
5个回答

3

我发现了一个可怕的方法来实现这个。

首先,src/com/myapp/views/preference/MySwitchPreference.java

public class MySwitchPreference extends SwitchPreference {
    public MySwitchPreference(Context context) {
        super(context);
    }

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

    public MySwitchPreference(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    protected void onBindView(View view) {
        super.onBindView(view);

        if (view instanceof ViewGroup) {
            setLayout((ViewGroup) view);
        }
    }

    @SuppressLint("NewApi")
    private void setLayout(ViewGroup viewGroup) {
        int count = viewGroup.getChildCount();
        for(int n = 0; n < count; ++n) {
            View childView = viewGroup.getChildAt(n);
            if(childView instanceof Switch) {
                final Switch switchView = (Switch) childView;

                if (Build.VERSION.SDK_INT > Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
                    switchView.setThumbResource(com.myapp.R.drawable.switch_inner);
                    switchView.setTrackResource(com.myapp.R.drawable.switch_track);
                }
                return;
            }
            else if (childView instanceof ViewGroup)
                setLayout((ViewGroup) childView);
        }
    }
}

现在,res/xml/preferences.xml

<com.myapp.views.preference.MySwitchPreference
            android:switchTextOff="Off"
            android:switchTextOn="On"
            android:title="whatever"
            android:key="switch" />

这有点棘手,只适用于 Android > 16。


当API <= 16时会发生什么情况?会使用默认的开关小部件或抛出异常吗? - Weekend

1

关于开关问题不是很清楚,但可以使用以下ToggleButton

在布局中定义按钮:

<ToggleButton
            android:id="@+id/your_awesome_toggle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:gravity="center_vertical|center_horizontal"
            android:layout_marginRight="15dp"
            android:textOn=""
            android:textOff=""
            android:background="@drawable/toggle_button"
        />

创建一个选择器:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
    <item 
        android:state_checked="false" 
        android:state_focused="false"
        android:drawable="@drawable/switch_off_btn" />
    <item 
        android:state_checked="true" 
        android:state_focused="false" 
        android:drawable="@drawable/switch_on_btn" />
    <item 
        android:drawable="@drawable/switch_off_btn" />
</selector>

OnClickListener:

    toggleOnOff = (ToggleButton) findViewById(R.id.your_awesome_toggle);

    toggleOnOff.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            updateButtons();
            if(toggleOnOff.isChecked()){
                 SharedPreferences emailPrefs = getSharedPreferences(rememberToggleOnOff,MODE_PRIVATE);
                 SharedPreferences.Editor editor = yourPrefs.edit();
                 editor.putBoolean("mon", true);
                 editor.commit();
            }
            else {
                SharedPreferences emailPrefs = getSharedPreferences(rememberToggleOnOff,MODE_PRIVATE);
                SharedPreferences.Editor editor = yourPrefs.edit();
                editor.putBoolean("mon", false);
                editor.commit();
            }
        }
    });
    checkToggleState();

checkToggleState 方法:

/**
     * Checks the state of the Toggle button preferences.  
     * If preferences are true set the toggle to on, if false set the toggle off.  
     * 
     */
    private void checkToggleState() {
        SharedPreferences yourPrefs = getSharedPreferences(rememberToggleOnOff,MODE_PRIVATE);
        boolean mON = yourPrefs.getBoolean("mon", true);
        if(mON) {
            toggleOnOff.setChecked(true);
        }
        else {
            toggleOnOff.setChecked(false);
        }
    }

0

更改:

android:id="@+android:id/switchWidget"

至:

android:id="@+id/switchWidget"

这里可以找到一个简单的开关示例here

Switch小部件仅支持14及以上的API级别,但是如果您想在API级别低于14的情况下使用Switch Preference,请查看this

更新:如果您想自定义样式开关,请尝试this


我需要使用 "@+android:id/switchWidget" ID,因为这个ID在 SwitchPreference 内部使用。我的问题是:“我如何获得适用于 SDK API 15 的自定义开关偏好设置?或者如何自定义偏好设置中的开关?” - Borys
еҰӮжһңжӮЁжғідҪҝз”Ё<SwitchPreference>жҲ–<Switch>пјҢеҲҷдёҚйңҖиҰҒдҪҝз”Ё"@+android:id/switchWidget"гҖӮ - Alejandro Colorado
你能给我提供一种解决方案,如何更改首选项中默认开关的颜色?或者更改开/关状态的可绘制对象? - Borys
Alejandro,你自己试过了吗?还是只是理论?当然,在发布我的问题之前,我已经尝试过了。如果你有工作样式的偏好示例,请在此处发布。不要发布对所有其他情况都有效的链接,除了我的情况。 - Borys
1
我已经定制了许多布局,但并没有专门定制SwitchPreference。仅通过阅读和分析代码,我非常确定我给你的链接中描述的定制可以实现,并且与您所要求的非常相似。在您的问题中,您没有提到尝试过该链接,因此我将其包含在内。别担心,如果您尝试了它并且感到困扰,我将停止发布任何可能帮助您的内容。 - Alejandro Colorado

0
继承SwitchPreference类并在preferences.xml中使用它,其中布局指向您的自定义布局。然后,在继承的SwitchPreference类的onBind方法中,您可以通过id找到相应的视图并设置侦听器。不要忘记在onBind()中调用super。

-3

更改:

android:id="@+android:id/switchWidget"

To:

android:id="@*android:id/switchWidget"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接