Android/Java — как выводить несколько переменных в строке?

226
28 июля 2018, 01:20

Делаю простое приложение по заказу кофе, основываясь на одном курсе из Udacity, только добавляя свои фишки, ибо они оставляют много "дыр".

В общем, пользователь там накликивал нужное количество чашек кофе, добавлял сливки и/или шоколад по желанию, и жал кнопку "заказать".

В зависимости от того, что он там накликивал, в файле strings.xml хранились строки типа:

<string name="total_coffee_cost">Hi, %1$s. You ordered %2$d cups of coffee. \nPrepare to pay $%3$d. \nThank you!</string>
<string name="total_coffee_cost_whipped_cream">Hi, %1$s. You ordered %2$d cups of coffee, whipped cream will be added. \nPrepare to pay $%3$d. \nThank you!</string>
<string name="total_coffee_cost_chocolate">Hi, %1$s. You ordered %2$d cups of coffee, chocolate will be added. \nPrepare to pay $%3$d. \nThank you!</string>
<string name="total_coffee_cost_cream_chocolate">Hi, %1$s. You ordered %2$d cups of coffee, whipped cream and chocolate will be added. \nPrepare to pay $%3$d. \nThank you!</string>
<string name="total_coffee_cost_one">Hi, %1$s. You ordered %2$d cup of coffee. \nPrepare to pay $%3$d. \nThank you!</string>
<string name="total_coffee_cost_one_whipped_cream">Hi, %1$s. You ordered %2$d cup of coffee, whipped cream will be added. \nPrepare to pay $%3$d. \nThank you!</string>
<string name="total_coffee_cost_one_chocolate">Hi, %1$s. You ordered %2$d cup of coffee, chocolate will be added. \nPrepare to pay $%3$d. \nThank you!</string>
<string name="total_coffee_cost_one_cream_chocolate">Hi, %1$s. You ordered %2$d cup of coffee, whipped cream and chocolate will be added. \nPrepare to pay $%3$d. \nThank you!</string>
<string name="total_coffee_cost_zero">Hi, %1$s. You have not ordered any cup of coffee. \nTry to choose again. \nThank you!</string>

Выводилось в MainActivity.java все это через setText(), в зависимости от количества выбранного кофе с топпингами (там девять веток if-else, привожу две, чтобы не засорять):

private TextView createOrderSummary(View view){
    EditText nameField = findViewById(R.id.name_field);
    String name = nameField.getText().toString();
    CheckBox whippedCreamCheckBox = findViewById(R.id.whipped_cream_checkbox);
    hasWhippedCream = whippedCreamCheckBox.isChecked();
    CheckBox chocolateCheckBox = findViewById(R.id.chocolate_checkbox);
    hasChocolate = chocolateCheckBox.isChecked();
    TextView priceMessage = findViewById(R.id.price_text_view);
    if (numberOfCoffees == 0)
        priceMessage.setText(getString(R.string.total_coffee_cost_zero, name));
    else if ((numberOfCoffees == 1) && (!hasWhippedCream) && (!hasChocolate))
        priceMessage.setText(getString(R.string.total_coffee_cost_one,name, numberOfCoffees, numberOfCoffees * priceOfCup));
    else if ((numberOfCoffees == 1) && (hasWhippedCream) && (!hasChocolate))
        priceMessage.setText(getString(R.string.total_coffee_cost_one_whipped_cream, name, numberOfCoffees, numberOfCoffees * priceOfCup));
    else if ((numberOfCoffees == 1) && (!hasWhippedCream) && (hasChocolate))
        priceMessage.setText(getString(R.string.total_coffee_cost_one_chocolate, name, numberOfCoffees, numberOfCoffees * priceOfCup));
    else if ((numberOfCoffees == 1) && (hasWhippedCream) && (hasChocolate))
        priceMessage.setText(getString(R.string.total_coffee_cost_one_cream_chocolate, name, numberOfCoffees, numberOfCoffees * priceOfCup));
    else if ((numberOfCoffees > 1) && (!hasWhippedCream) && (!hasChocolate))
            priceMessage.setText(getString(R.string.total_coffee_cost, name, numberOfCoffees, numberOfCoffees * priceOfCup));
    else if ((numberOfCoffees > 1) && (hasWhippedCream) && (!hasChocolate))
            priceMessage.setText(getString(R.string.total_coffee_cost_whipped_cream, name, numberOfCoffees, numberOfCoffees * priceOfCup));
    else if ((numberOfCoffees > 1) && (!hasWhippedCream) && (hasChocolate))
        priceMessage.setText(getString(R.string.total_coffee_cost_chocolate, name, numberOfCoffees, numberOfCoffees * priceOfCup));
    else if ((numberOfCoffees > 1) && (hasWhippedCream) && (hasChocolate))
        priceMessage.setText(getString(R.string.total_coffee_cost_cream_chocolate, name, numberOfCoffees, numberOfCoffees * priceOfCup));
    return priceMessage;
}

Все было хорошо, но потом в курсе решили добавить еще одну переменную - имя пользователя, которое тот вводит при заказе. И оказалось, что я не могу просто взять, и добавить третью переменную в строку, сделав, например, так:

<string name="total_coffee_cost">Hi, %1$s! You ordered %2$d cups of coffee. \nPrepare to pay $%3$d. \nThank you!</string>

Погуглив, выяснил, что метод setText() не может работать с тремя и более параметрами...

Как быть? В курсе Udacity не заморачиваются с этим - они напрямую выводят данные, не храня строки ни в strings.xml, не используя setText().

Должно же быть нормальное решение, ведь этих параметров может быть не три, как у меня, а намного больше...

Добавлю текст ошибки:

Wrong argument count, format string total_coffee_cost_one requires 2 but format call supplies 3. This lint check ensures the following:

(1) If there are multiple translations of the format string, then all translations use the same type for the same numbered arguments

(2) The usage of the format string in Java is consistent with the format string, meaning that the parameter types passed to String.format matches those in the format string.

Проблема решена. Подсказали ввести промежуточную текстовую переменную, которую вставлять в setText(). Как только я ее добавил, Андроид Студио указала на синтаксические ошибки - отсутствие фигурных скобочек у каждого условия в if-else ветвлении.

Когда метод выглядит так, все отлично работает:

private TextView createOrderSummary(View view){
    EditText nameField = findViewById(R.id.name_field);
    String name = nameField.getText().toString();
    CheckBox whippedCreamCheckBox = findViewById(R.id.whipped_cream_checkbox);
    hasWhippedCream = whippedCreamCheckBox.isChecked();
    CheckBox chocolateCheckBox = findViewById(R.id.chocolate_checkbox);
    hasChocolate = chocolateCheckBox.isChecked();
    TextView priceMessage = findViewById(R.id.price_text_view);
    if (numberOfCoffees == 0) {
        textString = getString(R.string.total_coffee_cost_zero, name);
        priceMessage.setText(textString);
    }
    else if ((numberOfCoffees == 1) && (!hasWhippedCream) && (!hasChocolate)) {
        textString = getString(R.string.total_coffee_cost_one, name, numberOfCoffees, numberOfCoffees * priceOfCup);
        priceMessage.setText(textString);
    }
    else if ((numberOfCoffees == 1) && (hasWhippedCream) && (!hasChocolate)) {
        textString = getString(R.string.total_coffee_cost_one_whipped_cream, name, numberOfCoffees, numberOfCoffees * priceOfCup);
        priceMessage.setText(textString);
    }
    else if ((numberOfCoffees == 1) && (!hasWhippedCream) && (hasChocolate)) {
        textString = getString(R.string.total_coffee_cost_one_chocolate, name, numberOfCoffees, numberOfCoffees * priceOfCup);
        priceMessage.setText(textString);
    }
    else if ((numberOfCoffees == 1) && (hasWhippedCream) && (hasChocolate)) {
        textString = getString(R.string.total_coffee_cost_one_cream_chocolate, name, numberOfCoffees, numberOfCoffees * priceOfCup);
        priceMessage.setText(textString);
    }
    else if ((numberOfCoffees > 1) && (!hasWhippedCream) && (!hasChocolate)) {
        textString = getString(R.string.total_coffee_cost, name, numberOfCoffees, numberOfCoffees * priceOfCup);
        priceMessage.setText(textString);
    }
    else if ((numberOfCoffees > 1) && (hasWhippedCream) && (!hasChocolate)) {
        textString = getString(R.string.total_coffee_cost_whipped_cream, name, numberOfCoffees, numberOfCoffees * priceOfCup);
        priceMessage.setText(textString);
    }
    else if ((numberOfCoffees > 1) && (!hasWhippedCream) && (hasChocolate)) {
        textString = getString(R.string.total_coffee_cost_chocolate, name, numberOfCoffees, numberOfCoffees * priceOfCup);
        priceMessage.setText(textString);
    }
    else if ((numberOfCoffees > 1) && (hasWhippedCream) && (hasChocolate)) {
        textString = getString(R.string.total_coffee_cost_cream_chocolate, name, numberOfCoffees, numberOfCoffees * priceOfCup);
        priceMessage.setText(textString);
    }
    return priceMessage;
}
READ ALSO
Начало работы с vk api

Начало работы с vk api

Хочу написать бота для вкНо столкнулся с такой проблемой

190
Переход с одного webview на другой

Переход с одного webview на другой

В Android studio сделал простой список используя массив listviewПредположим что в нем 3 пункта при нажатии на каждый выходит свой текст в файле txt

188
Jsoup java не подгружаются некоторые элементы

Jsoup java не подгружаются некоторые элементы

Парсю сайт с ценами на бензин , вот мой код:

153
Как получить путь к папке с помощью Intent на Android

Как получить путь к папке с помощью Intent на Android

Для получения файла использую:

162