Logo Icon Logo
A Crowd-sourced Cookbook on Writing Great Android® Apps
GitHub logo Twitter logo OReilly Book Cover Art

Handling the Nuances of strings.xml

Author: Daniel Fowler -- Published? true -- FormatLanguage: W

Problem:

Entering text in strings.xml on most occasions is easy enough, but sometimes peculiar results crop up.

Solution:

Having an understanding on how some text strings and characters work in strings.xml will prevent strange results.

Discussion:

When some text is required on a screen it can be declared in a layout file with the android:text attribute:

<TextView android:id="@+id/textview1" 
	  android:layout_width="fill_parent"
	  android:layout_height="wrap_content" 
          android:text="This is text"/>

The text can be also be set in code:

TextView tview = (TextView) findViewById(R.id.textview1);
tview.setText("This is text");

Although hardcoding strings like this is not recommended because it reduces maintainability. Changing text at a later date may mean hunting down declarations across several Java source files and layout files. Instead, text in a project can be centralized into a strings.xml file. The file is located in the directory values under res in the project folders. Centralizing text means only one place to go to change it. It also makes localization much easier; see Internationalizing Application Text. Here is an example of a strings.xml file:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">Strings XML</string>
    <string name="text1">This is text</string>
    <string name="text2">And so is this</string>
</resources>

To access the declared string from another project XML file use @ followed by string then a slash and the string's name. Using the example above, the text for two TextViews is set with the following layout XML file:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
  <TextView android:id="@+id/textview1"
            android:layout_width="fill_parent" 
            android:layout_height="wrap_content" 
            android:text="@string/text1"
            android:textSize="16dp"/>
  <TextView android:id="@+id/textview2"
            android:layout_width="fill_parent" 
            android:layout_height="wrap_content" 
            android:text="@string/text2"
            android:textSize="16dp"/>
</LinearLayout>

In Android Studio when the strings.xml file is saved, the R class is generated (see R.java in the build directory tree), this provides a static int that can be used to reference the string in code. The R class should not be amended because it is generated by the SDK. In Studio the text attribute can be accessed via the Properties pane. The ellipse button allows an existing resource to be chosen or a new one generated.

In strings.xml an entry can duplicate another string by referencing it the same way as a layout file:

<string name="text1">This is text</string>
<string name="text2">@string/text1</string>

Since @ is used to indicate another string resource trying to set the text to a single @, using <string name="text1">@</string> will not work. Nor will text that starts with an @, e.g. <string name="text2">@mytwittername</string>.

The first @ needs to be escaped with a \ (backslash), i.e. \@ and \@mytwittername. If the @ does not start a string or is being set in code it does not need to be escaped, e.g. android:text=Twitter:@mytwittername or tview.setText("@mytwittername");. This problem of @ as the first character, or only character, also applies to the ? (question mark). If it appears at the start of a string it also needs escaping, android:text=\?.

An alternative to escaping the @ or ? is to use quotes (speech marks), the closing quote mark is optional:

<string name="text1">"@"</string>
<string name="text2">"?"</string>

If fact any number of quotes or white space before and after text is dropped. The two lines above produce an identical result to these two lines:

<string name="text1">""""""""""@"""""""</string>
<string name="text2">         "?"      </string>

There is a character for which this approach will not work:

<string name="text1">War & Peace</string>
<string name="text2">War and Peace</string>

The first line will error because of the &. This is because of the XML file format itself. XML requires balanced pairs of tags, e.g. <string> and </string>, and each start tag and end tag are enclosed in opening (<) and closing (>) angle brackets. Once a start tag is encountered the editor is on the lookout for the opening bracket of the end tag. This produces a problem if the content of the XML tags contains the open angle bracket itself such as Is 5 < 6?. This will not work. The solution is to use an XML internal entity; this is similar to using an escape character but is in a specific format for XML. The format is an ampersand, &, followed by the entity name and then a semi-colon. For the open angle bracket, or less than symbol, the name is lt, therefore the full entity is &lt; as in:

<string name="question">Is 5 &lt; 6?</string>

Depending upon what is required in an XML file at a particular point there are five internal entities defined for XML that can be used, they are:

Entity Name Usage
Left angle bracket (<) lt &lt;
Right angle bracket (>) gt &gt;
Ampersand (&) amp &amp;
Single quote or apostrophe (') apos &apos;
Double quote (") quot &quot;

Now we can see why the ampersand causes us a problem. It is used to define an internal entity and thus when one is required the amp entity itself must be used. Therefore <string name="text1">War & Peace</string> becomes <string name="text1">War &amp; Peace</string>.

However, the XML internal entity apos, while valid for XML, is reported as an error when the file is saved:

<string name="text1">This isn't working</string>
<string name="text2">This isn&apos;t working either</string>

It is another character that requires escaping or wrapping in quotes:

<string name="text1">This\'ll work</string>
<string name="text2">"This'll work as well"</string>

To use quotes (speech marks) themselves, even the XML internal entity version, escape them:

<string name="text1">Quote: \"to be, or not to be\"</string>
<string name="text2">Quote: \&quot;to be, or not to be\&quot;</string>

When defining a string that requires pre or post space again use quotes:

<string name="text1">  No spaces before and after  </string>
<string name="text2">"  Two spaces before and after  "</string>

The strings will support a new line by escaping the letter n:

<string name="text1">Split over\ntwo lines</string>
<string name="text2">2 TextViews\n4 Lines</string>

Escaping a t adds tabs to the defined string:

<string name="text1">Tab stops\t\ta\t\tb</string>
<string name="text2">\t\t\t\t\t\tc\t\td</string>

To see the escape character (backslash), use two of them:

<string name="text1">Backlash:\\</string>
<string name="text2">Slash:/</string>

The three versions of the android:textstyle attribute of a TextView can be used to set the text either bold or italic (or both):

android:textStyle="bold"
android:textStyle="italic"
android:textStyle="bold|italic"

This can be achieved in the strings.xml file using a bold (<b>) or italic tag (<i>), plus it supports an underline tag (<u>). However, instead of applying to the whole text of the TextView it can be used for individual portions of the text:

<string name="text1">Hey look:<b>bold</b> and <i>italic</i>.</string>
<string name="text2">And look: <u>underline</u> and <b><i><u>bold italic underline</u></i></b>.</string>

See Also:

[1]

Download:

The source code for this project can be downloaded from http://tekeye.uk/android/examples/download/stringsxml.zip.
Praveen 2013-06-25 02:24:10.135 I tried to get same result problematically, but did not work. Here is the code : TextView textView = (TextView) findViewById(R.id.textview31); textView.setText(getResources().getString(R.string.text25)); Is there any way to get same result problematically ?
praveenb 2012-07-20 01:52:13.642 This tutorial is really helpful. Thank you so much for this info.