Showing posts with label strings. Show all posts
Showing posts with label strings. Show all posts

17 September 2016

String formatting and Lint

One piece of advice that we keep hearing over and over is to extract strings into resources. There really is no reason for you to hard code strings in code.

I wrote before about easily moving strings between Java and XML, and today I'd like to focus on string formatting. The Android dev guide gives a good overview of the support Android has for passing arguments into a String.format(String, Object...).

Worried about using incorrect syntax? I was! I can never remember which of the % or the $ comes first, or if I'm passing arguments in the correct order. To be clear, the syntax is
%[arg number]$[arg type]


Thankfully, Android Studio has come a long way with pointing us in the right direction when working with strings.

First off, a very useful warning when setting manually concatenated text into a TextView:
 And by "placeholders" they mean the format arguments.

You can mix and match multiple arguments and argument types in one string too!

And in case you removed an argument in the XML file but forgot to edit code, another helpful error for you!

If you change the argument type, Studio will tell you about it too.

If you forget the syntax, fear not for Studio will tell you. (May not be too obvious here but I used the incorrect "$1$s" format.)

Android Studio is really so helpful now, we are running out of excuses to be lazy coders. ðŸ˜±

14 May 2015

Stringy strings


While we are on the subject of strings, here are more ways of dealing with them in Android Studio. We all know that we should not hardcode strings in code, right? But sometimes, we forget and tend to do code first before defining them in strings.xml.

There are a couple of ways that Android Studio/IntelliJ makes this easy for us. The gif below (which took me a while to figure out how to do, by the way), shows how to deal with:
1. Moving a hardcoded string into strings.xml
2. Giving a previously undefined string ID a value in strings.xml

(Click to embiggen)

Move hardcoded string into XML:
This is probably the more common scenario. You happily put in texts into your TextViews, and now you have to copy and paste them into strings.xml. Don't! There is a shortcut for that.

Put your cursor somewhere in the string, press ALT+Enter to bring up the context menu, choose "Extract string resource" and give your string resource a name. This will create a new <string name="my_string_name">My string value</string> in strings.xml.

Studio magically also calls getString(R.string.xxxxx) for you. Neat, huh?


Make new string from ID:
This is for when you suddenly remember that you need a new string and want to sort of try to do it correctly so you type in the string ID. Only it hasn't been defined yet, so Studio complains. But it's fine. There is a shortcut for that.

Put your cursor somewhere in the as of yet undefined ID, press ALT+Enter to bring up the context menu, choose "Create string value for resource my_string_id", and type in the actual string value you want. Again, this will create a new <string name="my_string_id">My other string value</string> in strings.xml.

Remember, in both of these cases, Studio will create the new strings in strings.xml, but you can modify it to put in whatever variant you want it to be in (for localisations, screen size support, etc).

15 September 2010

More plurals: decimal values

In my previous post, I showed you how to set string plurals. If you noticed, the methods to get the plurals strings only accept ints. What if (like me) you want to display a decimal value? I am getting my raw value from a progress bar with a range of 1-10, with 0.1 increments.

First, to display decimal values, I set my plurals string to display a float value.
<item quantity="other">Progress is at %.1f units.</item>

And then I devised a way to set the quantity based on the value of the progress bar (ProgressBar.getProgress() returns an int).

public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {

// get quantity for plurals string
int quantity = setQuantity(progress);

// convert the actual progress to float
float floatProgress = convertProgress(progress);

// get the actual string and replace formatting with the float value
String currentProgress = getResources()
.getQuantityString(R.plurals.seekBarProgress, // get the plurals
quantity, // set the quantity
floatProgress); // format arguments

// set text to display
TextView displayProgress = (TextView)findViewById(R.id.prog_text);
displayProgress.setText(currentProgress);

}

/**
* Use this method to see if we will use the singular or plural string.
*
* @param progress
* @return the value to set in getQuantityString()
*/
private int setQuantity(int progress){
int quantity;

if (((progress%10) == 0) && ((progress/10) == 1)){
quantity = 1;
} else {
quantity = 2;
}

return quantity;
}

/**
* Use this value to get the *actual* value to display.
*
* @param progress actual progress value from 0 to 100
* @return the float value from 0.0 to 10.0
*/
private Float convertProgress(int progress){
return ((Float.valueOf(String.valueOf(progress)))/(float)10);
}
So you see, it's quite long-winded. Here are some screen shots of the results:
Different values for the unit value

String Pluralization

Last week, I discovered Android's support for plural strings by accident. And a good accident it was since I am working on an app that will display a float to the user. I used to display:
You set XX mile(s).
which is kinda lame.

Plurals lets you specify the string to display for different quantities. So how do we use this Plurals thing?

In your string resources XML, which is usually strings.xml, define the plurals element like so:

<?xml version="1.0" encoding="utf-8"?>
<resources>
<plurals name="pluralsTest">
<item quantity="one">You have one friend.</item>
<item quantity="other">You have %d friends.</item>
</plurals>
</resources>
Remember, your parent node must be <resources>!

Android provides several methods to use these in your code. Let's see what each of them results to when used:

// set one as the quantity
String one = getResources().getQuantityString(R.plurals.pluralsTest, 1);

// set two as the quantity
String more = getResources().getQuantityString(R.plurals.pluralsTest, 2, 2);

// set one as the quantity
CharSequence quantity = getResources().getQuantityText(R.plurals.pluralsTest, 1);

// set two as the quantity
CharSequence quantityMore = getResources().getQuantityText(R.plurals.pluralsTest, 2);

I created a basic layout with TextViews to display what each of these strings look like. Take note though that getQuantityText() returns a CharSequence and not a String! Also, from what I have noticed, and as the name mildly suggests, getQuantityText() gets the actual value of the text you defined in your xml.