Android Themes: A dialog without a title


Most of the times, I have seen developers not leveraging the power of themes and styles. Themes and styles are a great way to easily create UI that are  manageable and compatible for various platforms. Here’s the official documentation that explains styles and themes in details, and I consider this portion of documentation to be equally important to any developer working with Android.

For the example of this post, we will see how to make a dialog, a custom dialog, not to have a title. The easiest way to do this, is through code byt writing this snippet in your custom dialog class.

requestWindowFeature(Window.FEATURE_NO_TITLE);

Dialog with Title on Android 2.2


Dialog with no title on Android 2.2

While this would work anyway, and would also be compatible with all the versions of Android. But, it’s a good idea to use more of your themes and styles in your programming, so that your code base is maintainable and your apps would behave and feel consistently. Using styles and themes makes it very easy to tweak or adapt to various platform versions and/or device sizes and resolutions. So, let’s get in.

The application tag, has a configurable attribute called “android:theme” with which you can set a theme to your application as a whole. You can also specify themes for individual themes for all your activities separately. Sounds nice!!! But, let’s stick to one theme for our application as a whole for simplicity.

For this example, we have a theme (it’s actually called a style), called MyThemeSelector as shown below. This is specified in the styles.xml in your values folder. Notice, your custom theme is a child of the Theme, which is one of the system’s default themes.

<resources>        <style name=”MyThemeSelector” parent=”@android:style/Theme”></style></resources>

Ideally, you should also declare your custom theme to extend one of the basic themes that are available with platforms on or above Honeycomb. For example, here we have created another styles.xml in a folder called values-v11, which looks like this.

<resources>
        <style name=”MyThemeSelector” parent=”@android:style/Theme.DeviceDefault.Light”></style>
</resources>

So, your basic theme is now compatible with both older versions and versions greater than Honeycomb. By this, I mean, that, when you run the app, your app would adapt to the platform that it is running on, and would give a consistent look and feel for your users.

Now, coming back to the main problem. “Creating a dialog without title”. Here also, we would use themes, as against code. Here are the two new themes that you would be declaring.

For values folder: (Platform versions older than Honeycomb)

<style name=”My.Theme.Dialog” parent=”@android:style/Theme.Dialog”>
            <item name=”android:windowNoTitle”>true</item>
</style>
<style name=”MyThemedDialog” parent=”@style/My.Theme.Dialog”></style>

For values-v11 folder: (Platform version for Honeycomb and above)

<style name=”My.Dialog.Theme” parent=”@android:style/Theme.DeviceDefault.Light.Dialog.NoActionBar”></style>
<style name=”MyThemedDialog” parent=”@style/My.Dialog.Theme”></style>

There’s a subtle difference between the two versions. Of course, other than the parent classes. In older platform versions, there wasn’t a version of the Dialog theme without a title bar. So, what we do here, is to extend the basic Dialog them, and overwrite an attribute, so that our custom “My.Theme.Dialog” is a dialog without a title bar.

But, for Honeycomb and above, the platform itself provides a version of the Dialog theme, without the title bar (or the Action Bar).

And finally, the last step for getting everything to work is set the theme to your dialogs.

MyDialog dialog = new MyDialog(this, R.style.MyThemedDialog);
dialog.setTitle(“Here’s my title”);
dialog.show(); 

Why didn’t we use “My.Theme.Dialog” directly? Well, we could still try and tweak the theme for older versions, in the values folder, by adding a few more attributes.

Dialog with title on Android 4.1


Dialog with no title on Android 4.1

As you can see, for both older and newer platforms, the app runs by adapting itself and gives a consistent look and feel. You didn’t have to do much with your code. 
15 lines of XML is the MAGIC here!!!!  (I didn’t count though, just guessing)

Sample project here.

Streaming Radio Stations on Android

Streaming radio stations or audio files hosted on streaming servers on Android is pretty straight-forward. But then, Android has it’s limitations. It won’t stream just any file or radio station. In this post, I would not be specifying the formats or protocols that Android supports. Rather, this example is just a walk through of how the MediaPlayer class should be used to stream audio files/radio stations.

For an example here, I have used a SHOUTcast radio station. The URL for the source is:
http://shoutcast2.omroep.nl:8104/

The accompanying sample project contains a ProgressBar, two Buttons (for playing and stopping the MediaPlayer).

Before running the example, one should look into the documentation of the MediaPlayer class. A look at the state diagram would perhaps help you clear to understand how it actually works.

To initialize the MediaPlayer, you need a few lines of code. There you go:

MediaPlayer player = new MediaPlayer();

player.setDataSource(“http://shoutcast2.omroep.nl:8104/”);

Now that the MediaPlayer object is initialized, you are ready to start streaming. Ok, not actually. You will need to issue the MediaPlayer’s prepare command. There are 2 variations of this.

  1. prepare(): This is a synchronous call, which is blocked until the MediaPlayer object gets into the prepared state. This is okay if you are trying to play local files that would take the MediaPlayer longer, else your main thread will be blocked.
  2. prepareAsync(): This is, as the name suggests, an asynchronous call. It returns immediately. But, that obvisouly, doesn’t mean that the MediaPlayer is prepared yet. You will still have to wait for it to get into the prepared state, but since this method will not block your main thread, you can use this method when you are trying to stream some content from somewhere else. You will get a callback, when the MediaPlayer is ready through onPrepared(MediaPlayer mp) method, and then, the playing can start.

So, for our example, the best choice would be:

player.prepareAsync();

You need to attach a listener to the MediaPlayer to receive the callback when it is prepared. This is the code for that.

player.setOnPreparedListener(new OnPreparedListener(){

            public void onPrepared(MediaPlayer mp) {
                     player.start();
            }
 

});

Once, it goes into the prepared state, you can now start playing. Simple???? Yes, of course. Just to wrap it up, to stop the MediaPlayer, you need to call the stop() method.

There are several other helper methods which lets you query the progress or status of the player. Jump to the docs page and you will find more information on them. You can checkout the source code here.

Project source for the new Eclipse + Android tool chain. Download here.

NOTE: This sample project is tested on Gingerbread(2.3) and should work on Froyo(2.2) and above.

Improved Copy/Paste in Gingerbread

It’s really important for the copy/paste feature to work on a mobile even if you don’t have a mouse to select text you want to copy. Apple’s implementation is nice. Till Froyo, there wasn’t a unified concept of copy/paste feature implemented. But, the Gingerbread has actually changed a few things 🙂 . Copying phone numbers from your mails and email addresses from web pages should be trivial and should involve the least amount of button presses. Prior to Gingerbread, this wasn’t the case, but Gingerbread has this “New Feature now”.

Here’s the link where you can find out more about this.

Some images and videos

Official documentation

You need to double-tap on the text before you can bring up the text selection controls. Once you are done with the selection, single tap on the text copies the selected text to the clipboard, and then you can extract the data from the clipboard. This is really nice. Else, you would have to write a bit of extra code to trigger text selection mode first. This copy/paste selector works on an EditText and on the Browser. I haven’t tested it further.

Gingerbread Stuff!!!! **It works on the emulator**.