繁体   English   中英

Android:如何通过右侧的交叉按钮清除 EditText

[英]Android: How to clear an EditText by cross Button in the right side

我创建了一个用于搜索的EditText ,其中包含左侧的搜索图标和右侧的图标:

<EditText
    android:id="@+id/Search"
    android:layout_width="250dp"
    android:layout_height="wrap_content"
    android:drawableLeft="@android:drawable/ic_menu_search"
    android:drawableRight="@android:drawable/ic_delete"
    android:hint="Search Product .." >
</EditText>

我想知道如何在单击十字按钮时清除EditText的内容。

先感谢您。

@aristo_sh 从处理 EditText 中可绘制对象上的单击事件中得到的改进答案

    mQueryEditText.setOnTouchListener(new OnTouchListener() {
        final int DRAWABLE_LEFT = 0;
        final int DRAWABLE_TOP = 1;
        final int DRAWABLE_RIGHT = 2;
        final int DRAWABLE_BOTTOM = 3;
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if (event.getAction() == MotionEvent.ACTION_UP) {
                int leftEdgeOfRightDrawable = mQueryEditText.getRight() 
                      - mQueryEditText.getCompoundDrawables()[DRAWABLE_RIGHT].getBounds().width();
                // when EditBox has padding, adjust leftEdge like
                // leftEdgeOfRightDrawable -= getResources().getDimension(R.dimen.edittext_padding_left_right);
                if (event.getRawX() >= leftEdgeOfRightDrawable) {
                    // clicked on clear icon
                    mQueryEditText.setText("");
                    return true;
                }
            }
            return false;
        }
    });

我更喜欢使用另一个客户Edittex作为以下可清除的编辑文本。 您可以在 xml 中将它用作普通的编辑文本。 要收听清晰的情况下,您可以setListenerClearableEdittext

 /** Copyright 2014 Alex Yanchenko * To change clear icon, set * <p/> * <pre> * android:drawableRight="@drawable/custom_icon" * </pre> */ public class ClearableEditText extends EditText implements OnTouchListener, OnFocusChangeListener, TextWatcherAdapter.TextWatcherListener { public interface Listener { void didClearText(); } public void setListener(Listener listener) { this.listener = listener; } private Drawable xD; private Listener listener; public ClearableEditText(Context context) { super(context); init(); } public ClearableEditText(Context context, AttributeSet attrs) { super(context, attrs); init(); } public ClearableEditText(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); } @Override public void setOnTouchListener(OnTouchListener l) { this.l = l; } @Override public void setOnFocusChangeListener(OnFocusChangeListener f) { this.f = f; } private OnTouchListener l; private OnFocusChangeListener f; @Override public boolean onTouch(View v, MotionEvent event) { if (getCompoundDrawables()[2] != null) { boolean tappedX = event.getX() > (getWidth() - getPaddingRight() - xD .getIntrinsicWidth()); if (tappedX) { if (event.getAction() == MotionEvent.ACTION_UP) { setText(""); if (listener != null) { listener.didClearText(); } } return true; } } if (l != null) { return l.onTouch(v, event); } return false; } @Override public void onFocusChange(View v, boolean hasFocus) { if (hasFocus) { setClearIconVisible(!TextUtils.isEmpty(getText())); } else { setClearIconVisible(false); } if (f != null) { f.onFocusChange(v, hasFocus); } } @Override public void onTextChanged(EditText view, String text) { if (isFocused()) { setClearIconVisible(!TextUtils.isEmpty(text)); } } private void init() { xD = getCompoundDrawables()[2]; if (xD == null) { xD = getResources() .getDrawable(android.R.drawable.presence_offline); } xD.setBounds(0, 0, xD.getIntrinsicWidth(), xD.getIntrinsicHeight()); setClearIconVisible(false); super.setOnTouchListener(this); super.setOnFocusChangeListener(this); addTextChangedListener(new TextWatcherAdapter(this, this)); } protected void setClearIconVisible(boolean visible) { Drawable x = visible ? xD : null; setCompoundDrawables(getCompoundDrawables()[0], getCompoundDrawables()[1], x, getCompoundDrawables()[3]); } }

编辑:我忘记了TextWatcherAdapter ,实际上它只是客户TextWatcher

public class TextWatcherAdapter implements TextWatcher {

public interface TextWatcherListener {

    void onTextChanged(EditText view, String text);

}

private final EditText view;
private final TextWatcherListener listener;

public TextWatcherAdapter(EditText editText, TextWatcherListener listener) {
    this.view = editText;
    this.listener = listener;
}

@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
    listener.onTextChanged(view, s.toString());
}

@Override
public void beforeTextChanged(CharSequence s, int start, int count,
                              int after) {
    // pass
}

@Override
public void afterTextChanged(Editable s) {
    // pass
}
}

尝试这个:

活动_main.xml

<FrameLayout
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="9dp"
    android:padding="5dp">

    <EditText
        android:id="@+id/Search"
        android:layout_width="250dp"
        android:layout_height="wrap_content"
        android:drawableLeft="@android:drawable/ic_menu_search"
        android:hint="Search Product .." >
    </EditText>

    <Button
        android:id="@+id/clearText"
        android:layout_width="23dp"
        android:layout_height="23dp"
        android:layout_marginRight="10dp"
        android:layout_gravity="right|bottom"
        android:layout_marginBottom="10dp"
        android:background="@android:drawable/ic_delete"
        android:onClick="clear"/>

</FrameLayout>

主活动.java

public class MainActivity extends AppCompatActivity {

    EditText mEditText;
    Button mClearText;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mEditText = (EditText) findViewById(R.id.Search);
        mClearText = (Button) findViewById(R.id.clearText);

        //initially clear button is invisible
        mClearText.setVisibility(View.INVISIBLE);

        //clear button visibility on text change
        mEditText.addTextChangedListener(new TextWatcher() {

            @Override
            public void afterTextChanged(Editable s) {
                //do nothing
            }

            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
                //do nothing
            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                if(s.length() != 0) {
                    mClearText.setVisibility(View.VISIBLE);
                } else {
                    mClearText.setVisibility(View.GONE);
                }
            }
        });

    }

    //clear button onclick
    public void clear(View view) {
        mEditText.setText("");
        mClearText.setVisibility(View.GONE);
    }

}

编辑:

我之前的示例无法正常工作 (1)。 以下 kotlin 扩展应适用于所有开始和结束可绘制对象,将 TextView 填充考虑在内,并且独立于它所包含的任何视图。

private const val START = 0
private const val END = 2

fun TextView.onDrawableClicked(
    onDrawableStartClicked: () -> Unit = {},
    onDrawableEndClicked: () -> Unit = {}
) {
    setOnTouchListener(View.OnTouchListener { _, event ->
        when (event.action) {
            MotionEvent.ACTION_UP -> {
                compoundDrawables[START]?.let { startDrawable ->
                    val clickableAreaStart = paddingStart
                    val clickableAreaEnd = startDrawable.bounds.width() + paddingStart
                    if (event.x >= clickableAreaStart && event.x <= clickableAreaEnd) {
                        onDrawableStartClicked()
                        return@OnTouchListener true
                    }
                }
                compoundDrawables[END]?.let { endDrawable ->
                    val startOfDrawable = width - endDrawable.bounds.width() - paddingEnd
                    val endOfDrawable = width - paddingEnd
                    if (event.x >= startOfDrawable && event.x <= endOfDrawable) {
                        onDrawableEndClicked()
                        return@OnTouchListener true
                    }
                }
            }
        }
        true
    })
}

像这样实现 end drawable:

my_view.onDrawableClicked(onDrawableEndClicked = { 
    showPilotGroupPopup() 
})

Android 建议使用至少 48dp 的触摸尺寸。 要在扩展中启用此功能,请改用以下代码(您始终可以决定忽略每个视图的额外触摸区域)。 当然,它不会在可绘制对象周围启用点击,只能在视图本身内水平点击,但总比没有好!

private const val START = 0
private const val END = 2

fun TextView.onDrawableClicked(
    onDrawableStartClicked: () -> Unit = {},
    onDrawableEndClicked: () -> Unit = {},
    applyMinimalTouchSize: Boolean = true
) {
    setOnTouchListener(View.OnTouchListener { _, event ->
        when (event.action) {
            MotionEvent.ACTION_UP -> {
                compoundDrawables[START]?.let { startDrawable ->
                    val startDrawableWidth = startDrawable.bounds.width()
                    var clickableAreaStart = paddingStart
                    var clickableAreaEnd = startDrawableWidth + paddingStart
                    if (applyMinimalTouchSize) {
                        clickableAreaStart -= getTouchSizeCorrection(resources, startDrawableWidth)
                        clickableAreaEnd += getTouchSizeCorrection(resources, startDrawableWidth)
                    }
                    if (event.x >= clickableAreaStart && event.x <= clickableAreaEnd) {
                        onDrawableStartClicked()
                        return@OnTouchListener true
                    }
                }
                compoundDrawables[END]?.let { endDrawable ->
                    val endDrawableWidth = endDrawable.bounds.width()
                    var clickableAreaStart = width - endDrawableWidth - paddingEnd
                    var clickableAreaEnd = width - paddingEnd
                    if (applyMinimalTouchSize) {
                        clickableAreaStart -= getTouchSizeCorrection(resources, endDrawableWidth)
                        clickableAreaEnd += getTouchSizeCorrection(resources, endDrawableWidth)
                    }
                    if (event.x >= clickableAreaStart && event.x <= clickableAreaEnd) {
                        onDrawableEndClicked()
                        return@OnTouchListener true
                    }
                }
            }
        }
        true
    })
}

private fun getTouchSizeCorrection(resources: Resources, visibleSize: Int): Int {
    // R.dimen.touch_size = 48dp
    return ((resources.getDimensionPixelSize(R.dimen.touch_size) - visibleSize) / 2).coerceAtLeast(0)
}

(1) 由于计算不正确,原始答案在所有情况下都不能正常工作。 此外,它返回 false,这有时会阻止触发 ACTION_UP。


原答案:

Paul Verest答案不错,但没有考虑填充。 这是左键和右键单击的示例(在 Kotlin 中),包括 editText 的填充(将 drawable 相对从 editText 的两侧移动)。

editText.setOnTouchListener(View.OnTouchListener { _, event ->
            val DRAWABLE_LEFT = 0
            val DRAWABLE_RIGHT = 2

            if (event.action == MotionEvent.ACTION_UP) {
                if (event.x <= editText.compoundDrawables[DRAWABLE_LEFT].bounds.width() + (2 * editText.paddingStart)) {
                    // Left drawable clicked
                    return@OnTouchListener true
                }
                if (event.x >= editText.right - editText.compoundDrawables[DRAWABLE_RIGHT].bounds.width() - (2 * editText.paddingEnd)) {
                    // Right drawable clicked
                    return@OnTouchListener true
                }
            }
            false
        })

笔记:

  • 我使用event.x而不是event.rawX来获取点击位置。 event.rawX是屏幕上的原始 X 坐标,它不考虑 editText 的位置(例如,防止 editText 剪切屏幕边的边距)。 event.x是相对于 editText 本身event.x的 x 坐标,这使得计算更容易理解。
  • 在使元素可点击时始终考虑填充! 当然,如果您使用 editText padding 将 drawable 移动得太远,那么使整个 padding 可点击是没有意义的。 在我的情况下,使用editText.paddingStart两次效果很好,因此可绘制对象的两侧都可以单击它。 您可能会考虑仅在起始可绘制对象的左侧使用此填充一次,并为右侧填充添加editText.compoundDrawablePadding (可绘制对象和文本之间的填充)。 当然你也可以使用一些常量dp值,这取决于你自己的喜好。 可点击填充的概念在此博客中得到了很好的解释。

我做的例子:

mPasswordView = (EditText) findViewById(R.id.password);
mPasswordView.setOnTouchListener(new View.OnTouchListener() {

        @Override
        public boolean onTouch(View view, MotionEvent motionEvent) {
            if (motionEvent.getAction() == MotionEvent.ACTION_UP){
                // 100 is a fix value for the moment but you can change it
                // according to your view
                if (motionEvent.getX()>(view.getWidth()-100)){
                    ((EditText)view).setText("");
                }
            }
            return false;
        }
    });

    mPasswordView.addTextChangedListener(new TextWatcher() {

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {

            if(s.toString().trim().length()==0){
                mPasswordView.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
            } else {
                mPasswordView.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_close_black_24dp, 0);
            }
        }

        @Override
        public void beforeTextChanged(CharSequence s, int start, int count,
                                      int after) {
            // TODO Auto-generated method stub
            mPasswordView.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);

        }

        @Override
        public void afterTextChanged(Editable s) {
            // TODO Auto-generated method stub
            if (s.toString().trim().length() == 0) {
                mPasswordView.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
            } else {
                mPasswordView.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_close_black_24dp, 0);
            }
        }
    });

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM