我有一个自定义的 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,但避免连续焦点变化的关键在于 OnTouch
和 OnFocusChange
方法以及将监听器添加到 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);
}
原始 StackOverflow 问答:How to create EditText with cross(x) button at end of it?
关于android - 在焦点监听器中更改复合可绘制对象时,EditText 会无限触发焦点更改事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48954024/