SwitchPreferenceCompat:android:switchTextOff/switchTextOn不';行不通
我试图显示一个switchPreference,它允许用户根据英里或公里显示距离。我正在使用SwitchPreferenceCompat支持库。根据库,我可以使用textSwitchOff和textSwitchOn向开关添加文本。我只想将“km”或“miles”添加到我的开关中,以便用户知道显示哪个度量 根据,我只需要以下代码:SwitchPreferenceCompat:android:switchTextOff/switchTextOn不';行不通,android,switchpreference,Android,Switchpreference,我试图显示一个switchPreference,它允许用户根据英里或公里显示距离。我正在使用SwitchPreferenceCompat支持库。根据库,我可以使用textSwitchOff和textSwitchOn向开关添加文本。我只想将“km”或“miles”添加到我的开关中,以便用户知道显示哪个度量 根据,我只需要以下代码: <android.support.v7.preference.PreferenceCategory android:layout="@layout/pre
<android.support.v7.preference.PreferenceCategory
android:layout="@layout/preferences_category"
android:title="Distance" >
<android.support.v7.preference.SwitchPreferenceCompat android:title="KM or Miles"
android:key="kmormiles"
android:switchTextOff="miles"
android:switchTextOn="km"
android:defaultValue="true"/>
</android.support.v7.preference.PreferenceCategory>
还是不行。我正在两个不同的genymotion仿真器(API 16和API 21)上尝试它。因为默认情况下使用了
SwitchCompat
小部件的SwitchPreferenceCompat
,所以这里也有一个应用程序。第一句话呢
默认情况下,文本不会显示在材质主题下,因为开关小部件资产不能很好地处理文本
也解释了为什么结果看起来一点都不好
类本身不提供设置是否显示开/关文本的可能性。因此,使其工作的一种方法可能是重写onBindViewHolder(PreferenceViewHolder)
方法以编程方式设置它
另一种可能更好的方法是使用主题化机制,不管怎样,您必须使用首选项compat库。您不能直接为视图设置任何属性,但可以定义要与android:widgetLayout
一起使用的布局。因此,只需创建自己的首选主题覆盖
<style name="MyPreferenceThemeOverlay" parent="PreferenceThemeOverlay">
<item name="switchPreferenceCompatStyle">@style/MySwitchPreferenceCompat</item>
</style>
@样式/我的开关首选项兼容
使用您自己的开关首选项样式
<style name="MySwitchPreferenceCompat" parent="Preference.SwitchPreferenceCompat">
<item name="android:widgetLayout">@layout/pref_stack</item>
</style>
@布局/预处理堆栈
使用稍微修改过的
基于tynn重写OnBindViewHolder方法的选项,我已经实现了它,它正在工作。因此,我将在这里发布带有解释性注释的代码,以防有人想要使用它
注意:我正在Xamarin.Android上开发我的应用程序,所以代码是用C#编写的,但是将其翻译成Java(或Kotlin)应该非常直观
CustomSwitchPreferenceWidget.cs
namespace KeepTravelling.Ui
{
class CustomSwitchPreferenceWidget : SwitchPreferenceCompat
{
private int TitleId = 0;
private bool IsTitleFound => TitleId > 0; //equivalent to bool IsTitleFound(){ return TitleId > 0};
public string TextWhenOn { get; set; }//getters and setters
public string TextWhenOff { get; set; }
public CustomSwitchPreferenceWidget(Context context, IAttributeSet attrs) : base(context, attrs)
{
TypedArray attrsArray = context.ObtainStyledAttributes(attrs, Resource.Styleable.CustomSwitchPreferenceWidget);
TextWhenOn = attrsArray.GetString(Resource.Styleable.CustomSwitchPreferenceWidget_textWhenOn);
TextWhenOff = attrsArray.GetString(Resource.Styleable.CustomSwitchPreferenceWidget_textWhenOff);
}
//Method that will search through holder element for a view with id = "title"
//Once found it will store it in TitleId member
private void FindTitleId(PreferenceViewHolder holder)
{
//Base element is a LinearLayout, but you can check it again to make sure it is
LinearLayout layout = (LinearLayout)holder.ItemView;
for (int i = 0; i < layout.ChildCount; i++)
{
var item = layout.GetChildAt(i);
if (item.GetType().ToString().Contains("Layout")) //check if child element is a layout view
{
ViewGroup group = (ViewGroup)item;
for (int j = 0; j < group.ChildCount; j++)
{
var nestedItem = group.GetChildAt(j);
string entryName = Context.Resources.GetResourceEntryName(nestedItem.Id);
if (entryName.Equals("title"))//we are looking for the TextView with id = "title"
{
//If we found it, store in TitleId member and return from the method
TitleId = nestedItem.Id;
return;
}
if (nestedItem.GetType().ToString().Contains("Layout"))
{
ViewGroup nestedGroup = (ViewGroup)nestedItem;
for (int k = 0; k < nestedGroup.ChildCount; k++)//3 levels should be enough and it actually never arrive here
{
var nestedNestedItem = nestedGroup.GetChildAt(k);
string nestedEntryName = Context.Resources.GetResourceEntryName(nestedNestedItem.Id);
if (entryName.Equals("title"))
{
TitleId = nestedNestedItem.Id;
return;
}
}
}
}
}
}
}
public override void OnBindViewHolder(PreferenceViewHolder holder)
{
base.OnBindViewHolder(holder);
//Check if we already have found it
if (!IsTitleFound)
{
//If not => find it!!
FindTitleId(holder);
//If for some reason it is not found, return from method
if (!IsTitleFound) return;
}
AppCompatTextView title = (AppCompatTextView)holder.FindViewById(TitleId);
if (title != null)
{
if (MChecked)//MChecked value is self-explanatory
{
title.Text = TextWhenOn;
}
else
{
title.Text = TextWhenOff;
}
}
}
}
namespace keeptraveling.Ui
{
类CustomSwitchPreferenceWidget:SwitchPreferenceCompat
{
私有int TitleId=0;
private bool IsTitleFound=>TitleId>0;//相当于bool IsTitleFound(){return TitleId>0};
公共字符串TextWhenOn{get;set;}//getter和setter
公共字符串TextWhenOff{get;set;}
公共CustomSwitchPreferenceWidget(上下文,IAttributeSet属性):基本(上下文,属性)
{
TypedArray attrsArray=context.actainStyledAttributes(attrs,Resource.Styleable.CustomSwitchPreferenceWidget);
TextWhenOn=attrsArray.GetString(Resource.Styleable.CustomSwitchPreferenceWidget\u TextWhenOn);
TextWhenOff=attrsArray.GetString(Resource.Styleable.CustomSwitchPreferenceWidget_TextWhenOff);
}
//方法,该方法将在holder元素中搜索id为=“title”的视图
//一旦找到,它将存储在TitleId成员中
私有void FindTitleId(首选视图持有者)
{
//基本元素是线性布局,但可以再次检查以确保它是线性布局
LinearLayout布局=(LinearLayout)holder.ItemView;
对于(int i=0;i找到它!!
FindTitleId(持有人);
//如果由于某种原因找不到它,请从方法返回
如果(!IsTitleFound)返回;
}
AppCompatTextView title=(AppCompatTextView)holder.FindViewById(TitleId);
如果(标题!=null)
{
if(MChecked)//MChecked值是自解释的
{
title.Text=TextWhenOn;
}
其他的
{
title.Text=TextWhenOff;
}
}
}
}
}
然后必须在值/att中声明属性
<android.support.v7.widget.SwitchCompat
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/switchWidget"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@null"
android:clickable="false"
android:focusable="false"
app:showText="true" />
namespace KeepTravelling.Ui
{
class CustomSwitchPreferenceWidget : SwitchPreferenceCompat
{
private int TitleId = 0;
private bool IsTitleFound => TitleId > 0; //equivalent to bool IsTitleFound(){ return TitleId > 0};
public string TextWhenOn { get; set; }//getters and setters
public string TextWhenOff { get; set; }
public CustomSwitchPreferenceWidget(Context context, IAttributeSet attrs) : base(context, attrs)
{
TypedArray attrsArray = context.ObtainStyledAttributes(attrs, Resource.Styleable.CustomSwitchPreferenceWidget);
TextWhenOn = attrsArray.GetString(Resource.Styleable.CustomSwitchPreferenceWidget_textWhenOn);
TextWhenOff = attrsArray.GetString(Resource.Styleable.CustomSwitchPreferenceWidget_textWhenOff);
}
//Method that will search through holder element for a view with id = "title"
//Once found it will store it in TitleId member
private void FindTitleId(PreferenceViewHolder holder)
{
//Base element is a LinearLayout, but you can check it again to make sure it is
LinearLayout layout = (LinearLayout)holder.ItemView;
for (int i = 0; i < layout.ChildCount; i++)
{
var item = layout.GetChildAt(i);
if (item.GetType().ToString().Contains("Layout")) //check if child element is a layout view
{
ViewGroup group = (ViewGroup)item;
for (int j = 0; j < group.ChildCount; j++)
{
var nestedItem = group.GetChildAt(j);
string entryName = Context.Resources.GetResourceEntryName(nestedItem.Id);
if (entryName.Equals("title"))//we are looking for the TextView with id = "title"
{
//If we found it, store in TitleId member and return from the method
TitleId = nestedItem.Id;
return;
}
if (nestedItem.GetType().ToString().Contains("Layout"))
{
ViewGroup nestedGroup = (ViewGroup)nestedItem;
for (int k = 0; k < nestedGroup.ChildCount; k++)//3 levels should be enough and it actually never arrive here
{
var nestedNestedItem = nestedGroup.GetChildAt(k);
string nestedEntryName = Context.Resources.GetResourceEntryName(nestedNestedItem.Id);
if (entryName.Equals("title"))
{
TitleId = nestedNestedItem.Id;
return;
}
}
}
}
}
}
}
public override void OnBindViewHolder(PreferenceViewHolder holder)
{
base.OnBindViewHolder(holder);
//Check if we already have found it
if (!IsTitleFound)
{
//If not => find it!!
FindTitleId(holder);
//If for some reason it is not found, return from method
if (!IsTitleFound) return;
}
AppCompatTextView title = (AppCompatTextView)holder.FindViewById(TitleId);
if (title != null)
{
if (MChecked)//MChecked value is self-explanatory
{
title.Text = TextWhenOn;
}
else
{
title.Text = TextWhenOff;
}
}
}
}
<?xml version="1.0" encoding="utf-8" ?>
<resources>
<declare-styleable name="CustomSwitchPreferenceWidget">
<attr name="textWhenOn" format="string"/>
<attr name="textWhenOff" format="string"/>
</declare-styleable>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:customAttrs="http://schemas.android.com/apk/res-auto2">
<!-- More items -->
<!-- ... -->
<KeepTravelling.Ui.CustomSwitchPreferenceWidget
android:defaultValue="true"
android:title="Start location service"
android:key="start_stop_option"
android:summary="If this option is turned off the service won't be running and thus you will not get new locations."
customAttrs:textWhenOn="Text when ON"
customAttrs:textWhenOff="Text when OFF">
</KeepTravelling.Ui.CustomSwitchPreferenceWidget>
</PreferenceScreen>