OnBindViewHolder メソッドをオーバーライドする tynn のオプションに基づいて、私はそれを実装し、機能しています。そのため、誰かが使用したい場合に備えて、コードを説明コメント付きでここに投稿します。
注: 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;
}
}
}
}
}
次に、次のようにvalues/attrs.xmlで属性を宣言する必要があります。
リソース/値/attrs.xml
<?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>
これで、それらをレイアウトで使用できるようになりました (私の場合は設定ファイルで使用しています):
Resources/xml/preferences.axml
<?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>
Android のものと一致しないように、使用している xml 名前空間を宣言する必要があることに注意してください。URL は存在する必要はありません。プロジェクト内で一意になる任意の文字列である必要があります。
そして結果:
ご不明な点がございましたら、お気軽にお問い合わせください。
編集:コードを汎用にして、あらゆる目的に使用できるようにしました。