Check orientation of images/captures

A lot of times, you would need your app to either pick an image from the gallery or use the device’s camera for capturing a picture that your app could use. I have seen a lot of apps, do it plain wrong. Especially, the orientation of the images.

The default gallery app, reads the orientation properly, and displays the images/thumbnails properly. So, our apps can also handle images in various orientations properly. And the good news is, it’s very easy to handle.

There’s a class called ExifInterface. Most of the times, when you have a similar situation, you would almost never want a full-scaled image to be shown in your app. Most often, we use a thumbnail view for the purpose. The following code would get you a re-sized bitmap, from your original file.

Say for example, we have this path to the actual image file. imagePath


1. Create a Bitmap from the file

Bitmap b = BitmapFactory.decodeFile(imagePath);

2. Resize the Bitmap by scaling it to appropriate level

int width = b.getWidth();
int height = b.getHeight();
int newWidth = 150;
int newHeight = 150;
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
// Bitmap resizedBitmap = Bitmap.createBitmap(b, 0, 0, width, height, matrix, true);
// resizedBitmap.compress(Bitmap.CompressFormat.JPEG, 70, out);

3. Handle orientation of the image

ExifInterface exif = new ExifInterface(imagePath);
String orientation = exif.getAttribute(ExifInterface.TAG_ORIENTATION);
if (orientation.equals(ExifInterface.ORIENTATION_NORMAL)) {
        // Do nothing. The original image is fine.
} else if (orientation.equals(ExifInterface.ORIENTATION_ROTATE_90+””)) {
        matrix.postRotate(90);
} else if (orientation.equals(ExifInterface.ORIENTATION_ROTATE_180+””)) {
        matrix.postRotate(180);
} else if (orientation.equals(ExifInterface.ORIENTATION_ROTATE_270+””)) {
        matrix.postRotate(270);
}

4. Save the new bitmap 

out = new FileOutputStream(new File(“some output file path”));
Bitmap resizedBitmap = Bitmap.createBitmap(b, 0, 0, width, height, matrix, true);
resizedBitmap.compress(Bitmap.CompressFormat.JPEG, 70, out);

Now your output file would be an image that is resized and handled properly for orientation of the images. You could directly use the “resized” bitmap, but I prefere files.

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.

Custom title for your apps

The default title bar for the apps might not suit the theme of your app. You also might want to add a few more things to the title bar which the default title bar doesn’t help you with. This example will help you develop your own Title Widget which you can directly embed in your layouts containing a left icon, a title text and a progress bar. You can also control the contents of these three widgets and change it as required in your activities. Here we go.

1. The first thing you should do is to switch off the default title. You can do this easily by specifying in your AndroidManifest.xml file that do not intend to use it.

<?xml version=”1.0″ encoding=”utf-8″?>
<manifest xmlns:android=”http://schemas.android.com/apk/res/android”
    package=”com.beanie.samples.titlewidget” android:versionCode=”1″
    android:versionName=”1.0″>
    <application android:icon=”@drawable/icon” android:label=”@string/app_name”
        android:theme=”@android:style/Theme.NoTitleBar”>
        <activity android:name=”.TitleWidgetActivity”
         android:label=”@string/app_name”>
        <intent-filter>
        <action android:name=”android.intent.action.MAIN” />
        <category android:name=”android.intent.category.LAUNCHER” />
        </intent-filter>
    </activity>
    </application>
    <uses-sdk android:minSdkVersion=”4″ />
</manifest>

Here, in the application tag, set the theme of your app to use the NoTitleBar theme.

2. Create a title_widget.xml which would be the custom layout for your title bar. You can technically add any number of widgets here and finally display it with your custom title. As an example, we will add an ImageView, a TextView and a ProgressBar here.

3. Create a TitleWidget.java class which extends LinearLayout(you can use any Layout) which loads this layout file and exposes methods to modify the contents of the widgets.

4. Add the TitleWidget class as the first view in all your activity layouts’ files to display your custom title bar.

<?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">
 <com.beanie.samples.titlewidget.TitleWidget
android:id="@+id/titleWidget"
  android:layout_width="fill_parent"
android:layout_height="wrap_content">
 </com.beanie.samples.titlewidget.TitleWidget>
</LinearLayout>

5. Now, in your activity, you can initialize this TitleWidget as any view, since it is a LinearLayout now, and can control the contents of all the widgets.

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        // Initialize title Widget
        TitleWidget titleWidget = (TitleWidget)
                             findViewById(R.id.titleWidget);

        // Call the methods to change the underlying widgets
        titleWidget.setTitle("My Custom Title");
        titleWidget.setIcon(R.drawable.icon);
        titleWidget.showProgressBar();
        titleWidget.hideProgressBar();
    }

Now you have your own custom title. On the surface, it doesn’t actually feel like a title bar, and yes, it isn’t. It’s just a custom view, that you are trying to make it look like a title bar. Remember!! We switched off the titles by specifying that our app’s theme to “NoTitleBar”. :)
You can find the whole source code here.

Using Custom fonts on Android

I had to do this for a project that I am working on, and I felt that it wasn’t possible to achieve this. Well, there are several examples on the internet regarding this and nothing seemed to be working for me. So, in this post, we will see how to use custom fonts for your application on Android.

Few things before we start off:

  • Not all fonts are compatible with Android
  • You need to package the ttf files with your apk
  • It’s obviously a little bit of extra work

So for this example, we have a TextView and a Button with different fonts. To be able to use your custom font everywhere, ie, on all the TextView and Button widgets in your app, you will have to extend these classes to create your own TextView and Button classes. I have named them as MyTextView and MyButton. And then, I can use these buttons in my layout xml files, with the fully-qualified name of my custom classes.

<?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”>

    <com.beanie.samples.customfont.MyTextView
        android:layout_marginTop=”10dip” android:id=”@+id/textView”
        android:layout_width=”fill_parent” android:layout_height=”wrap_content”
        android:text=”@string/hello” android:textSize=”20sp”></com.beanie.samples.customfont.MyTextView>

    <com.beanie.samples.customfont.MyButton
        android:layout_marginTop=”10dip” android:id=”@+id/textView”
        android:layout_width=”fill_parent” android:layout_height=”wrap_content”
        android:text=”@string/hello” android:textSize=”20sp”></com.beanie.samples.customfont.MyButton>
</LinearLayout>

In both these classes, we have a method called init() which is called from all the constructors. The method is just 3 line long.

        if (!isInEditMode()) {
                  Typeface tf = Typeface.createFromAsset(getContext().getAssets(), “fonts/ds_digib.ttf”);
                  setTypeface(tf);
        }

Simple!!! You might notice that there is an if condition. This is not required, but it does help when you are preparing your layouts on eclipse, and you need to keep checking if everything’s fine. This method, isInEditMode() returns true while eclipses tries to render the view from the XML.

This is what the documentation says:

Indicates whether this View is currently in edit mode. A View is usually in edit mode when displayed within a developer tool. For instance, if this View is being drawn by a visual user interface builder, this method should return true. Subclasses should check the return value of this method to provide different behaviors if their normal behavior might interfere with the host environment. For instance: the class spawns a thread in its constructor, the drawing code relies on device-specific features, etc. This method is usually checked in the drawing code of custom widgets.

If you don’t put this condition, the layout editor will complain about not being able to set the TypeFace. So, in the layout editor, you will see your TextView and Button widgets with the default font. But, when you run your app on an emulator or a device, you can see the goodness of your custom fonts.

The source code for the sample project can be found here. You can find 3 different fonts (ttf file) in the assets folder to play with.

Inverted Android Button

Nothing complex. Just a few lines of code to invert your button. A horizontal flip of 180 degrees is pretty simple to achieve. If you want it with a specific angle, it might be a bit tricky.

Lets start with a creating a custom button class that extends the android Button class. Name it as InvertedButton.java.

You will need to override it’s onDraw() method to rotate the canvas, so that before any drawing is done, you rotate it by 180 degrees. To make the text-alignment perfect, you will also need to do a few calculations.

    @Override
    protected void onDraw(Canvas canvas) {
        int left = getPaddingLeft();
        int top = getPaddingTop();
        int right = getPaddingRight();
        int bottom = getPaddingBottom();
        int width = getWidth() – left – right;
        int height = getHeight() – top – bottom;
       
        int saveCount = canvas.getSaveCount();
        canvas.translate(left + width / 2, top + height / 2);
        canvas.rotate(-180);
        canvas.translate((-width / 2)-left, (-height / 2)-top);
        canvas.restoreToCount(saveCount);
       
        super.onDraw(canvas);

    }

There you go. You can now add this button anywhere in your XML layouts and you will always get an inverted button.

<?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”>
    <Button android:text=”Button” android:id=”@+id/button1″
        android:layout_width=”wrap_content” android:layout_height=”wrap_content”
        android:layout_gravity=”center_horizontal|top” android:textStyle=”bold”></Button>
    <com.beanie.examples.invertedbutton.InvertedButton
        android:text=”Button” android:id=”@+id/button2″ android:layout_width=”wrap_content”
        android:layout_height=”wrap_content” android:layout_gravity=”center_horizontal|bottom”
        android:textStyle=”bold”></com.beanie.examples.invertedbutton.InvertedButton>
</LinearLayout>

You can find the source code here. Happy coding!!!!