2

我在 EditText 框上有一个 TextWatcher。当用户键入时,我将 EditText 框上的任何内容设置为按钮标签。

EditText et = rootView.findViewById(R.id.userInput);
et.addTextChangedListener(this);
...

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

@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
    Button btn = (Button) rootView.findViewById(R.id.myButton);
    btn.setText(s.toString());
    //btn.setText("\u00A9");
}

但我不知道如何编写unicode 符号。注释行在未注释时将Button文本设置为版权符号 © 。尽管在 EditText 框中输入相同的 unicode 代码不起作用。我尝试在 EditText 中输入双反斜杠,仍然不好。

注意:与此无关,btn.setText(s)不使用该toString()部分时,按钮中的文本带有下划线。

澄清 由于一些评论和答案(现已删除),我意识到我并不清楚。让我改写一下:

我不想以任何方式干扰用户输入文本。现在,当用户在 EditText 中输入“Hello \u0089”时,我使用以下行将其复制到 Button 文本中:

btn.setText(s.toString());

它显示为"Hello \u0089"。我期待“你好‰”。为什么?因为如果我运行一个小测试并使用这一行:

btn.setText("Hello \u0089");

它显示为"Hello ‰"。那么,使 unicode 在直接方法中正确显示但在通过 EditText 输入时不显示的区别是什么?

4

1 回答 1

6

那么,使 unicode 在直接方法中正确显示但在通过 EditText 输入时不显示的区别是什么?

Arggh,我希望人们不要再说“unicode”。它是“文本”,而不是“unicode”。Unicode 是一种标准。用户输入的文本不是一个标准,它只是文本。

顺便说一句,让我们看看我是否可以解释其中的区别。

当您像"Hello \u0089"在 Java 中那样编写字符串文字时,您的源代码文件将包含以下字符序列:

  1. a U+0022 ǫᴜᴏᴛᴀᴛɪᴏɴ ᴍᴀʀᴋ</a>;
  2. 一个U+0048 ʟᴀᴛɪɴ ᴄᴀᴘɪᴛᴀʟ ʟᴇᴛᴛᴇʀ ʜ ;
  3. a U+0065 ʟᴀᴛɪɴ sᴍᴀʟʟ ʟᴇᴛᴛᴇʀ ᴇ</a>;
  4. a U+006C ʟᴀᴛɪɴ sᴍᴀʟʟ ʟᴇᴛᴛᴇʀ ʟ ;
  5. a U+006C ʟᴀᴛɪɴ sᴍᴀʟʟ ʟᴇᴛᴛᴇʀ ʟ ;
  6. a U+006F ʟᴀᴛɪɴ sᴍᴀʟʟ ʟᴇᴛᴛᴇʀ ᴏ</a>;
  7. 一个U+0020 sᴘᴀᴄᴇ ;
  8. a U+005C ʀᴇᴠᴇʀsᴇ sᴏʟɪᴅᴜs(也称为反斜杠);
  9. a U+0075 ʟᴀᴛɪɴ sᴍᴀʟʟ ʟᴇᴛᴛᴇʀ ᴜ</a>;
  10. a U+0030 ᴅɪɢɪᴛ ᴢᴇʀᴏ</a>;
  11. a U+0030 ᴅɪɢɪᴛ ᴢᴇʀᴏ</a>;
  12. a U+0038 ᴅɪɢɪᴛ ᴇɪɢʜᴛ ;
  13. a U+0039 ᴅɪɢɪᴛ ɴɪɴᴇ</a>; 和
  14. a U+0022 ǫᴜᴏᴛᴀᴛɪᴏɴ ᴍᴀʀᴋ</a>。

这里没有魔法。你输入的就是你得到的。\u0089顺序并不神奇。

但是,当您将相同的源文件提供给 Java 编译器时,Java 编译器与您(程序员)达成了一项协议:它将转换它在字符串文字中找到的任何序列,该字符串文字以字符 U+005C U+0075 开头并且是后跟四个十六进制数字字符到与这些十六进制数字指定的 Unicode 值相对应的字符中。该协议还包括一项规定,当您(程序员)想要实际表示带有反斜杠、u 和十六进制数字(即六个字符,而不是一个)的序列时。为此,您在反斜杠之前加上另一个反斜杠,Java 编译器除了删除这两个反斜杠之一之外不执行任何其他转换。

因此,虽然源文件的字符串文字在引号之间有 12 个字符,但 Java 编译器将按照 Java 规范中与程序员达成的协议,将其转换为只有 7 个字符的字符串。

  1. 一个U+0048 ʟᴀᴛɪɴ ᴄᴀᴘɪᴛᴀʟ ʟᴇᴛᴛᴇʀ ʜ ;
  2. a U+0065 ʟᴀᴛɪɴ sᴍᴀʟʟ ʟᴇᴛᴛᴇʀ ᴇ</a>;
  3. a U+006C ʟᴀᴛɪɴ sᴍᴀʟʟ ʟᴇᴛᴛᴇʀ ʟ ;
  4. a U+006C ʟᴀᴛɪɴ sᴍᴀʟʟ ʟᴇᴛᴛᴇʀ ʟ ;
  5. a U+006F ʟᴀᴛɪɴ sᴍᴀʟʟ ʟᴇᴛᴛᴇʀ ᴏ</a>;
  6. 一个U+0020 sᴘᴀᴄᴇ ;
  7. a U+0089 ᴄʜᴀʀᴀᴄᴛᴇʀ ᴛᴀʙᴜʟᴀᴛɪᴏɴ ᴡɪᴛʜ ᴊᴜsᴛɪғɪᴄᴀᴛɪᴏɴ ;

现在,当用户在某些 UI 中输入文本时,他们输入的不是 Java 字符串文字,这些文字稍后将由 Java 编译器处理,或者是吗?

他们不是。当用户键入反斜杠后跟 au 和一些数字时,用户会得到一个反斜杠,后跟 au 和一些数字。当用户\u0089在文本字段中输入时,该文本字段包含一个包含六个字符的字符串,而不是一个字符。那里没有 Java 编译器,没有任何预先约定的约定来用它们的 Unicode 值来表示字符;它只是一个用户输入文本,而不是 Java 代码。

当用户\u0089在文本字段中输入时,文本字段包含一个字符串,该字符串可以在 Java 源代码中表示为"\\u0089",而不是"\u0089"

如果您想为此类用户输入赋予 Java 编译器赋予那些 Unicode 转义序列相同的含义,则需要在显示之前调用执行此类转换的代码。

为了完整性 这是我根据上面的答案编写的 OP 发布代码。

public static String convertUnicode(CharSequence s) {
    StringBuffer result = new StringBuffer();
    Matcher m = Pattern.compile("\\\\u([0-9a-zA-Z]{4,4})\\b").matcher(s);
    while ( m.find() ) {
        char c = (char) Integer.parseInt(m.group(1), 16);
        m.appendReplacement(result, String.valueOf(c) );
    }
    m.appendTail(result);
    return result.toString();
}
于 2013-06-17T10:57:49.330 回答