簡體   English   中英

AutoCompleteTextView:檢測何時關閉下拉菜單並且未選擇項目

[英]AutoCompleteTextView: detecting when dropdown is dismissed and item is NOT selected

我需要知道用戶何時在AutoCompleteTextView下拉列表之外點擊以將其關閉(即他們通過選擇列表中的項目來關閉彈出窗口)。 我已經設置了setOnDismissListener() ,如下所示:

    mAutoView.setOnDismissListener(new AutoCompleteTextView.OnDismissListener() {
        @Override
        public void onDismiss() {
            CharSequence msg = "isPerformingCompletion = " + mAutoView.isPerformingCompletion() +
                    "   Item selected at = " + mAutoView.getListSelection();
            Toast.makeText(getContext(), msg, Toast.LENGTH_LONG).show();
        }
    });

還有一個像這樣的 OnItemClickListener:

 private AdapterView.OnItemClickListener mAutocompleteClickListener
        = new AdapterView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        // get selected item and pass it to result callback
    }
};

onDismiss事件在onItemClick事件之前觸發,不幸的是,在onItemClick事件觸發之前,“isPerformingCompletion()”和“getListSelection()”方法都不會返回值。

任何人都可以建議一種在沒有列表選擇的情況下檢測解雇的方法嗎?

下面的代碼將檢測到如果用戶關閉 autocompletetextview 的下拉菜單,然后 onDismiss 它將使用 Geocode API 檢查所選輸入,如果有結果則所選輸入有效,否則輸入無效,所以在這種情況下,輸入文本將在幾秒鍾內消失。

mAutoView.setOnDismissListener {
    try {
        val fromLocationName = Geocoder(context).getFromLocationName(mAutoView.getText().toString(), 1)
        if (fromLocationName != null && fromLocationName.isNotEmpty()) {
            Log.d(TAG, "Address valid")
        } else {
            mAutoView.setText("")
            Log.d(TAG, "Address not valid")
        }
    } catch (e: Exception) {
        mAutoView.setText("")
        Log.d(TAG, "Address not valid with Exception")
    }
}

意味着您需要在 OnDismiss 中使用一種驗證器,它將檢查輸入文本是否有效,基於驗證您可以向用戶指示輸入的輸入是否有效。

AutoCompleteTextView:檢測何時關閉下拉菜單並且未選擇項目

如果我理解你的話,你需要通過觸摸它的外部而不是選擇一個項目來捕捉解除 draopDown 的事件。

出於某種原因, setOnDismissListener對我不起作用。 如果不觸摸在任一事件(項目單擊或觸摸外部)上調用的內部ListPopupWindow ,我就找不到線索。

通過注冊內部OnItemClickListener偵聽器來區分事件,以將視圖的標記設置為指示BY_ITEM_CLICK的某個值; 如果標簽是其他東西; 它將被視為觸摸外部事件。

這是一個可用於此的自定義AutoCompleteTextView

import android.annotation.SuppressLint
import android.content.Context
import android.util.AttributeSet
import android.view.KeyEvent
import android.view.View
import android.widget.AdapterView
import android.widget.AutoCompleteTextView
import android.widget.ListPopupWindow
import androidx.appcompat.widget.AppCompatAutoCompleteTextView


class OnDismissAutoCompleteTextView @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null
) : AppCompatAutoCompleteTextView(context, attrs), AdapterView.OnItemClickListener {

    interface OnMenuDismissListener {
        fun onTouchOutside()
        fun onItemClick()
        fun onBackPressed()
    }

    companion object {
        // set the tag to this value when an item is clicked to dismiss the menu
        const val BY_ITEM_CLICK = "BY_ITEM_CLICK"
        // set the tag to this value when the back is pressed to dismiss the menu
        const val BY_BACK_PRESSED = "BY_BACK_PRESSED"
    }

    init {
        super.setOnItemClickListener(this)
    }

    var onMenuDismissListener: OnMenuDismissListener? = null

    private var consumerListener: AdapterView.OnItemClickListener? = null


    @SuppressLint("DiscouragedPrivateApi")
    private fun getPopup(): ListPopupWindow? {
        try {
            val field = AutoCompleteTextView::class.java.getDeclaredField("mPopup")
            field.isAccessible = true
            return field.get(this) as ListPopupWindow
        } catch (e: NoSuchFieldException) {
            e.printStackTrace()
        } catch (e: IllegalAccessException) {
            e.printStackTrace()
        }
        return null
    }

    private fun setupDismissListener() {
        getPopup()?.let {
            it.setOnDismissListener {

                when (tag) {
                    BY_ITEM_CLICK -> onMenuDismissListener?.onItemClick() // Menu dismissal Event of clicking on the menu item
                    BY_BACK_PRESSED -> onMenuDismissListener?.onBackPressed()
                    else -> onMenuDismissListener?.onTouchOutside() // Menu dismissal Event of touching outside the menu
                }
                // reset the tag for the next dismissal
                tag = null
            }

        }
    }

    override fun onPreDraw(): Boolean {
        // Registering the mPopup window OnDismissListener
        setupDismissListener()
        return super.onPreDraw()
    }

    override fun onItemClick(p0: AdapterView<*>?, p1: View?, p2: Int, p3: Long) {
        tag = BY_ITEM_CLICK
        if (consumerListener != null) {
            consumerListener!!.onItemClick(p0, p1, p2, p3); }
    }

    override fun setOnItemClickListener(l: AdapterView.OnItemClickListener?) {
        // DO NOT CALL SUPER HERE
//        super.setOnItemClickListener(l)
        consumerListener = l
    }

    override fun onKeyPreIme(keyCode: Int, event: KeyEvent?): Boolean {
        if (keyCode == KeyEvent.KEYCODE_BACK && isPopupShowing)
            tag = BY_BACK_PRESSED
        return super.onKeyPreIme(keyCode, event)
    }

}

用法:

myAutoCompleteTV.onMenuDismissListener = object :
    OnDismissAutoCompleteTextView.OnMenuDismissListener {
    override fun onTouchOutside() {
        // Menu dismiss is due to touch outside event
        Toast.makeText(context, "touch outside", Toast.LENGTH_SHORT).show()
    }

    override fun onItemClick() {
        // Menu dismiss is due to clicking on an item
        Toast.makeText(context, "item clicked", Toast.LENGTH_SHORT).show()
    }

    override fun onBackPressed() {
        Toast.makeText(context, "back pressed", Toast.LENGTH_SHORT).show()
    }
}

暫無
暫無

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

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