18 February 2011

Using a custom font in WebView

In one of my projects, I needed to display some special characters that the Android OS by itself cannot seem to render. I figured that I would need to provide a custom font that includes the characters that I needed.

If I was using a TextView, I could use TextView#setTypeFace. But I was using a WebView and I feared that things would be more complicated than that. So how do I do this?

Here's how we can make it work.

Step 1: We would need to have our font face included in our project's /assets folder. So look for a TTF file that you can use freely, make sure the author/creator allows you to re-distribute it!

Step 2: Edit your HTML file to include some CSS stuff, just so the WebView would know what font you want to use. Here's a sample file:
<html><head><link href="YourCssFile.css" rel="stylesheet" type="text/css" /></head><body><span class="phon">This string contains special characters: əˈpåstrəfi </span></body></html>
Make sure that the href references are correct. In this case, my CSS file, HTML file and font file are in the same folder.

Step 3: Define your CSS file. In this case, our YourCssFile.css would be:
@font-face {
font-family: "My font";
src: url('MyFontFile.TTF');
}

.phon, .unicode {
display: inline;
font-family: 'My font', Verdana, sans-serif;
font-size: 14pt;
font-weight: 500;
font-style:normal;
color: black;
}
Step 4: Load the file in your WebView! You can use
WebView webView = (WebView) findViewById(R.id.myWebview);
webView.loadUrl("path/to/html/file");
or
webView.loadDataWithBaseURL("file:///android_asset/",
article, "text/html", Encoding.UTF_8.toString(), null);
If you will use the second option, your article variable would contain the HTML string. Just make sure that you escape your quotation marks with a backslash (\).
IMPORTANT NOTE: This feature seems to be broken in Android 2.0 and 2.1, as reported here.

17 February 2011

It never ends!

Been ultra super busy the past few weeks. Also learning a lot of new things. And renewing my battle with orientation change, AsyncTasks and dialog boxes.

So, I have been thinking of what to document here next. Here are my choices:
- Loading HTML pages stored in the SD card in a WebView
- Managing your SharedPreferences
- Using a ViewStub

I had a long list in my mind yesterday, but I managed to not write it down. *facepalm*

07 February 2011

*stealth ninja mode on*

Over the past couple of weeks, this blog has been getting unusually high traffic. Which means I get more than one hit per week.

So if it isn't too much to ask, can I please know how you got here, and what you were looking for. And please please let me know if I said anything wrong, or if you know of a better/easier/more optimized way to do the stuff I'm trying to talk about. Thanks! :)

02 February 2011

That damn seekbar thumb

If you have ever needed to use a SeekBar, you definitely would have noticed how hard it is to move the slider (aka thumb) when it is set to the minimum or maximum value. The slider tends to be cut in half, and fitting your finger into it to press it becomes a test of patience.

See how small the slider becomes when it reaches the far ends of the SeekBar? Crazy!

Luckily, I found a way (just today!) to move the slider just a little tiny bit to make it easier to press. Apparently, there is a method called setThumbOffset() that allows us to nudge the slider by a number of pixels.

It's pretty easy to use, aside from the fact that it accepts pixels and not dip measurements. Anyway, here's how to do it:
int pixels = convertDipToPixels(8f);
SeekBar mySeekBar = (SeekBar) findViewById(R.id.quiz_settings_seekbar);
mySeekBar.setOnSeekBarChangeListener(mySeekBarListener);
mySeekBar.setThumbOffset(pixels);
I convert dip measurements to pixels to better manage the growing number of resolutions of screen sizes present. Here's the code to do that:
private int convertDipToPixels(float dip) {
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
float density = metrics.density;
return (int)(dip * density);
}
Aaaaaaaand this is now how our slider looks:Applause! Confetti! Applause!