如何将点击侦听器设置为此按钮

时间:2018-11-05 17:31:36

标签: android kotlin preferencefragment clicklistener

我无法执行此操作,我希望此Button屏幕上的preferences登出ClickListener

它是这样的:

enter image description here

这里是代码,buttonView始终为NULL:

class PreferencesFragment : PreferenceFragmentCompat() {

    lateinit var activity: Context

    private var prefs: SharedPreferences = BleApplication.getInstance().getDefaultSharedPreferences()

    override fun onAttach(context: Context?) {
        super.onAttach(context)
        activity = requireActivity()
    }


    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        val buttonView = view.findViewById<View>(R.id.btn_sign_out)

        if (buttonView != null) {
            buttonView.setOnClickListener {
                Toast.makeText(getActivity(), "You clicked me.", Toast.LENGTH_SHORT).show()
            }
        }
        // Hide the divider
/*        setDivider(ColorDrawable(Color.TRANSPARENT))
        setDividerHeight(0)*/
    }

    override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
        addPreferencesFromResource(R.xml.app_prefs)
    }
}

我也尝试过kotlinx.android.synthetic,但那里同样存在问题

这是xml

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

    <PreferenceCategory
        android:layout="@layout/pref_category_text"
        android:title="@string/pref_category_remote_battery_title">

        <SwitchPreferenceCompat
            android:key="@string/pref_key_category_remote_battery_switch"
            android:title="@string/pref_category_remote_battery_switch_title"
            android:summary="@string/pref_category_remote_battery_switch_summ"/>

    </PreferenceCategory>

    <PreferenceCategory
        android:layout="@layout/pref_category_text"
        android:title="@string/pref_category_sign_out_title">

        <Preference
            android:key="@string/pref_key_category_signed_out"
            android:widgetLayout="@layout/pref_category_sign_out_button"
            android:title="@string/pref_category_sign_out_button_title"
            android:summary="@string/pref_category_sign_out_buttom_summ"/>

    </PreferenceCategory>

</PreferenceScreen>

这是"@layout/pref_category_sign_out_button"布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <Button
        android:id="@+id/btn_sign_out"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/buttonshape"
        android:text="@string/pref_category_sign_out_title" />
</LinearLayout>

3 个答案:

答案 0 :(得分:1)

由于您的FragmentPreferenceFragmentCompat扩展而来,因此您不应尝试设置View.OnClickListener,而应覆盖PreferenceFragmentCompat.onPreferenceTreeClick()。根据{{​​3}},此方法为...

  

在以该PreferenceScreen为根的树中的首选项被单击时调用。

Java中的代码示例:

@Override
onPreferenceTreeClick(Preference preference){
    if(preference.getKey().equals(getContext().getString(R.string.pref_key_category_signed_out))){
       // user clicked signout "button"
       // take appropriate actions
       // return "true" to indicate you handled the click
       return true;
    }
    return false;
}

Kotlin中的代码示例(我希望我可以信任Android Studio:P)

override fun onPreferenceTreeClick(preferenceScreen: PreferenceScreen, preference: Preference): Boolean {
    return if (preference.key == context.getString(R.string.pref_key_category_signed_out)) {
        // user clicked signout "button"
        // take appropriate actions
        // return "true" to indicate you handled the click
        true
    } else false
}

这将使您能够捕获Preference而不是Button的点击事件。

为了做到这一点,可以使用自定义Preference并覆盖onBindViewHolder(PreferenceViewHolder)。由于PreferenceViewHolder-与RecyclerView.ViewHolder类似-具有字段itemView,其中包含膨胀的布局,因此这是设置我们自己的View.OnClickListener的好机会。

SignOutPreference来自TwoStatePreference(在 com.android.support:preference-v7 库中)的扩展,因为用您的自定义{{ 1}}仅需要设置CheckBox属性,就像您在代码段中所做的一样:

Button

SignOutPreference.java

android:widgetLayout

答案 1 :(得分:1)

我一直在寻找一个简单的答案并找到了一种方法。只需在 onClick 文件中为按钮设置 xml 属性,并在首选项片段的父活动中实现该方法。 (重要的是在 Activity 中实现它,而不是在 Preference Fragment 中。否则它会让你崩溃)
我想让我的 onClick 方法仅在触摸(点击)按钮时工作,而不响应按钮外区域的点击。到目前为止,这是我想要的唯一方法。

我的代码是用 Kotlin 写的,但是逻辑很简单,所以用 java 写起来也不难。

这是我用于偏好设置的 button.xmlwidgetLayout。看看我是如何设置 android:onClick= 属性的。

<?xml version="1.0" encoding="utf-8"?>
<Button
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/btn"
    android:text="reset"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    style="@style/rippleEffect" //my custom ripple effect
    android:onClick="onClickMethod">
</Button>

然后我在首选项片段的父活动中实现了 onClickMethod。这个回调方法应该是public,并且有View作为输入参数。
(有关更多信息,请阅读此 -> How exactly does the android:onClick XML attribute differ from setOnClickListener?

fun onClickMethod(view: View) {
    //do something
}

下面是我的preference.xml

<Preference
    android:key="pref_key"
    android:title="Reset"
    android:summary="summary.."
    app:iconSpaceReserved="false"
    android:widgetLayout="@layout/button"/>

我还尝试以编程方式设置 ClickListener,但唯一没有错误的方法是在 ClickListener 中设置按钮的 PreferenceClickListener。这只工作了一半,因为我需要先触摸(单击)首选项以初始化按钮的 ClickListener

val view = findPreference<androidx.preference.Preference>("pref_key")
var isFirst = true
view?.setOnPreferenceClickListener {
    if (isFirst) {
        btn.setOnClickListener {
            Toast.makeText(requireContext(), "button clicked!", Toast.LENGTH_SHORT).show()
        }
        isFirst = false
        it.summary = "unlocked"
    } else {
        isFirst = true
        it.summary = "locked - tap to unlock"
    }
    true
}



无论如何,这个答案对我来说效果很好,但我仍在寻找一种使用我的首选项键的方法,因为此方法没有完全使用首选项属性,而只是作为布局使用。但现在我希望这对那些想要在 android 偏好中使用按钮的人有所帮助。

答案 2 :(得分:0)

正如@ 0X0nosugar所述,您可以使用onPreferenceTreeClicked方法以这种便捷的方式处理所有点击:

@Override
onPreferenceTreeClick(Preference preference){
    if ((preference.getKey().equals(getContext().getString(R.string.pref_key_category_signed_out))){
       // user clicked signout "button"
       // take appropriate actions
       // return "true" to indicate you handled the click
       return true;
    }
    return false;
}

通过widgetLayout使用自定义按钮时的问题是,当按钮单击不是首选项单击时,处理程序将无法捕获它。解决此问题的一种方法是仅禁用按钮的内置单击,如下所示:

<Button
    android:id="@+id/btn_sign_out"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/buttonshape"
    android:text="@string/pref_category_sign_out_title"
    android:clickable="false"/>

请参阅最后一行。这样,您无需仅为按钮创建额外的类,就可以轻松访问PreferencesFragment类中具有的任何方法和变量。

我敢肯定,有一种更好的方法可以从按钮单击中触发“偏好设置”单击,但至少效果很好。