(从源码通过反射实现)禁止EditText弹出系统键盘

来源:互联网 发布:淘宝内裤真人秀在哪看 编辑:程序博客网 时间:2024/05/24 23:16

上篇文章还没写完,真的是没有太多时间写博客咯,今晚回去补上,最近在做银行的项目,需要用到自定义键盘,肯定会用到EditText,那么怎么禁止EditText弹出系统键盘呢,为此我也下了番功夫研究了下EditText的源码。下面我们从源码出发实现我们的需求。
我们看看EditText的源码:

/* * Copyright (C) 2006 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *      http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package android.widget;import android.content.Context;import android.os.Bundle;import android.text.Editable;import android.text.Selection;import android.text.Spannable;import android.text.TextUtils;import android.text.method.ArrowKeyMovementMethod;import android.text.method.MovementMethod;import android.util.AttributeSet;import android.view.accessibility.AccessibilityNodeInfo;/* * This is supposed to be a *very* thin veneer over TextView. * Do not make any changes here that do anything that a TextView * with a key listener and a movement method wouldn't do! *//** * EditText is a thin veneer over TextView that configures itself * to be editable. * * <p>See the <a href="{@docRoot}guide/topics/ui/controls/text.html">Text Fields</a> * guide.</p> * <p> * <b>XML attributes</b> * <p> * See {@link android.R.styleable#EditText EditText Attributes}, * {@link android.R.styleable#TextView TextView Attributes}, * {@link android.R.styleable#View View Attributes} */public class EditText extends TextView {    public EditText(Context context) {        this(context, null);    }    public EditText(Context context, AttributeSet attrs) {        this(context, attrs, com.android.internal.R.attr.editTextStyle);    }    public EditText(Context context, AttributeSet attrs, int defStyleAttr) {        this(context, attrs, defStyleAttr, 0);    }    public EditText(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {        super(context, attrs, defStyleAttr, defStyleRes);    }    @Override    protected boolean getDefaultEditable() {        return true;    }    @Override    protected MovementMethod getDefaultMovementMethod() {        return ArrowKeyMovementMethod.getInstance();    }    @Override    public Editable getText() {        return (Editable) super.getText();    }    @Override    public void setText(CharSequence text, BufferType type) {        super.setText(text, BufferType.EDITABLE);    }    /**     * Convenience for {@link Selection#setSelection(Spannable, int, int)}.     */    public void setSelection(int start, int stop) {        Selection.setSelection(getText(), start, stop);    }    /**     * Convenience for {@link Selection#setSelection(Spannable, int)}.     */    public void setSelection(int index) {        Selection.setSelection(getText(), index);    }    /**     * Convenience for {@link Selection#selectAll}.     */    public void selectAll() {        Selection.selectAll(getText());    }    /**     * Convenience for {@link Selection#extendSelection}.     */    public void extendSelection(int index) {        Selection.extendSelection(getText(), index);    }    @Override    public void setEllipsize(TextUtils.TruncateAt ellipsis) {        if (ellipsis == TextUtils.TruncateAt.MARQUEE) {            throw new IllegalArgumentException("EditText cannot use the ellipsize mode "                    + "TextUtils.TruncateAt.MARQUEE");        }        super.setEllipsize(ellipsis);    }    @Override    public CharSequence getAccessibilityClassName() {        return EditText.class.getName();    }    /** @hide */    @Override    public boolean performAccessibilityActionInternal(int action, Bundle arguments) {        switch (action) {            case AccessibilityNodeInfo.ACTION_SET_TEXT: {                CharSequence text = (arguments != null) ? arguments.getCharSequence(                        AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE) : null;                setText(text);                if (text != null && text.length() > 0) {                    setSelection(text.length());                }                return true;            }            default: {                return super.performAccessibilityActionInternal(action, arguments);            }        }    }}

整个EdtiText代码就那么100多行,不得不说EditText的父类TextView写的太牛逼了,不管其他的代码了,重点是实现我们今天的需求,禁止弹系统的键盘。我们看看这个方法:

 /** @hide */    @Override    public boolean performAccessibilityActionInternal(int action, Bundle arguments) {        switch (action) {            case AccessibilityNodeInfo.ACTION_SET_TEXT: {                CharSequence text = (arguments != null) ? arguments.getCharSequence(                        AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE) : null;                setText(text);                if (text != null && text.length() > 0) {                    setSelection(text.length());                }                return true;            }            default: {                return super.performAccessibilityActionInternal(action, arguments);            }        }    }

然后看到super.performAccessibilityActionInternal(action, arguments);这一句点进去,发现我们到了父类TextView里面了

/**     * Performs an accessibility action after it has been offered to the     * delegate.     *     * @hide     */    @Override    public boolean performAccessibilityActionInternal(int action, Bundle arguments) {        if (mEditor != null                && mEditor.mProcessTextIntentActionsHandler.performAccessibilityAction(action)) {            return true;        }        switch (action) {            case AccessibilityNodeInfo.ACTION_CLICK: {                boolean handled = false;                // Simulate View.onTouchEvent for an ACTION_UP event.                if (isClickable() || isLongClickable()) {                    if (isFocusable() && !isFocused()) {                        requestFocus();                    }                    performClick();                    handled = true;                }                // Simulate TextView.onTouchEvent for an ACTION_UP event.                if ((mMovement != null || onCheckIsTextEditor()) && isEnabled()                        && mText instanceof Spannable && mLayout != null                        && (isTextEditable() || isTextSelectable()) && isFocused()) {                    // Show the IME, except when selecting in read-only text.                    final InputMethodManager imm = InputMethodManager.peekInstance();                    viewClicked(imm);                    if (!isTextSelectable() && mEditor.mShowSoftInputOnFocus && imm != null) {                        handled |= imm.showSoftInput(this, 0);                    }                }                return handled;            }            case AccessibilityNodeInfo.ACTION_COPY: {                if (isFocused() && canCopy()) {                    if (onTextContextMenuItem(ID_COPY)) {                        return true;                    }                }            } return false;            case AccessibilityNodeInfo.ACTION_PASTE: {                if (isFocused() && canPaste()) {                    if (onTextContextMenuItem(ID_PASTE)) {                        return true;                    }                }            } return false;            case AccessibilityNodeInfo.ACTION_CUT: {                if (isFocused() && canCut()) {                    if (onTextContextMenuItem(ID_CUT)) {                        return true;                    }                }            } return false;            case AccessibilityNodeInfo.ACTION_SET_SELECTION: {                ensureIterableTextForAccessibilitySelectable();                CharSequence text = getIterableTextForAccessibility();                if (text == null) {                    return false;                }                final int start = (arguments != null) ? arguments.getInt(                        AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;                final int end = (arguments != null) ? arguments.getInt(                        AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;                if ((getSelectionStart() != start || getSelectionEnd() != end)) {                    // No arguments clears the selection.                    if (start == end && end == -1) {                        Selection.removeSelection((Spannable) text);                        return true;                    }                    if (start >= 0 && start <= end && end <= text.length()) {                        Selection.setSelection((Spannable) text, start, end);                        // Make sure selection mode is engaged.                        if (mEditor != null) {                            mEditor.startSelectionActionMode();                        }                        return true;                    }                }            } return false;            case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY:            case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {                ensureIterableTextForAccessibilitySelectable();                return super.performAccessibilityActionInternal(action, arguments);            }            case ACCESSIBILITY_ACTION_SHARE: {                if (isFocused() && canShare()) {                    if (onTextContextMenuItem(ID_SHARE)) {                        return true;                    }                }            } return false;            default: {                return super.performAccessibilityActionInternal(action, arguments);            }        }    }

尼玛,太多了啊,我们看重点

// Simulate TextView.onTouchEvent for an ACTION_UP event.                if ((mMovement != null || onCheckIsTextEditor()) && isEnabled()                        && mText instanceof Spannable && mLayout != null                        && (isTextEditable() || isTextSelectable()) && isFocused()) {                    // Show the IME, except when selecting in read-only text.                    final InputMethodManager imm = InputMethodManager.peekInstance();                    viewClicked(imm);                    if (!isTextSelectable() && mEditor.mShowSoftInputOnFocus && imm != null) {                        handled |= imm.showSoftInput(this, 0);                    }                }

终于看到我们的想要的内容了,当下面这三个条件成立的时候就会默认弹出系统键盘,好的,既然知道思路了,我们就去看看怎么实现,

 if (!isTextSelectable() && mEditor.mShowSoftInputOnFocus && imm != null) {                        handled |= imm.showSoftInput(this, 0);                    }

方案一:mEditor.mShowSoftInputOnFocu这个设为false
方案二:isTextSelectable()设为true

先说下第二种方案:

public boolean isTextSelectable() {        return mEditor == null ? false : mEditor.mTextIsSelectable;    }

我们看到有这么一个方法,我们在布局文件中把我们的EditText的android:textIsSelectable=”true”设为true试试,

  <EditText            android:id=@+id/id_edit1            android:textIsSelectable=true            android:layout_width=match_parent            android:layout_height=50dp />

好吧,运行下代码,然后点击EditText,发现键盘不再弹出了,但貌似不是我们想要的效果啊,感觉怪怪的,
android:textIsSelectable=”true”的意思为文本是否可以复制,如果是true可以复制如果是false不可以复制,稍微查了一下,又把这哥们的东西翻出来了,啊哈哈哈~!!我发现真是受益良多啊,Android TextView支持拷贝&粘帖 textIsSelectable,
好了,是不弹出键盘了,但是光标没啦,很蛋疼啊~!!!
让我们再来研究下第二种方式mEditor.mShowSoftInputOnFocu这个设为false:顺藤摸瓜的让我们又找到了TextView的这个方法,不过默认是隐藏的,说到这里想必大家都知道要干什么了,那就是“反射”~~~!! 多么高大上的词汇啊,哈哈哈

@android.view.RemotableViewMethod    public final void setShowSoftInputOnFocus(boolean show) {        createEditorIfNeeded();

直接上代码了

      public static void disableShowSoftInput(EditText editText)      {        if (android.os.Build.VERSION.SDK_INT <= 10)         {            editText.setInputType(InputType.TYPE_NULL);              }         else {                      Class<EditText> cls = EditText.class;                      Method method;                  try {                       method = cls.getMethod("setShowSoftInputOnFocus",boolean.class);                        method.setAccessible(true);                        method.invoke(editText, false);                    }catch (Exception e) {              // TODO: handle exception            }                  try {                       method = cls.getMethod("setSoftInputShownOnFocus",boolean.class);                        method.setAccessible(true);                        method.invoke(editText, false);                    }catch (Exception e) {              // TODO: handle exception            }            }       }

放到我们的工程中再试试,尼玛~! 居然可以了。。好吧,觉得被自己笑到了,不要喷哈~~!!!! 重点是学习的过程,

0 0
原创粉丝点击