java - TextView 可在长按时编辑 - 但按下“后退”按钮时会出现一个小问题

标签 java android

我已经搜索了好几天了,终于编译了足够的答案来完成我想要的。首先,这似乎是一个经常被问到的问题,但没有得到真正的回答(至少不是我寻找的方式)。我想我会分享我的发现,但我还有一个小问题需要寻求帮助。这里是:

我有一个显示分数的 TextView。它从 0 开始,在 onClick 事件中分数递增并更新 TextView(分数以字节形式跟踪 - valScore)。

onLongClick:这就是挑战。我希望用户能够通过长按来纠正/更改分数。我首先找到了一个解决方案,该解决方案利用另一个layout.xml 文件,其中仅包含一个EditText 元素以及“确定”和“取消”按钮。更改乐谱非常麻烦,因为它涉及长按,然后对话框打开,然后您必须单击 EditText 元素以打开键盘,然后输入值,单击“完成”,然后单击“确定”。我通过弄清楚如何在对话框打开时自动打开软件键盘来缩短它。但是,您仍然必须单击“完成”,然后单击“确定”。我不喜欢这个 Action ,所以我继续搜索。

几天后,我想出了一些代码,然后又写了更多代码,经过大量的尝试/黑客攻击,我想出了以下解决方案:

    // set the onLongClickListener for tvScoreHome
    tvScoreHome.setOnLongClickListener(new View.OnLongClickListener() {
        @Override
        public boolean onLongClick(View v) {
            tvScoreHome.setInputType( InputType.TYPE_CLASS_NUMBER );
            tvScoreHome.setFocusable(true);
            tvScoreHome.setFocusableInTouchMode( true );
            tvScoreHome.requestFocus();

            InputMethodManager imm = (InputMethodManager) context.getSystemService(Service.INPUT_METHOD_SERVICE);
            imm.showSoftInput(tvScoreHome, InputMethodManager.SHOW_FORCED);

            tvScoreHome.setText("");

            tvScoreHome.setOnEditorActionListener( new TextView.OnEditorActionListener() {

                @Override
                public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
                    if (actionId == EditorInfo.IME_ACTION_DONE) {
                        valScoreHome = Byte.valueOf( tvScoreHome.getText().toString() );

                        // This part will hide the keyboard after input
                        InputMethodManager imm = (InputMethodManager) context.getSystemService(Service.INPUT_METHOD_SERVICE);
                        imm.hideSoftInputFromWindow(v.getWindowToken(), 0);

                        tvScoreHome.setFocusable( false );
                        tvScoreHome.setFocusableInTouchMode( false );
                        tvScoreHome.setText( Byte.toString(valScoreHome) );

                        return true;
                    }

                    return false;
                }

            });

            return true;
        }
    });

这正是我想要的。用户执行长按键盘打开,用户输入新值并单击“完成”。 TextView 已更新并且效果很好!

如果用户改变主意并点击设备上的“返回”按钮,就会出现问题。键盘关闭(良好),但焦点仍保留在 TextView 上,而不是像按下“完成”按钮时那样移除焦点。因此,如果您取消更改,则每次单击都会导致键盘再次打开,而不仅仅是增加分数 - 直到您实际在键盘中输入一个值并单击“完成”(然后常规行为再次接管。我需要如果按下“后退”按钮,则将FocusableInTouchMode 设置为FALSE。

另一个问题是,如果输入了不同的值,即使按下“后退”按钮,也会执行 setText() 方法。即使 valScoreHome 未更新,TextView 也会发生变化。在下一个增量中,它会再次转到正确的数字,但如果按下“后退”按钮,则 setText() 不应执行。

有人可以帮我解决这个问题吗?

最佳答案

这两个问题都可以通过子类化 TextView 来解决。

按下后退按钮关闭键盘是通过重写onKeyPreIme来处理的。

为了避免在用户关闭键盘时更新文本,分数值将保存在变量 mScore 中,但前提是 TextView 当前不可聚焦。这意味着,TextView 会“记住”当前的分数值,而不是用户输入的分数。当用户关闭键盘时,文本将设置回保存的值。

public class ScoreTextView extends TextView {
    private CharSequence mScore;

    public ScoreTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public void setText(CharSequence text, BufferType type) {
        if (!isFocusable()) {
            mScore = text;
        }
        super.setText(text, type);
    }

    @Override
    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
        if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
            setFocusable(false);
            setFocusableInTouchMode(false);
            setText(mScore);
        }
        return super.onKeyPreIme(keyCode, event);
    }
}

关于java - TextView 可在长按时编辑 - 但按下“后退”按钮时会出现一个小问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14073154/

相关文章:

java - 使用 includeFrom 属性关联 SmartGwt 数据源的问题

android - 在 Android 中手动重绘 ActionBar

java - 深入比较数组中的每个元素

java - ConcurrentBitSet 中的竞争条件

android - 有安卓的照片处理库吗?

android - 维护 Android 应用程序发布的最佳实践

android - 为什么不希望将时区偏移量添加到时间(03 :00 to 08:00)

android - 自动上传安卓应用

java - Gson - 序列化时避免不必要的包装类

java - 如何启动 WildFly8 服务器(在 OpenShift 中)