android - 在焦点监听器中更改复合可绘制对象时,EditText 会无限触发焦点更改事件

标签 android xamarin xamarin.android android-edittext

我有一个自定义的 edittext 控件,当它处于焦点状态并且有文本时,它在右侧设置了一个清晰的 (x) 图标。单击清除图标将从文本框中删除文本。不幸的是,当您单击文本框时,会无限触发焦点更改事件,因为在焦点更改监听器中更改复合可绘制对象似乎会触发另外两个焦点更改事件,第一个是关闭焦点,第二个是焦点更改回来。知道如何在没有无限循环的情况下使它工作吗?

代码如下:

public class CustomEditText : EditText {
        private Drawable clearButton;

        protected CustomEditText (IntPtr javaReference, JniHandleOwnership transfer) : base (javaReference, transfer) {
        }

        public CustomEditText (Context context) : base (context) {
            Init ();
        }

        public CustomEditText (Context context, IAttributeSet attrs) : base (context, attrs) {
            Init (attrs);
        }

        public CustomEditText (Context context, IAttributeSet attrs, int defStyle) : base (context, attrs, defStyle) {
            Init (attrs);
        }

        protected void Init (IAttributeSet attrs = null) {
            // Set up clear button
            SetupClearButton ();
            SetupEvents ();
        }

        private void SetupClearButton () {
            clearButton = ContextCompat.GetDrawable (Android.App.Application.Context, Resource.Drawable.forms_edit_text_clear_gray);
            clearButton.SetBounds (0, 0, clearButton.IntrinsicWidth, clearButton.IntrinsicHeight);
        }

        private void SetupEvents () {
            // Handle clear button visibility
            this.TextChanged += (sender, e) => {
                if (this.HasFocus)
                    UpdateClearButton ();
            };
            this.FocusChange += (object sender, FocusChangeEventArgs e) => {
                UpdateClearButton (e.HasFocus);// Gets called infinitely
            };

            // Handle clearing the text
            this.Touch += (sender, e) => {
                if (this.GetCompoundDrawables ()[2] != null && 
                    e.Event.Action == MotionEventActions.Up &&
                    e.Event.GetX () > (this.Width - this.PaddingRight - clearButton.IntrinsicWidth)) {
                    this.Text = "";
                    UpdateClearButton ();
                    e.Handled = true;
                } else
                    e.Handled = false;
            };
        }

        private void UpdateClearButton (bool hasFocus = true) {
            var compoundDrawables = this.GetCompoundDrawables ();
            var compoundDrawable = this.Text.Length == 0 || !hasFocus ? null : clearButton;
            if (compoundDrawables[2] != compoundDrawable)
                this.SetCompoundDrawables (compoundDrawables[0], compoundDrawables[1], compoundDrawable, compoundDrawables[3]);
        }
    }

最佳答案

我将 DroidParts 的 ClearableEditText 移植到 Xamarin.Android 以在使用 Android 的支持库小部件不合适时使用。

注意:DroidParts 受 Apache 2.0 许可,因此我无法将我的 C# 衍生产品完整发布到 StackOverflow,但避免连续焦点变化的关键在于 OnTouchOnFocusChange 方法以及将监听器添加到 base EditText Widget 的事实。

完整代码@ https://gist.github.com/sushihangover/01a7965aae75d8ef0589697aa8f0e750

public bool OnTouch(View v, MotionEvent e)
{
    if (GetDisplayedDrawable() != null)
    {
        int x = (int)e.GetX();
        int y = (int)e.GetY();
        int left = (loc == Location.LEFT) ? 0 : Width - PaddingRight - xD.IntrinsicWidth;
        int right = (loc == Location.LEFT) ? PaddingLeft + xD.IntrinsicWidth : Width;
        bool tappedX = x >= left && x <= right && y >= 0 && y <= (Bottom - Top);
        if (tappedX)
        {
            if (e.Action == MotionEventActions.Up)
            {
                Text = "";
                if (listener != null)
                {
                    listener.DidClearText();
                }
            }
            return true;
        }
    }
    if (l != null)
        return l.OnTouch(v, e);
    return false;
}

public void OnFocusChange(View v, bool hasFocus)
{
    if (hasFocus)
        SetClearIconVisible(!string.IsNullOrEmpty(Text));
    else
        SetClearIconVisible(false);
    if (f != null)
        f.OnFocusChange(v, hasFocus);
}

enter image description here

enter image description here

enter image description here

原始 StackOverflow 问答:How to create EditText with cross(x) button at end of it?

关于android - 在焦点监听器中更改复合可绘制对象时,EditText 会无限触发焦点更改事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48954024/

相关文章:

android - 在没有物理手机的情况下测试android opengl es 2.0,有什么办法吗?

Android:像素密度是如何计算的?

xamarin.ios - iOS8:backgroundSessionConfiguration 已弃用

c# - Xamarin Android 工具栏如何动态添加项目

启用链接器的 MvvmCross 从 4.2.3 更新到 4.4.0 后,Android EditText 绑定(bind)被破坏

android - 无效的资源目录名称 "font"Xamarin Android

android - 在单元测试中调用 Dispatchers.setMain() 时出错

android - flutter 位置,未处理的异常 : PlatformException(PERMISSION_DENIED_NEVER_ASK, 后台位置权限永远被拒绝

android - 带有图像的 Xamarin ListView 滚动不流畅

android - 无法添加 Xamarin.Facebook.AudienceNetwork.Android 包