Книга: Beginning Android

Styled Formats

Styled Formats

Where styled text gets tricky is with styled string formats, as String.format() works on String objects, not Spanned objects with formatting instructions. If you really want to have styled string formats, here is the workaround:

1. Entity-escape the angle brackets in the string resource (e.g., this is <b>%1$s</b>).

2. Retrieve the string resource as normal, though it will not be styled at this point (e.g., getString(R.string.funky_format)).

3. Generate the format results, being sure to escape any string values you substitute in, in case they contain angle brackets or ampersands.

String.format(getString(R.string.funky_format),
 TextUtils.htmlEncode(strName));

4. Convert the entity-escaped HTML into a Spanned object via Html.fromHtml().

someTextView.setText(Html
 .fromHtml(resultFromStringFormat));

To see this in action, let’s look at the Resources/Strings demo, which can be found in the Source Code area of http://apress.com. Here is the layout file:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:orientation="vertical"
 android:layout_width="fill_parent"
 android:layout_height="fill_parent"
>
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="horizontal"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
 >
  <Button android:id="@+id/format"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:text="@string/btn_name"
  />
  <EditText android:id="@+id/name"
   android:layout_width="fill_parent"
   android:layout_height="wrap_content"
  />
 </LinearLayout>
 <TextView android:id="@+id/result"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
 />
</LinearLayout>

As you can see, it is just a button, a field, and a label. The intent is for somebody to enter their name in the field, then click the button to cause the label to be updated with a formatted message containing their name.

The Button in the layout file references a string resource (@string/btn_name), so we need a string resource file (res/values/strings.xml):

<?xml version="1.0" encoding="utf-8"?>
<resources>
 <string name="app_name">StringsDemo</string>
 <string name="btn_name">Name:</string>
 <string name="funky_format">My name is &lt;b&gt;%1$s&lt;/b&gt;</string>
</resources>

The app_name resource is automatically created by the activityCreator script. The btn_name string is the caption of the Button, while our styled string format is in funky_format.

Finally, to hook all this together, we need a pinch of Java:

package com.commonsware.android.resources;
import android.app.Activity;
import android.os.Bundle;
import android.text.TextUtils;
import android.text.Html;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class StringsDemo extends Activity {
 EditText name;
 TextView result;
 @Override
 public void onCreate(Bundle icicle) {
  super.onCreate(icicle);
  setContentView(R.layout.main);
  name = (EditText)findViewById(R.id.name);
  result = (TextView)findViewById(R.id.result);
  Button btn = (Button)findViewById(R.id.format);
  btn.setOnClickListener(new Button.OnClickListener() {
   public void onClick(View v) {
    applyFormat();
   }
  });
 }
 private void applyFormat() {
  String format = getString(R.string.funky_format);
  String simpleResult = String.format(format,
   TextUtils.htmlEncode(name.getText().toString()));
  result.setText(Html.fromHtml(simpleResult));
 }
}

The string resource manipulation can be found in applyFormat(), which is called when the button is clicked. First, we get our format via getString() — something we could have done at onCreate() time for efficiency. Next, we format the value in the field using this format, getting a String back, since the string resource is in entity-encoded HTML. Note the use of TextUtils.htmlEncode() to entity-encode the entered name, in case somebody decides to use an ampersand or something. Finally, we convert the simple HTML into a styled text object via Html.fromHtml() and update our label.

When the activity is first launched, we have an empty label (see Figure 19-1).


Figure 19-1. The StringsDemo sample application, as initially launched

However, if we fill in a name and click the button, we get the result seen in Figure 19-2.


Figure 19-2. The same application, after filling in some heroic figure’s name

Оглавление книги

Оглавление статьи/книги

Генерация: 2.581. Запросов К БД/Cache: 3 / 0
поделиться
Вверх Вниз