【问题标题】:Custom SwitchPreference in AndroidAndroid 中的自定义 SwitchPreference
【发布时间】:2014-01-20 13:52:23
【问题描述】:

如何在 Android 中为 SwitchPreference 小部件设置自定义样式或其他可绘制的背景选择器?

(注意:不是常规的Switch 小部件,我指的是PreferenceActivity / PreferenceFragment 中使用的标准SwitchPreference 小部件)

【问题讨论】:

标签: android custom-widgets


【解决方案1】:

您必须为开关本身创建自定义布局,并且可以动态应用它。

preference.setWidgetLayoutResource(R.layout.custom_switch);

但我会详细介绍并告诉你具体如何实现这一点。

因此,您可以在 preferences.xml

之类的 xml 文件中定义您的偏好
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
    <PreferenceCategory android:title="YOUR_CATEGORY_TITLE" >
        <SwitchPreference
            android:key="SWITCH"
            android:title="YOUR_TITLE_FOR_SWITCH" />
    </PreferenceCategory>
</PreferenceScreen>

然后在 PreferenceActivty 类中的 onCreate() 方法中读取它:

    SwitchPreference pref = (SwitchPreference) findPreference(getString(R.string.SWITCH));
    //pref.setChecked(true); // You can check it already if needed to true or false or a value you have stored persistently
    pref.setWidgetLayoutResource(R.layout.custom_switch); // THIS IS THE KEY OF ALL THIS. HERE YOU SET A CUSTOM LAYOUT FOR THE WIDGET
    pref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {

        @Override
        public boolean onPreferenceChange(Preference preference, Object newValue) {
            // Here you can enable/disable whatever you need to
            return true;
        }
    });

custom_switch 布局如下所示:

<?xml version="1.0" encoding="utf-8"?>
<Switch xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/custom_switch_item"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center_vertical"
    android:textColor="@android:color/white"
    android:textIsSelectable="false"
    android:textSize="18sp"
    android:textStyle="bold"
    android:track="@drawable/switch_track" 
    android:thumb="@drawable/switch_thumb"/>

对于开关,您将有 2 个选择器用于 trackthumb 属性。 这些选择器的可绘制对象可以使用tasomaniac 建议的 Android Holo 颜色生成器生成。在这种情况下,您所要做的就是复制生成的可绘制文件夹的内容(仅适用于drawable-hdpi、drawable-mdpi、drawable-xhdpi、drawable-xxhdpi)。但是您可以为您需要的每个状态创建自定义视图。

以下是这些选择器的外观: switch_track:

<?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:drawable="@drawable/switch_bg_focused" android:state_focused="true"/>
    <item android:drawable="@drawable/switch_bg"/>

</selector>

switch_thumb:

<?xml version="1.0" encoding="utf-8"?>
     <selector xmlns:android="http://schemas.android.com/apk/res/android">

     <item android:drawable="@drawable/switch_thumb_disabled" android:state_enabled="false"/>
     <item android:drawable="@drawable/switch_thumb_pressed" android:state_pressed="true"/>
     <item android:drawable="@drawable/switch_thumb_activated" android:state_checked="true"/>
     <item android:drawable="@drawable/switch_thumb"/>

</selector>

差不多就是这样。这个解决方案帮助了我。如果我遗漏了什么,请告诉我,我会更正问题。

【讨论】:

  • 我在解决方案中遇到的问题是,小部件似乎不代表 sharedpreference 值的状态,即它永远不会根据 sp 被检查/取消检查,而 setCheck 似乎没有更改用户界面。我认为这是我使用的 Android 版本(4.4.2)的问题
  • 我无法处理任何切换偏好事件
  • @siyb - 共享首选项不会通过 setChecked 等进行更改 :) - 如果您想手动更改 sp 小部件,您需要通过首选项管理器设置首选项,然后重绘标题或重新加载视图 { 通过无效或getPreferenceScreen().removeAll(); addPreferencesFromResource(@IdRes int); }
  • 此解决方案不完整,因为在 SwitchPreference.java 中,它会搜索 ID 为“com.android.internal.R.id.switchWidget”的小部件,该小部件未被 SDK 公开。因此,您需要复制原始 SwitchPreference.Java 并将该 id 更改为您在布局中提供的内容
【解决方案2】:

您可以使用以下网站为您的 Switch 生成样式。 http://android-holo-colors.com/

然后您可以使用以下库来自定义常规 Switch 的实现。这些库还包括 SwitchPreference 替代方案。

https://github.com/BoD/android-switch-backport

https://github.com/ankri/SwitchCompatLibrary

【讨论】:

    【解决方案3】:

    这样做的一种方法是继承 SwitchPreference 并覆盖 onBindView 方法。这样做时,您仍然希望在该方法中调用 super.onBindView(view),然后在子视图中找到 Switch 并根据需要设置其样式:

    package com.example;
    
    import android.annotation.SuppressLint;
    import android.content.Context;
    import android.preference.SwitchPreference;
    import android.util.AttributeSet;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.Switch;
    
    import com.example.R;
    
    
    public class CustomSwitchPreference extends SwitchPreference {
    
        @SuppressLint("NewApi")
        public CustomSwitchPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
            super(context, attrs, defStyleAttr, defStyleRes);
        }
    
        public CustomSwitchPreference(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
    
        public CustomSwitchPreference(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        public CustomSwitchPreference(Context context) {
            super(context);
        }
    
        @Override
        protected void onBindView(View view) {
    
            super.onBindView(view);
            Switch theSwitch = findSwitchInChildviews((ViewGroup) view);
            if (theSwitch!=null) {
                //do styling here
                theSwitch.setThumbResource(R.drawable.new_thumb_resource);
            }
    
        }
    
        private Switch findSwitchInChildviews(ViewGroup view) {
            for (int i=0;i<view.getChildCount();i++) {
                View thisChildview = view.getChildAt(i);
                if (thisChildview instanceof Switch) {
                    return (Switch)thisChildview;
                }
                else if (thisChildview instanceof  ViewGroup) {
                    Switch theSwitch = findSwitchInChildviews((ViewGroup) thisChildview);
                    if (theSwitch!=null) return theSwitch;
                }
            }
            return null;
        }
    }
    

    【讨论】:

      【解决方案4】:

      在您的 style.xml 文件中创建一个样式并将其指定为 Widget.AppCompat.CompoundButton.Switch 父级。

      <style name="theme_switch_compat" parent="Widget.AppCompat.CompoundButton.Switch">
      
          <item name="colorAccent">@color/YourColorAccent</item>
      
      </style>
      

      然后你可以使用下面的链接来完成你的主题

      How to change the track color of a SwitchCompat

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-10-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多