即使 EditText 不可编辑,EditText 光标也可见

2024-04-11

我需要在一个中引入数据EditText但我想使用虚拟键盘,而不是安卓键盘。如果我使用setKeyListener(null)即使使用后光标也是不可见的setCursorVisible(true).

是否有可能制作一个EditText即使它不可编辑,光标在哪里也是可见的?

EDIT 2 :我找到了一个部分方法来做到这一点,但是当我双击 EditText 时它不起作用。

我做了一个setOnClickListner() and an setOnLongClickListner()方法为EditText。在这种方法中,我隐藏了窗口中的软输入,我也使用setTextIsSelectable(false)。我唯一的问题是当我双击EditText软输入键盘显示,我不知道如何隐藏它,我尝试使用android:windowSoftInputMode="stateAlwaysHidden"在清单中,但它也不起作用。

EDIT :

这是我目前用于基本转换器计算器的代码。

public class MainActivity extends AppCompatActivity {

EditText number;
EditText base;
boolean baseB = false;
String numberS = "0";
String baseS = "10";

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


    //make the EditText for number and base not editable
    number = (EditText) findViewById(R.id.number);
    number.setKeyListener(null);
    base = (EditText) findViewById(R.id.base);
    base.setKeyListener(null);

    //... more code here (changing fonts for each EditText and changing status bar color

}

// I have a function for each button all are the same

public void onClickBaseChange(View v) {
    if (baseB) {
        baseB = false;
        // i use toasts at this moment to know when i'm on number or base field
        Toast.makeText(this, "Number", Toast.LENGTH_SHORT).show();
    } else {
        baseB = true;
        Toast.makeText(this, "Base", Toast.LENGTH_SHORT).show();
    }
}

public void onClickB0(View v) {
    if (numberS.length() > 0 && !numberS.equals("0") && !baseB) {
        numberS += "0";
        number = (EditText) findViewById(R.id.number);
        number.setText(numberS, TextView.BufferType.EDITABLE);
        number.setSelection(numberS.length());
    } else {
        if (Integer.valueOf(baseS) >= 1) {
            baseS += "0";
            base = (EditText) findViewById(R.id.base);
            base.setText(baseS, TextView.BufferType.EDITABLE);
        }
    }
}

public void onClickB1(View v) {
    if (numberS.equals("0")) {
        numberS = "1";
    } else {
        numberS += "1";
    }
    number = (EditText) findViewById(R.id.number);
    number.setText(numberS, TextView.BufferType.EDITABLE);
    number.requestFocus();
    number.setSelection(numberS.length());
}

xml 看起来像这样:

<android.widget.RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@color/colorBackground"

tools:context="manastur.calculator.MainActivity">


<EditText
    android:id="@+id/base"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentRight="true"
    android:layout_marginRight="20dp"
    android:layout_marginTop="120dp"
    android:background="@android:color/transparent"
    android:cursorVisible="true"
    android:text=""
    android:textColor="@color/text"
    android:textSize="30dp" />

<EditText
    android:id="@+id/number"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentTop="true"
    android:layout_marginLeft="30dp"
    android:layout_marginTop="50dp"
    android:background="@android:color/transparent"
    android:cursorVisible="true"
    android:text=""
    android:textColor="@color/text"
    android:textSize="50dp" />


<LinearLayout
    android:id="@+id/secondRow"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_above="@+id/firstRow"
    android:layout_centerHorizontal="true">

    <Button
        android:id="@+id/b1"
        android:layout_width="85dp"
        android:layout_height="85dp"
        android:background="@drawable/b1"
        android:onClick="onClickB1" />

    <Button
        android:id="@+id/b2"
        android:layout_width="85dp"
        android:layout_height="85dp"
        android:background="@drawable/b2"
        android:onClick="onClickB2" />

   <!-- from this point on is the same, there are 5 LinearLayouts which
   represents the 5 rows of button of the num pad -->       

使用这段代码来实现这一点,

在开发时我参考了nativeDialpad https://android.googlesource.com/platform/packages/apps/Contacts/+/39948dc7e34dc2041b801058dada28fedb80c388/src/com/android/contacts/dialpad/DialpadFragment.java code

KeypadlessKeypad.java

import android.content.Context;
import android.graphics.Rect;
import android.support.v4.view.MotionEventCompat;
import android.text.InputType;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class KeypadlessKeypad extends EditText {

    private static final Method mShowSoftInputOnFocus = getSetShowSoftInputOnFocusMethod(
            EditText.class, "setShowSoftInputOnFocus", boolean.class);

    public static Method getSetShowSoftInputOnFocusMethod(Class<?> cls, String methodName, Class<?>... parametersType) {
        Class<?> sCls = cls.getSuperclass();
        while (sCls != Object.class) {
            try {
                return sCls.getDeclaredMethod(methodName, parametersType);
            } catch (NoSuchMethodException e) {
                // Just super it again
            }
            sCls = sCls.getSuperclass();
        }
        return null;
    }

    private Context mContext;


    /**
     * Listener for Copy, Cut and Paste event
     * Currently callback only for Paste event is implemented
     */
    private OnEditTextActionListener mOnEditTextActionListener;

    public KeypadlessKeypad(Context context) {
        super(context);
        mContext = context;
        init();
    }

    public KeypadlessKeypad(Context context, AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
        init();
    }

    public KeypadlessKeypad(Context context, AttributeSet attrs,
                            int defStyle) {
        super(context, attrs, defStyle);
        mContext = context;

        init();
    }

    @Override
    protected void onSelectionChanged(int selStart, int selEnd) {
        super.onSelectionChanged(selStart, selEnd);
    }


    public final void appendText(CharSequence text) {
        append(text, 0, text.length());
    }

    /***
     * Initialize all the necessary components of TextView.
     */
    private void init() {

        setSingleLine(true);

        synchronized (this) {
            setInputType(getInputType() | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
            setFocusableInTouchMode(true);
        }

        reflexSetShowSoftInputOnFocus(false); // Workaround.

        // Ensure that cursor is at the end of the input box when initialized. Without this, the
        // cursor may be at index 0 when there is text added via layout XML.
        setSelection(getText().length());
    }

    @Override
    protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
        super.onFocusChanged(focused, direction, previouslyFocusedRect);
        hideKeyboard();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        final boolean ret = super.onTouchEvent(event);
        // Must be done after super.onTouchEvent()
        hideKeyboard();
        return ret;
    }

    private void hideKeyboard() {
        final InputMethodManager imm = ((InputMethodManager) getContext()
                .getSystemService(Context.INPUT_METHOD_SERVICE));
        if (imm != null && imm.isActive(this)) {
            imm.hideSoftInputFromWindow(getApplicationWindowToken(), 0);
        }
    }

    private void reflexSetShowSoftInputOnFocus(boolean show) {
        if (mShowSoftInputOnFocus != null) {
            invokeMethod(mShowSoftInputOnFocus, this, show);
        } else {
            // Use fallback method. Not tested.
            hideKeyboard();
        }
    }

    public static Object invokeMethod(Method method, Object receiver, Object... args) {
        try {
            return method.invoke(receiver, args);
        } catch (IllegalArgumentException e) {
        } catch (IllegalAccessException e) {
        } catch (InvocationTargetException e) {
        }

        return null;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        int textViewWidth = View.MeasureSpec.getSize(widthMeasureSpec);
        int height = getMeasuredHeight();

        this.setMeasuredDimension(textViewWidth, height);
    }

    @Override
    protected void onTextChanged(CharSequence text, int start, int before,
                                 int after) {
        super.onTextChanged(text, start, before, after);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    }

    @Override
    public boolean onTextContextMenuItem(int id) {
        boolean consumed = super.onTextContextMenuItem(id);

        switch (id) {
            case android.R.id.paste:
                if (mOnEditTextActionListener != null) {
                    mOnEditTextActionListener.onPaste();
                }
                break;
        }

        return consumed;
    }


    /**
     * Setter method for {@link #mOnEditTextActionListener}
     *
     * @param onEditTextActionListener
     *         Instance of the {@link OnEditTextActionListener}
     */
    public void setOnEditTextActionListener(OnEditTextActionListener onEditTextActionListener) {
        this.mOnEditTextActionListener = onEditTextActionListener;
    }


    private Rect mRect = new Rect();

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        final int action = MotionEventCompat.getActionMasked(event);

        int[] location = new int[2];
        getLocationOnScreen(location);
        mRect.left = location[0];
        mRect.top = location[1];
        mRect.right = location[0] + getWidth();
        mRect.bottom = location[1] + getHeight();

        int x = (int) event.getX();
        int y = (int) event.getY();

        if (action == MotionEvent.ACTION_DOWN && !mRect.contains(x, y)) {
            InputMethodManager input = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
            input.hideSoftInputFromWindow(getWindowToken(), 0);
        }
        return super.dispatchTouchEvent(event);
    }

    @Override
    public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
        if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED) {
            // Since we're replacing the text every time we add or remove a
            // character, only read the difference. (issue 5337550)
            final int added = event.getAddedCount();
            final int removed = event.getRemovedCount();
            final int length = event.getBeforeText().length();
            if (added > removed) {
                event.setRemovedCount(0);
                event.setAddedCount(1);
                event.setFromIndex(length);
            } else if (removed > added) {
                event.setRemovedCount(1);
                event.setAddedCount(0);
                event.setFromIndex(length - 1);
            } else {
                return;
            }
        } else if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_FOCUSED) {
            // The parent EditText class lets tts read "edit box" when this View has a focus, which
            // confuses users on app launch (issue 5275935).
            return;
        }
        super.sendAccessibilityEventUnchecked(event);
    }

    /**
     * Interface to get callback from the Edittext copy, cut and paste event
     * For time being only the Paste Event callback is generated
     */
    public interface OnEditTextActionListener {

        /**
         * If Edittext get paste event then this method will be called
         */
        void onPaste();
    }

}

在你的 xml 中你可以这样给出,

<[package name].KeypadlessKeypad
        android:id="@+id/dialnumbertv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#00000000"
        android:cursorVisible="false"
        android:ellipsize="start"
        android:gravity="center"
        android:inputType="phone"
        android:singleLine="true"
        android:textIsSelectable="true"
        android:textSize="30sp"
        android:textStyle="italic"
        android:visibility="visible"/>

在你的片段中你可以这样实现,

   public void onViewCreated(final View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        mDialNumbertv = view.findViewById(R.id.dialnumbertv);

        mDialNumbertv.setCursorVisible(false);

        mDialNumbertv.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (!isDigitsEmpty()) {
                    mDialNumbertv.setCursorVisible(true);
                }
            }
        });

        mDialNumbertv.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

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

            }

            @Override
            public void afterTextChanged(Editable s) {
                if (isDigitsEmpty()) {
                    mDialNumbertv.setCursorVisible(false);
                }
//                updateDeleteButton();
            }
        });

        mDialNumbertv.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                // Ref https://android.googlesource.com/platform/packages/apps/Contacts/+/39948dc7e34dc2041b801058dada28fedb80c388/src/com/android/contacts/dialpad/DialpadFragment.java
                // Right now EditText does not show the "paste" option when cursor is not visible.
                // To show that, make the cursor visible, and return false, letting the EditText
                // show the option by itself.
                mDialNumbertv.setCursorVisible(true);
                return false;
            }
        });

        mDialNumbertv.setOnEditTextActionListener(
                new KeypadlessKeypad.OnEditTextActionListener() {
                    @Override
                    public void onPaste() {
                        // If some content pasted on mDialNumbertv
                        // we need to run some search on Contact and Price

                        String mobileNumber = mDialNumbertv.getText().toString();

                        if (TextUtils.isEmpty(mobileNumber)) {
                            return;
                        }

//                        updateContactName(mobileNumber);
                    }
                });

    }

    private KeypadlessKeypad mDialNumbertv;

    private boolean isDigitsEmpty() {
        return mDialNumbertv.length() == 0;
    }

    private void setClickedDigit(final String digitToSet) {
        if (!TextUtils.isEmpty(digitToSet)) {

            char digit = digitToSet.charAt(0);

            String mobileNumber = mDialNumbertv.getText() + digitToSet;
            mDialNumbertv.getText().insert(mDialNumbertv.getSelectionStart(), digitToSet);

            // If the cursor is at the end of the text we hide it.
            final int length = mDialNumbertv.length();
            if (length == mDialNumbertv.getSelectionStart() && length == mDialNumbertv.getSelectionEnd()) {
                mDialNumbertv.setCursorVisible(false);
            }
        }
    }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

即使 EditText 不可编辑,EditText 光标也可见 的相关文章

随机推荐

  • Lion + Xcode 3.2.3 启动问题

    我刚刚从图书馆得到一本基于 Xcode 3 x 的 iPhone 编程书籍 所以我想从它开始 幸运的是 我从 SnowLeopard 更新到 Lion 时已经安装了 Xcode 因此安装或运行它时没有遇到任何问题 因此 我通读了 Hello
  • RecyclerView 中检测到不一致,如何在滚动时更改 RecyclerView 的内容

    我在用着RecyclerView显示项目的名称 我的行包含单个TextView 项目名称存储在List
  • 列表视图项目内的 UWP 按钮

    I m working on my first UWP app and I want create a UI like this For each list item project there ll be a set of buttons
  • jQuery/Javascript - 使用附加的查询字符串重新加载当前页面?

    我的表单上有一个下拉菜单 当选择某些内容时 我需要重新加载当前页面 但带有附加的查询字符串 我该怎么做呢 这是一个老问题 但它首先出现在谷歌搜索结果中 我采用的解决方案与 jAndy 的类似 window location pathname
  • XCode 库搜索路径

    对于我的 iOS 项目 我有一个特定的文件夹结构 root src xcode MyProject
  • 提取两个给定字符串之间的文本

    希望有人可以帮助我 现在已经遍布谷歌了 我正在对文档进行一些区域 ocr 并且想使用正则表达式提取一些文本 总是这样 直到 姓名 姓名 org nr 12323123 我想提取名称部分 它可以是 1 4 个名称 但 Til 和 org nr
  • 大数组的堆栈溢出,但同样大的向量的堆栈溢出?

    今天我在处理大型数据结构时遇到了一个有趣的问题 我最初使用向量来存储超过 1000000 个整数 但后来决定我实际上并不需要向量的动态功能 无论如何 我在声明后就保留了 1000000 个位置 相反 这将是有益的 能够在数据结构中的任何位置
  • 如何禁用 PHP 中的线程安全?

    我正在使用一些需要禁用线程安全的软件 我正在 Windows 服务器上工作 根据我在其他地方读到的内容 我不能只在 ini 文件中配置它 这是真的 如果是这样 我将如何编译它以关闭线程安全 您必须在禁用 ZTS 的情况下编译 PHP 编译标
  • MATLAB 中的 .m 和 .mat 文件有什么区别

    当我跟踪我的参考 MATLAB 脚本时 我发现了带有以下内容的文件 mat扩大 我的问题是 有什么区别 mat and m files 如何使用打开文件 mat扩大 扩展名为 m 的文件包含 MATLAB 代码 其形式为script htt
  • 移动设备上的 jQuery 实时滚动事件(解决方法)

    老问题 当用户在移动网站或应用程序 Web 视图 上滚动元素时触发滚动事件 我所寻找的只是访问正确的scrollTop 当用户在移动设备上滚动我的页面时获取该值 而不是在用户停止时获取它 我确信在某个地方有一个解决方法 如果我是正确的话 这
  • iOS:从背景图像中检索矩形图像

    我正在开发一个实现 其中我在大背景图像中有一个矩形图像 我正在尝试以编程方式从大图像中检索矩形图像 并从该特定矩形图像中检索文本信息 我正在尝试使用 Open CV 第三方框架 但无法从大背景图像中检索矩形图像 有人可以指导我 我怎样才能实
  • 如何使用 JSZip 使用 Node.js 中的缓冲区内容生成 zip 文件?

    我有一个字符串数组 应将其写入 txt 文件 另外 我需要使用 JSZip 将生成的 txt 文件压缩为 zip 格式 在客户端 我能够使用该字符串数组生成 文本 纯文本 Blob 然后使用 JSZip 将此 Blob 压缩为 zip 格式
  • .NET 6 混淆

    我试图使用 生成单个文件 选项来混淆编译 NET 6 项目后获得的 exe 文件 问题是没有混淆器对其起作用 我想知道是否有人知道为什么 预先感谢您的回答 您必须混淆位于 obj Release net6 0 windows win x64
  • 为分组依据字段创建索引?

    Oracle数据库中需要为group by字段创建索引吗 例如 select from some table where field one is not null and field two group by field three fi
  • 编码 NSAttributedString 会引发错误

    根据已接受的答案这个问题 https stackoverflow com questions 2626667 saving custom attributes in nsattributedstring 我写了以下代码 NSData som
  • Angular 2 中的访问控制允许来源问题

    我在从 Node js 服务器获取数据时遇到问题 客户端是 public getTestLines Observable
  • “变量”变量名c++

    问题 我在这里搜索了一段时间 寻找一种循环遍历名为有点像的变量的方法variable 1 variable 2 variable n 基本上 我问是否有一种方法可以使用循环来实现variable i或者 更具体地说 就我而言 functio
  • 如何使ODP.NET 4.0(64位)在64位机Windows 7上运行?

    我已经使用 Oracle 提供的 XCopy 11 2 安装了 64 位计算机的 Oracle 客户端 按照自述说明安装了所有内容 我正在使用 Visual Studio 2010 该项目的类型为 ASP NET 网站 当我尝试使用上面安装
  • app.module.ts 中的environment.product变量始终为true

    我试图在我的 app module 文件中设置一个配置设置 以便它根据我是否在生产中而有所不同 My environment ts文件有 export const environment production false My enviro
  • 即使 EditText 不可编辑,EditText 光标也可见

    我需要在一个中引入数据EditText但我想使用虚拟键盘 而不是安卓键盘 如果我使用setKeyListener null 即使使用后光标也是不可见的setCursorVisible true 是否有可能制作一个EditText即使它不可编