繁体   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