在焦点侦听器中更改复合可绘制时,EditText会无限地触发焦点更改事件
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在焦点侦听器中更改复合可绘制时,EditText会无限地触发焦点更改事件相关的知识,希望对你有一定的参考价值。
我有一个自定义的edittext
控件,当它处于焦点并有文本时,右侧有一个清晰的(x)
图标。单击清除图标将从textbox
中删除文本。不幸的是,当你点击进入textbox
时,焦点变化事件无限激发,因为在drawable
中更改复合focus change listener
似乎会激活两个focus change events
,第一个关闭焦点,第二个重点关注。知道如何在没有无限循环的情况下让它工作吗?
这是代码:
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
方法以及将侦听器添加到基础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 Q / A:How to create EditText with cross(x) button at end of it?
在我看来,我最简单的实现是这样的:
public class ClearableEditext : EditText
{
Context mContext;
Drawable imgX;
public ClearableEditext(Context context) : base(context)
{
init(context, null);
}
public ClearableEditext(Context context, Android.Util.IAttributeSet attrs) : base(context, attrs)
{
init(context, attrs);
}
public ClearableEditext(Context context, Android.Util.IAttributeSet attrs, int defStyleAttr) : base(context, attrs, defStyleAttr)
{
init(context, attrs);
}
public ClearableEditext(Context context, Android.Util.IAttributeSet attrs, int defStyleAttr, int defStyleRes) : base(context, attrs, defStyleAttr, defStyleRes)
{
init(context, attrs);
}
public void init(Context ctx, Android.Util.IAttributeSet attrs)
{
mContext = ctx;
imgX = ContextCompat.GetDrawable(ctx, Android.Resource.Drawable.PresenceOffline);
imgX.SetBounds(0, 0, imgX.IntrinsicWidth, imgX.IntrinsicHeight);
manageClearButton();
this.SetOnTouchListener(new TouchHelper(this, imgX));
this.AddTextChangedListener(new TextListener(this));
}
public void manageClearButton()
{
if (this.Text.ToString().Equals(""))
removeClearButton();
else
addClearButton();
}
public void addClearButton()
{
this.SetCompoundDrawables(this.GetCompoundDrawables()[0],
this.GetCompoundDrawables()[1],
imgX,
this.GetCompoundDrawables()[3]);
}
public void removeClearButton()
{
this.SetCompoundDrawables(this.GetCompoundDrawables()[0],
this.GetCompoundDrawables()[1],
null,
this.GetCompoundDrawables()[3]);
}
}
public class TouchHelper : Java.Lang.Object, View.IOnTouchListener
{
ClearableEditext Editext;
public ClearableEditext objClearable { get; set; }
Drawable imgX;
public TouchHelper(ClearableEditext editext, Drawable imgx)
{
Editext = editext;
objClearable = objClearable;
imgX = imgx;
}
public bool OnTouch(View v, MotionEvent e)
{
ClearableEditext et = Editext;
if (et.GetCompoundDrawables()[2] == null)
return false;
// Only do this for up touches
if (e.Action != MotionEventActions.Up)
return false;
// Is touch on our clear button?
if (e.GetX() > et.Width - et.PaddingRight - imgX.IntrinsicWidth)
{
Editext.Text = string.Empty;
if (objClearable != null)
objClearable.removeClearButton();
}
return false;
}
}
public class TextListener : Java.Lang.Object, ITextWatcher
{
public ClearableEditext objClearable { get; set; }
public TextListener(ClearableEditext objRef)
{
objClearable = objRef;
}
public void AfterTextChanged(IEditable s)
{
}
public void BeforeTextChanged(ICharSequence s, int start, int count, int after)
{
}
public void OnTextChanged(ICharSequence s, int start, int before, int count)
{
if (objClearable != null)
objClearable.manageClearButton();
}
}
可能寿司有更好的答案,但我建议你试试这个。
要将x图标更改为自定义图标,请在init()中更改图像
以上是关于在焦点侦听器中更改复合可绘制时,EditText会无限地触发焦点更改事件的主要内容,如果未能解决你的问题,请参考以下文章
Android Edittext Drawable 点击卡住焦点