I found a work around for this without having to create custom preferences.
One benefit with this solution is that you can use the same widget resource with different implementations of listeners i.e. the 'setOnClickListener'.
The example below creates two EditTextPreferecnes, each pointing to the same widget layout. Then an addOnChildAttachStateChangeListener is used to set the widgets as desired. The listener is needed because the view bindings of the preferences in the preference Recycler view is one of the last things that happen or after onResume().
Also, make sure to use non zero Id's.
Strings:
<resources>
<!-- Preference Titles -->
<string name="prefs_header">Prefs With Widgets</string>
<!-- Preferences -->
<string name="pref_key_a">pref_key_a</string>
<string name="pref_key_b">pref_key_b</string>
</resources>
Widget Layout:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageButton
android:id="@+id/imageButton"
style="@android:style/Widget.Holo.ImageButton"
android:layout_width="32dp"
android:layout_height="32dp"
android:contentDescription="@string/messages_header"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@android:drawable/stat_sys_download" />
</androidx.constraintlayout.widget.ConstraintLayout>
Preferecne Layout:
<PreferenceScreen xmlns:app="http://schemas.android.com/apk/res-auto">
<PreferenceCategory
app:iconSpaceReserved="false"
app:title="Prefs With Widgets">
<EditTextPreference
app:iconSpaceReserved="false"
app:key="@string/pref_key_a"
app:title="Test Button A"
app:useSimpleSummaryProvider="true"
app:widgetLayout="@layout/my_widget" />
<EditTextPreference
app:iconSpaceReserved="false"
app:key="@string/pref_key_b"
app:title="Test Button B"
app:useSimpleSummaryProvider="true"
app:widgetLayout="@layout/my_widget" />
</PreferenceCategory>
</PreferenceScreen>
Kotlin:
class SettingsFragment : PreferenceFragmentCompat() {
private lateinit var _onChildAttachListener : RecyclerView.OnChildAttachStateChangeListener
private lateinit var _editTextA : EditTextPreference
private lateinit var _editTextB : EditTextPreference
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.root_preferences, rootKey)
_editTextA = preferenceScreen.findPreference(getString(R.string.pref_key_a))!!
_editTextB = preferenceScreen.findPreference(getString(R.string.pref_key_b))!!
_editTextA.setViewId(PREF_A_ID)
_editTextB.setViewId(PREF_B_ID)
_onChildAttachListener = object : RecyclerView.OnChildAttachStateChangeListener {
override fun onChildViewAttachedToWindow(view: View) {
if(PREF_A_ID == view.id){
view.findViewById<ImageButton>(R.id.imageButton).setOnClickListener {
Toast.makeText(context, "Button A", Toast.LENGTH_SHORT).show()
}
}
if(PREF_B_ID == view.id){
view.findViewById<ImageButton>(R.id.imageButton).setOnClickListener {
Toast.makeText(context, "Button B", Toast.LENGTH_SHORT).show()
}
}
}
override fun onChildViewDetachedFromWindow(view: View) {
// Do nothing..
}
}
}
override fun onResume() {
listView.addOnChildAttachStateChangeListener(_onChildAttachListener)
super.onResume()
}
override fun onDestroy() {
listView.removeOnChildAttachStateChangeListener(_onChildAttachListener)
super.onDestroy()
}
companion object {
// Note: Set ID's to anything but 0
const val PREF_A_ID = 1
const val PREF_B_ID = 2
}
}