安卓:用户完成编辑后评估EditText

6

我想要的 我有一个EditText,用户可以在其中输入值,例如10.40。一旦用户完成编辑,我会将他的输入格式化为货币,例如上述值将被格式化为$10.40(在Locale.US的情况下)。我将结果显示在用户之前编辑过的同一EditText中。

问题 因为我将要格式化(即修改)他的输入,所以我需要知道他什么时候完成了输入(这样我的格式化不会干扰他正在进行的输入)。

我尝试过的 TextWatcher不是一个选项,因为它在每次编辑时都会触发,因此当用户输入一个、零、四、点和零(=10.40)时会触发多次。我目前正在使用OnFocusChangeListener,它起到了期望的作用,但问题是:我在应用程序中有按钮,如果用户在编辑EditText后点击按钮,EditText不会失去焦点,因此我的格式化代码永远不会被调用……

在这之后,我尝试了一些关于按钮焦点的操作,将其设置为FocusableInTouchMode——这会导致必须两次点击按钮才能触发(这是不可行的),因为它在第一次获得焦点并在第二次激活。经过这么多的hack,我想知道是否有人有解决这个困境的想法。

一些代码

我向我的EditText添加了以下OnFocusChangeListener,其功能如上所述。EditText被封装在CurrencyTextbox中(这并不是很重要):

@Override
protected OnFocusChangeListener getOnFocusChangeListener() {
    return new OnFocusChangeListener() {
        @Override
        public void onFocusChange(View v, boolean hasFocus) {
            if (hasFocus) {
                //Member variable in the class which contains an EditText
                CurrencyTextbox.this.hadFocus = true;
            } else {
                // Thes EditText has lost focus
                Log.v(TAG, "Lost focus.");
                if (CurrencyTextbox.this.hadFocus) {
                    // We previously had focus, now we lost it, format the user input!
                    // Get current value of the Textbox
                    String value = CurrencyTextbox.this.textbox.getText().toString();
                    // Formatting the user input
                    value = String.format(//Doing some formatting);
                    // Reset the had focus
                    CurrencyTextbox.this.hadFocus = false;
                }
            }
        }
    };
}

然而问题是,上面的OnFocusChangeListener只有在我的EditText失去焦点时才会被调用,但是当我在Activity中点击按钮时,它并不会失去焦点。正如上面所述,将Button的isFocusableInTouchMode设置为true并不可行,因为这样需要每次点击两次才能触发。


展示相关的代码总是有帮助的。 - vdbuilder
我不确定它是否有用 - 问题实际上非常普遍,我理解这是一个普遍的问题(我期望得到一般性的答案/方法描述,而不是详细的代码片段)。我可以发布一些代码,但我担心它可能无法更好地理解所描述的问题。 - AgentKnopf
另外:我没有失败的代码,这真的不是代码问题。只是,当你在Android上点击一个按钮时,该按钮不会获得焦点(就是这样),因此之前获得焦点的任何其他小部件都不会失去焦点(因为按钮没有获得焦点)。 - AgentKnopf
4个回答

10

我做了一些研究,其中我发现这个线程。它详细说明了你遇到的类似问题(按钮没有获得焦点)。请尝试以下操作:在你的按钮上,设置setFocusable(true)(不要使用setFocusableInTouchMode!因为这会产生你在原始帖子中提到的讨厌行为),然后在你的按钮上设置以下OnClickListener:

    return new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO workaround because of android issue nr. 2705
            button.requestFocusFromTouch();
            // Do some stuff to handle OnClick
        }
    };

但他们可能只需要修复按钮的焦点问题,当前的行为确实会引起一些问题(比如您遇到的问题)。


我尝试了一下,它可以工作:D!谢谢你,正是我在寻找的东西! - AgentKnopf
另外补充一点:即使没有强制设置Button的setFocusable(true),它也可以正常工作。 - AgentKnopf
它对我也起作用了,但我想知道为什么editText视图如此复杂。 - Muhammad Irfan

0
尝试同时使用View.setFocusableInTouchMode()View.requestFocus()。您可以使用onKeyListener()接口来检测用户输入,并在每个onKey事件后启动计时器以在合理的延迟后开始编辑。

我应该在我的EditText上使用requestFocus吗?问题是我在我的活动中有许多小部件。计时器的想法很有创意,但可能是错误的;)。用户可能会输入edittext并快速进入下一个活动,所以如果我的计时器太慢,它不会及时触发,如果我的计时器太快,问题仍然存在。 - AgentKnopf
你必须为你想要触发 onKey 事件的 View 请求焦点(这可能是你上面提到需要点击两次的原因)。现在,你不需要停止 UI 线程来运行它。你可以在一个单独的线程中运行计时器,在用户输入新的线程时后台运行(尽管你需要注意垃圾回收和如果用户过于迅速则创建大量线程的问题)。 - Mohamed_AbdAllah
我应该补充说明一下,这是一个框架 - 因此您建议的并不容易实现,因为活动不知道它们的视图 - 一切都非常通用,因此我需要以更一般的方式解决此问题。至于计时器:我不担心UI线程,问题在于:一旦用户快速点击按钮以移动到下一个活动,我们需要将所有字段数据保存到数据库中,因此完整数据集需要在活动离开时可用,相信我,在这种情况下计时器不起作用,谢谢 :) - AgentKnopf

0

您遇到了什么问题?需要在您的editfield中包含setOnFocusChangeListener。请检查一下,并且必须重写onFocusChange

请检查一下...

这里输入链接描述


感谢您的回答。我在我的问题中解释了建议实现方式存在的问题。我不能简单地覆盖按钮的onFocusChange并触发button.performClick(),因为这会在每次按钮获得焦点时都触发,这会引起各种问题 - 如果这是您想表达的意思的话。至于EditText:我已经设置了onFocusChangeListener。如果有可用的侦听器,您不必覆盖onFocusChange - 除非我没有理解您的想法。 - AgentKnopf

0

是的,编辑文本框一旦获得焦点就无法失去焦点,这确实存在问题。经过一番搜索,我发现只有通过解决方法才能实现所需的结果。
我有一个类似的要求,我制定了一个解决方案来完成上述任务,并且对我非常有效。
解决方法如下:
为editText设置onClickListener,在onClick事件中设置一个标志,表示已单击editText。
为editText设置onKeyListener,在onKey事件中获取editText的当前值。
现在,假设您在活动/对话框中单击了“完成”/“返回”按钮。在这里,您可以检查单击editText时设置的标志。因此,如果为true,则进行任何所需的过程调用。

EditText v = (EditText) layout.findViewById(R.id.framerate);
v.setOnClickListener(new OnClickListener() {
    public void onClick(View v) {
        Log.d(ExploreUIActivity.TAG, "Insided onClick");
        vClicked= true;
    }
});
v.setOnKeyListener(new OnKeyListener() {
    public boolean onKey(View v, int keyCode, KeyEvent event) {
        Log.d(ExploreUIActivity.TAG, "Inside onKeyListener");
        value = ((EditText) v).getText().toString();
        return false;
    }
});

现在针对返回/完成按钮设置onClick监听器,并检查标志是否已设置。
back.setOnClickListener(new OnClickListener() {
    public onClick(View v) {
        //check the flag
        //if set do some stuff
    });

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接