簡體   English   中英

如何為這個按鈕設置點擊監聽器

[英]How to set click listener to this Button

我不能ClickListener工作我希望這個preferences屏幕上的注銷Button有一個ClickListener

這是它的樣子:

在此處輸入圖片說明

這是代碼, 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>

由於您的FragmentPreferenceFragmentCompat擴展,您不應該嘗試設置View.OnClickListener而是覆蓋PreferenceFragmentCompat.onPreferenceTreeClick() 根據文檔,這種方法是...

單擊以該 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

SignOutPreferenceTwoStatePreference (在com.android.support:preference-v7庫中),因為用您的自定義Button替換CheckBox小部件只需要設置android:widgetLayout屬性,就像您在代碼片段中所做的那樣:

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

    <your.package.name.SignOutPreference
        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>

退出首選項

public class SignOutPreference extends TwoStatePreference {
    public SignOutPreference(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public SignOutPreference(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public SignOutPreference(Context context) {
        super(context);
    }

    @Override
    public void onBindViewHolder(final PreferenceViewHolder holder) {
        super.onBindViewHolder(holder);
        Button button = holder.itemView.findViewById(R.id.btn_sign_out);
        if(button != null){
            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Toast.makeText(holder.itemView.getContext(), "CLICKED!", Toast.LENGTH_SHORT).show();
                }
            });
        }
    }
}

正如@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類中的任何方法和變量。

我確信有一種更好的方法可以通過單擊按鈕以某種方式觸發 Preference 單擊,但至少這很有效。

我正在尋找一個簡單的答案並找到了一種方法。 只需在xml文件中為按鈕設置onClick屬性,在preference片段的父Activity中實現該方法即可。 (在Activity實現它很重要,而不是在Preference Fragment 。否則它會讓你崩潰)
我想讓我的onClick方法僅在觸摸(單擊)按鈕時才起作用,而不響應按鈕外部區域中的單擊。 到目前為止,這是唯一像我想要的那樣工作的方法。

我的代碼是用 Kotlin 寫的,但邏輯很簡單,所以用 java 編寫它並不難。

這是我button.xml用於偏好的widgetLayout 看看我如何設置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作為輸入參數。
(有關更多信息,請閱讀此內容 -> android:onClick XML 屬性與 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 ,但唯一沒有錯誤的方法是當我在PreferenceClickListener設置按鈕的ClickListener 這只工作了一半,因為我需要先觸摸(單擊)首選項以初始化按鈕的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 偏好中使用按鈕的人有所幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM