【问题标题】:Do not concatenate text displayed with setText issue + App crashing when other language than default lang is used不要连接使用 setText 问题显示的文本 + 使用默认语言以外的其他语言时应用程序崩溃
【发布时间】:2016-08-22 14:48:20
【问题描述】:

我在 strings.xml 中定义了字符串(以及其他语言的相应文件)。

当应用程序执行这一行时(不仅仅是这一行,其他人喜欢这一行): timeTextView.setText(substr2 + " " + getString(R.string.shours) + " " + minutereal + " " + getString(R.string.sminutes));

在默认(英文)语言中,屏幕上的结果还可以!但是,如果我更改手机上的语言并尝试使用该应用程序,一切正常,直到我单击按钮(应显示结果时),然后应用程序崩溃。

我在stackoverflow上进行了搜索(不仅如此),但我不知道如何解决问题。

在 values\strings.xml 中定义的字符串:

<string name="shours">hour(s),</string>
<string name="sminutes">minute(s)</string>

我试过了:

timeTextView.setText(getString(substr2, R.string.shours, minutereal, R.string.sminutes));

但这一个根本不起作用。

这个:

timeTextView.setText(substr2 + " stunde(n), " + minutereal + "  minute(n)");

与第一个选项一样有效,但结果相同,适用于默认语言,并且作为第一个选项,我收到相同的警告:不要连接 setText 问题显示的文本。

来自崩溃的日志:

08-21 16:21:02.834 23866-23866/com.example.android.test_app E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.android.test_app, PID: 23866
java.lang.StringIndexOutOfBoundsException: length=4; regionStart=0; regionLength=-1
at java.lang.String.startEndAndLength(String.java:504)
at java.lang.String.substring(String.java:1333)
at com.example.android.test_app.MainActivity.displayTimeReal(MainActivity.java:91)
at com.example.android.test_app.MainActivity.access$200(MainActivity.java:12)
at com.example.android.test_app.MainActivity$1.onClick(MainActivity.java:31)
at android.view.View.performClick(View.java)
at android.view.View$PerformClick.run(View.java)
at android.os.Handler.handleCallback(Handler.java)
at android.os.Handler.dispatchMessage(Handler.java)
at android.os.Looper.loop(Looper.java)
at android.app.ActivityThread.main(ActivityThread.java)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java)

所以,正如我之前所说,我已经在寻找答案,并不是我懒惰或什么,而是我不明白......(可能是愚蠢的:P)。

这是插入数据并按下按钮后应该在屏幕上显示的值之一的完整脚本:

private void displayTimeReal(double timpreal) {
    DecimalFormat formattr = new DecimalFormat();
    formattr.setMaximumFractionDigits(2);
    String formattedTimpR = formattr.format(timpreal);
    String substr1 = formattedTimpR.substring(formattedTimpR.indexOf(".") + 1); //decimals
    String substr2 = formattedTimpR.substring(0, formattedTimpR.indexOf(".")); //unit
    double minutereal = Double.parseDouble(substr1);
    minutereal = minutereal * 0.6;
    TextView timeTextView = (TextView) findViewById(R.id.rezultat_ore_real);
    timeTextView.setText(substr2 + " " + getString(R.string.shours) + " " + minutereal + " " + getString(R.string.sminutes));
    //timeTextView.setText(getString(substr2, R.string.shours, minutereal, R.string.sminutes));

任何帮助将不胜感激!!!

感谢您的宝贵时间和您永无止境(希望 :P)的耐心和支持!

附:神奇的按钮:

<Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="20dp"
        android:id="@+id/butto"
        android:onClick="onClick"
        android:text="@string/sbutton"
        android:textColor="#0277BD"
        android:textStyle="bold" />

以及要显示的全部内容:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    findViewById(R.id.butto)
            .setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    displayTarget((procente / Double.parseDouble(((EditText) findViewById(R.id.vZeit))
                            .getText().toString())) * mitarbeiter);
                    displayTime((Double.parseDouble(((EditText) findViewById(R.id.aufGesSt))
                            .getText().toString())) / (procente / Double.parseDouble(((EditText) findViewById(R.id.vZeit))
                            .getText().toString()) * mitarbeiter));
                    displayTimeReal((Double.parseDouble(((EditText) findViewById(R.id.aufGesSt))
                            .getText().toString())) / (procente / Double.parseDouble(((EditText) findViewById(R.id.vZeit))
                            .getText().toString()) * mitarbeiter));

                }
            });
}

【问题讨论】:

  • 第 91 行是什么?
  • 第 91 行:字符串 substr2 = formattedTimpR.substring(0, formattedTimpR.indexOf(".")); //单位
  • 第 12 行:公共类 MainActivity 扩展 AppCompatActivity {
  • 第 31 行:displayTimeReal((Double.parseDouble(((EditText) findViewById(R.id.aufGesSt)))
  • 字符串中没有.。这就是它抛出 IndexOutOfBound 异常的原因。

标签: java android xml string concatenation


【解决方案1】:

问题的第二部分(使用默认语言以外的其他语言时应用程序崩溃)的答案在这里得到了解决:

Android app crashes if installed as apk, works if runned trough Android Studio

答案,由用户 samgak 提供:

这个问题似乎是由于数字的格式因设备的区域设置而异。

当您使用 DecimalFormat 对象时,小数分隔符会因设备的语言设置而异。例如在英语中它是一个点,例如3.14159 但在德语中它是一个逗号,例如3,14159。

这会导致问题,因为当您调用 indexOf() 时,您的代码总是在寻找点。

您可以通过多种方式解决此问题。一种方法是在创建 DecimalFormat 对象时指定语言环境,例如:

NumberFormat nf = NumberFormat.getNumberInstance(Locale.ENGLISH);
DecimalFormat formattr = (DecimalFormat)nf;

或者你可以设置小数点分隔符:

DecimalFormat formattr = new DecimalFormat(); formattr.setDecimalSeparator('.'); 但是,也许您希望它为德国用户以不同的方式显示。在这种情况下,您可以更改检查点的代码以检查正确的字符:

String zecimaleTimpReal = formattedTimpR.substring(formattedTimpR.indexOf("" + formattr.getDecimalFormatSymbols().getDecimalSeparator()) + 1);

添加到空字符串只是将字符转换为字符串的技巧。

请注意,还有一个“分组符号”,它也可以是逗号或点,例如123,456.78。您可能想要禁用分组,如下所示:

formattr.setGroupingUsed(false);

@samgak - 再次感谢您!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-07-31
    • 2010-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-22
    相关资源
    最近更新 更多