Introduction to SwitchPreference
SwitchPreference is a UI component in Android, which is used to display the switch button in the setting interface of the application, and allows the user to toggle the state of some functions or options. SwitchPreference inherits from Preference class, so it can be used in PreferenceScreen like other preferences. When the user toggles the state of the toggle button, the app can use the OnPreferenceChangeListener listener to catch the state change event and update the app’s settings accordingly.
What is Preference Screen?
PreferenceScreen is a UI component in Android that provides a structured way to present an application’s setting options. It is a subclass of the Preference class and can contain multiple instances of the Preference class, such as CheckBoxPreference, EditTextPreference, etc. When the user clicks an option in the PreferenceScreen, it will enter a new PreferenceScreen or open a Dialog for the user to make corresponding settings.
When implementing PreferenceScreen, you need to use the PreferenceScreen tag in the layout file, as follows:
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> <!-- Contains multiple instances of the Preference class --> </PreferenceScreen>
In java code, you can use PreferenceFragment or PreferenceActivity to manage PreferenceScreen.
PreferenceFragment is a Fragment that can be added to an Activity. In PreferenceFragment, you can load a PreferenceScreen layout file by calling the addPreferencesFromResource(int) method. For example:
public class MyPreferenceFragment extends PreferenceFragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.preferences); } }
PreferenceActivity is an Activity that inherits from ListActivity. In PreferenceActivity, you can load a PreferenceScreen layout file by calling the addPreferencesFromResource(int) method. For example:
public class MyPreferenceActivity extends PreferenceActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.preferences); } }
It should be noted that starting from Android 11, it is recommended to use PreferenceFragmentCompat instead of PreferenceFragment. PreferenceFragmentCompat is a compatibility library that can be used in Android 4.0 and above.
Custom SwitchPreference layout
Dem: An activity contains a PreferenceScreen, and there is a SwitchPreference in the PreferenceScreen. The SwitchPreference uses a custom layout, and from left to right are switch, title, icon
Define a custom layout “custom_switch_preference.xml”
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:minHeight="?android:attr/listPreferredItemHeight" android:gravity="center_vertical" android:paddingStart="?android:attr/listPreferredItemPaddingStart" android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"> <Switch android:id="@android:id/switch_widget" android:layout_width="wrap_content" android:layout_height="wrap_content" android:focusable="false" android:clickable="false" android:layout_gravity="center_vertical" /> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" android:gravity="center_vertical" android:layout_marginStart="16dp"> <TextView android:id="@ + android:id/title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceListItem" android:textColor="?android:attr/textColorPrimary" android:singleLine="true" android:ellipsize="marquee" /> <TextView android:id="@ + android:id/summary" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceListItemSecondary" android:textColor="?android:attr/textColorSecondary" android:singleLine="true" android:ellipsize="marquee" /> </LinearLayout> <ImageView android:id="@ + android:id/icon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="16dp" android:layout_marginEnd="16dp" android:layout_gravity="center_vertical" /> </LinearLayout>
Create a PreferenceScreen file using this custom layout:
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> <SwitchPreference android:key="switch_preference" android:title="Switch Preference" android:icon="@drawable/ic_launcher" android:widgetLayout="@layout/custom_switch_preference" /> </PreferenceScreen>
Finally, load this PreferenceScreen in your Activity: slightly
Operation result:
Question: The order of the layout is the opposite of what we want?
Reason: The pictures and text displayed here are set in PreferenceScreen, not in custom layout. The button is in a custom layout
Modification scheme: custom SwitchPreference
Custom SwitchPreference
Create a custom SwitchPreference
public class CustomSwitchPreference extends SwitchPreference { private Drawable drawable; private String title; public CustomSwitchPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); setWidgetLayoutResource(R.layout.custom_switch_preference); } public CustomSwitchPreference(Context context, AttributeSet attrs, int defStyleAttr) { this(context, attrs, defStyleAttr, 0); } public CustomSwitchPreference(Context context, AttributeSet attrs) { this(context, attrs, android. R. attr. switchPreferenceStyle); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CustomSwitchPreference); title = a.getString(R.styleable.CustomSwitchPreference_title); drawable = a.getDrawable(R.styleable.CustomSwitchPreference_icon); a. recycle(); } public CustomSwitchPreference(Context context) { this(context, null); } @Override protected void onBindView(View view) { super.onBindView(view); TextView titleView = view.findViewById(R.id.title); ImageView iconView = view.findViewById(R.id.icon); if (titleView != null) { titleView.setText(title); } if (iconView != null) { iconView.setImageDrawable(drawable); } } }
Add custom attributes in the attrs.xml file:
<resources> <declare-styleable name="CustomSwitchPreference"> <attr name="title" format="string" /> <attr name="icon" format="reference" /> </declare-styleable> </resources>
Modify the PreferenceScreen file to use this custom SwitchPreference: and delete the title and icon attributes
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> <com.example.mvvm.preference.CustomSwitchPreference android:key="example_switch_preference" xmlns:app="http://schemas.android.com/apk/res-auto" app:title = "cherry" app:icon = "@drawable/cherry" android:defaultValue="true" /> </PreferenceScreen>
operation result