gpt4 book ai didi

android - EditText setCompoundDrawablesWithIntrinsicBounds() 在 setError() 之后不工作

转载 作者:搜寻专家 更新时间:2023-11-01 07:48:16 24 4
gpt4 key购买 nike

我有一个自定义小部件,它使用 setCompoundDrawablesWithIntrinsicBounds() 方法将一个清除按钮设置为正确的可绘制对象。现在我需要向小部件添加错误,我尝试使用默认功能并依赖于 setError() 方法。

我遇到的问题是,在我设置错误后,我的右侧可绘制对象将不会再次显示,即使我之后再次设置它也是如此。

有没有人遇到过这个问题并且可能找到了解决问题的方法?

谢谢。

乐:我忘了提到,如果我使用 setError("My error hint text", null) 而不是 setError("Please choose an valid destination!") 一切正常,但您可以猜到错误图标不会显示。

LLE:这是我的自定义类,用于处理清除图标的显示及其操作。

/**
* Class of {@link android.widget.AutoCompleteTextView} that includes a clear (dismiss / close) button with a
* OnClearListener to handle the event of clicking the button
* <br/>
* Created by ionut on 26.04.2016.
*/
public class ClearableAutoCompleteTextView extends AppCompatAutoCompleteTextView implements View.OnTouchListener {

/**
* The time(in milliseconds) used for transitioning between the supported states.
*/
private static final int TRANSITION_TIME = 500;

/**
* Flag for hide transition.
*/
private static final int TRANSITION_HIDE = 101;

/**
* Flag for show transition.
*/
private static final int TRANSITION_SHOW = 102;

/**
* Image representing the clear button. (will always be set to the right of the view).
*/
@DrawableRes
private static int mImgClearButtonRes = R.drawable.ic_clear_dark;

/**
* Task with the role of showing the clear action button.
*/
private final Runnable showClearButtonRunnable = new Runnable() {
@Override
public void run() {
Message msg = transitionHandler.obtainMessage(TRANSITION_SHOW);
msg.sendToTarget();
}
};

/**
* Task with the role of hiding the clear action button.
*/
private final Runnable hideClearButtonRunnable = new Runnable() {
@Override
public void run() {
Message msg = transitionHandler.obtainMessage(TRANSITION_HIDE);
msg.sendToTarget();
}
};

/**
* Flag indicating if the default clear functionality should be disabled.
*/
private boolean mDisableDefaultFunc;
// The default clear listener which will clear the input of any text
private OnClearListener mDefaultClearListener = new OnClearListener() {
@Override
public void onClear() {
getEditableText().clear();
setText(null);
}
};

/**
* Touch listener which will receive any touch events that this view handles.
*/
private OnTouchListener mOnTouchListener;

/**
* Custom listener which will be notified when an clear event was made from the clear button.
*/
private OnClearListener onClearListener;

/**
* Transition drawable used when showing the clear action.
*/
private TransitionDrawable mTransitionClearButtonShow = null;

/**
* Transition drawable used when hiding the clear action.
*/

private TransitionDrawable mTransitionClearButtonHide = null;

private AtomicBoolean isTransitionInProgress = new AtomicBoolean(false);

private final Handler transitionHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case TRANSITION_HIDE:
setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
isTransitionInProgress.set(false);
break;
case TRANSITION_SHOW:
setCompoundDrawablesWithIntrinsicBounds(0, 0, mImgClearButtonRes, 0);
isTransitionInProgress.set(false);
break;
default:
super.handleMessage(msg);
}
}
};

/* Required methods, not used in this implementation */
public ClearableAutoCompleteTextView(Context context) {
super(context);
init();
}

/* Required methods, not used in this implementation */
public ClearableAutoCompleteTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}

/* Required methods, not used in this implementation */
public ClearableAutoCompleteTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}

@Override
public boolean onTouch(View v, MotionEvent event) {
if (getCompoundDrawables()[2] == null) {
// Pass the touch event to other listeners, if none, the normal flow is resumed
return null != mOnTouchListener && mOnTouchListener.onTouch(v, event);
}

// React only when the UP event is detected
if (event.getAction() != MotionEvent.ACTION_UP) {
return false;
}

// Detect the clear button area of touch
int x = (int) event.getX();
int y = (int) event.getY();
int left = getWidth() - getPaddingRight() - getCompoundDrawables()[2].getIntrinsicWidth();
int right = getWidth();
boolean tappedX = x >= left && x <= right && y >= 0 && y <= (getBottom() - getTop());
if (tappedX) {
// Allow clear events only when the transition is not in progress
if (!isTransitionInProgress.get()) {
if (!mDisableDefaultFunc) {
// Call the default functionality only if it wasn't disabled
mDefaultClearListener.onClear();
}

if (null != onClearListener) {
// Call the custom clear listener so that any member listening is notified of the clear event
onClearListener.onClear();
}
}
}

// Pass the touch event to other listeners, if none, the normal flow is resumed
return null != mOnTouchListener && mOnTouchListener.onTouch(v, event);
}

@Override
public void setOnTouchListener(OnTouchListener l) {
// Instead of using the super, we manually handle the touch event (only one listener can exist normally at a
// time)
mOnTouchListener = l;
}

private void init() {
// Set the bounds of the button
setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
if (getCompoundDrawablePadding() == 0) {
// We want to have some default padding, in case no one is specified in the xml
setCompoundDrawablePadding(Dimensions.dpToPx(getContext(), 5f));
}
enableTransitionClearButton();

// if the clear button is pressed, fire up the handler. Otherwise do nothing
super.setOnTouchListener(this);
}

@Override
public void onRestoreInstanceState(Parcelable state) {
super.onRestoreInstanceState(state);
updateClearButton();
}

@Override
protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
super.onTextChanged(text, start, lengthBefore, lengthAfter);
updateClearButton();
}

/**
* When hiding/showing the clear button an transition drawable will be used instead of the default drawable res.
*/
public void enableTransitionClearButton() {
mTransitionClearButtonShow =
(TransitionDrawable) ContextCompat.getDrawable(getContext(), R.drawable.ic_clear_fade_in);
mTransitionClearButtonHide =
(TransitionDrawable) ContextCompat.getDrawable(getContext(), R.drawable.ic_clear_fade_out);
mTransitionClearButtonShow.setCrossFadeEnabled(true);
mTransitionClearButtonHide.setCrossFadeEnabled(true);
}

/**
* When hiding/showing the clear button the default drawable res will be used instead of the transition drawable.
*/
@SuppressWarnings("unused")
public void disableTransitionClearButton() {
mTransitionClearButtonShow = null;
isTransitionInProgress.set(false);
transitionHandler.removeCallbacks(hideClearButtonRunnable);
transitionHandler.removeCallbacks(showClearButtonRunnable);
}

/**
* Set an custom listener which will get notified when an clear event was triggered from the clear button.
*
* @param clearListener
* The listener
* @param disableDefaultFunc
* {@code true} to disable the default clear functionality, usually meaning it will be
* handled by the
* calling member. {@code false} allow the default functionality of clearing the input.
*
* @see #setOnClearListener(OnClearListener)
*/
public void setOnClearListener(final OnClearListener clearListener, boolean disableDefaultFunc) {
this.onClearListener = clearListener;
this.mDisableDefaultFunc = disableDefaultFunc;
}

/**
* Set an custom listener which will get notified when an clear event was triggered from the clear button.
*
* @param clearListener
* The listener
*
* @see #setOnClearListener(OnClearListener, boolean)
*/
public void setOnClearListener(final OnClearListener clearListener) {
setOnClearListener(clearListener, false);
}

/**
* Disable the default functionality of the clear event - calling this won't allow for the input to be
* automatically
* cleared (it will give the ability to make custom implementations and react to the event before the clear).
*/
@SuppressWarnings("unused")
public void disableDefaultClearFunctionality() {
mDisableDefaultFunc = true;
}

/**
* Enable the default functionality of the clear event. Will automatically clear the input when the clear button is
* clicked.
*/
@SuppressWarnings("unused")
public void enableDefaultClearFunctionality() {
mDisableDefaultFunc = false;
}

/**
* Automatically show/hide the clear button based on the current input detected.
* <br/>
* If there is no input the clear button will be hidden. If there is input detected the clear button will be shown.
*/
public void updateClearButton() {
if (isEmpty()) {
hideClearButton();
} else {
showClearButton();
}
}

private boolean isEmpty() {
if (null == getText()) {
// Invalid editable text
return true;
} else if (TextUtils.isEmpty(getText().toString())) {
// Empty
return true;
} else if (TextUtils.isEmpty(getText().toString().trim())) {
// White spaces only
return true;
}
return false;
}

/**
* Hide the clear button.
* <br/>
* If an transition drawable was provided, it will be used to create an fade out effect, otherwise the default
* drawable resource will be used.
*/
public void hideClearButton() {
if (getCompoundDrawables()[2] == null) {
// The clear button was already hidden - do nothing
return;
}

if (null == mTransitionClearButtonHide) {
setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
return;
}

mTransitionClearButtonHide.resetTransition();
isTransitionInProgress.set(true);

mTransitionClearButtonHide.startTransition(TRANSITION_TIME);
setCompoundDrawablesWithIntrinsicBounds(null, null, mTransitionClearButtonHide, null);

transitionHandler.removeCallbacks(showClearButtonRunnable);
transitionHandler.removeCallbacks(hideClearButtonRunnable);
transitionHandler.postDelayed(hideClearButtonRunnable, TRANSITION_TIME);
}

/**
* Show the clear button.
* <br/>
* If an transition drawable was provided, it will be used to create an fade in effect, otherwise the default
* drawable resource will be used.
*/
public void showClearButton() {
if (getCompoundDrawables()[2] != null) {
// The clear button was already set - do nothing
return;
}

if (null == mTransitionClearButtonShow) {
setCompoundDrawablesWithIntrinsicBounds(0, 0, mImgClearButtonRes, 0);
return;
}

isTransitionInProgress.set(true);

mTransitionClearButtonShow.startTransition(TRANSITION_TIME);
setCompoundDrawablesWithIntrinsicBounds(null, null, mTransitionClearButtonShow, null);

transitionHandler.removeCallbacks(hideClearButtonRunnable);
transitionHandler.removeCallbacks(showClearButtonRunnable);
transitionHandler.postDelayed(showClearButtonRunnable, TRANSITION_TIME);
}

/**
* Custom contract which is used to notify any listeners that an clear event was triggered.
*/
public interface OnClearListener {

/**
* Clear event from the clear button triggered.
*/
void onClear();
}
}

当我想显示错误时,我使用以下命令:

 // Enable and show the error
mClearView.requestFocus(); // we need to request focus, otherwise the error won't be shown
mClearView.setError("Please choose an valid destination!", null);

如果我使用:mClearView.setError("Please choose an valid destination!"),以便显示错误图标,此后将不再显示清除按钮。

最佳答案

由于 setCompoundDrawablesWithIntrinsicBounds() 的文档(并非如此)明确指出后续调用应覆盖先前设置的 drawable,而 setError() 的文档说明如下:

Sets the right-hand compound drawable of the TextView to the "error" icon and sets an error message that will be displayed in a popup when the TextView has focus.

我认为这是一个错误。

在设置新的可绘制对象之前调用 setError(null) 并将先前设置的可绘制对象设置为 null 是一种可能的解决方法:

void setError(String error) {
editText.setError(error);
}

void setCompoundDrawableRight(Drawable rightDrawable) {
editText.setError(null);
editText.setCompoundDrawables(null, null, null, null);

editText.setCompoundDrawablesWithIntrinsicBounds(null, null, rightDrawable, null);
}

关于android - EditText setCompoundDrawablesWithIntrinsicBounds() 在 setError() 之后不工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39364379/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com