Create an Android Dialog with an Image

Want something more than text when you pop up a dialog from your Android app? How about a company logo inside your about box? It’s not hard at all. In this post, I show how to create a menu option for an about box and how to launch a dialog with a custom view when its selected.

First of all, we create an xml layout file for our about dialog and call it about.xml:

<?xml version="1.0" encoding="UTF-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  android:id="@+id/root"
  android:padding="10dip">

<ImageView
  android:id="@+id/about_logo"
  android:layout_width="40dip"
  android:layout_height="40dip"
  android:layout_margin="10dip"
  android:layout_gravity="center"
  android:layout_centerHorizontal="true"
  android:src="@drawable/icon"
  />

<TextView android:id="@+id/about_title"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_gravity="center"
  android:text="@string/about_content"
  android:gravity="center_horizontal"
  android:layout_centerHorizontal="true"
  android:layout_below="@id/about_logo"
  />
</RelativeLayout>

This layout contains a RelativeLayout root which means we can a bit more precise with how elements are positioned compared to the LinearLayout where items are stacked side by side either horizontally or vertically depending on the chosen android:orientation setting. Having said that, I’m not doing anything special by using the RelativeLayout here. In fact, I could have achieved the same layout with the LinearLayout but I try to use RelativeLayout where possible as I believe it’s more efficient when rendering, especially when nesting layouts. In this file we have an ImageView that will display the company logo and a TextView that will display the copyright blurb. The actual text and image displayed are resources in the application designated by android:src=”@drawable/icon” and android:text=”@string/about_content” respectively.

Next up, we need a menu that will appear when the Menu button of an Android phone is tapped. Again the content of a menu is determined by an xml file that lives in the res/menu folder named menu.xml:

<?xml version="1.0" encoding="UTF-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:id="@+id/menuAbout"
  android:title="About..."
  android:alphabeticShortcut="a"
  />
</menu>

Having defined our layouts and menus let’s turn to the code. In our Activity we override the onCreateOptionsMenu. When invoked the MenuInflater creates the UI element to display our “About…”  menu option using the identifier R.menu.menu, which corresponds to menu.xml

@Override
public boolean onCreateOptionsMenu(Menu menu){
  super.onCreateOptionsMenu(menu);
  MenuInflater inflater = getMenuInflater();
  inflater.inflate(R.menu.menu, menu);
  return true;
}

In order to respond to the menu item being selected we also need to override the onOptionsItemSelected method and this is where we show our dialog with our image:

@Override
public boolean onOptionsItemSelected(MenuItem item){
  super.onOptionsItemSelected(item);
  switch(item.getItemId()){
  case R.id.menuAbout:
    LayoutInflater inflater = (LayoutInflater)this.getSystemService(LAYOUT_INFLATER_SERVICE);
    View layout = inflater.inflate(R.layout.about, (ViewGroup)findViewById(R.id.root));
    AlertDialog.Builder adb = new AlertDialog.Builder(this);
    adb.setView(layout);
    adb.show();
    return true;
  }
  return false;
}

The switch statement only shows the one option (I removed others for clarity) but we could easliy have more which is why we need to know which one was selected hence the call to getItemId() on the MenuItem object which is passed to us by the runtime. Once we determine that the About option was selected we need to turn our xml file, which we declared at the beginning, into a full fledged view instance. This is the job of the LayoutInflater which we grab using the getSystemService method call. Next, the inflate method is invoked passing the id of the layout file that we want to instantiate. This id is automatically generated for us based on the name of the file – about.xml. The second parameter corresponds to the id we gave to the RelativeLayout element in the same file. The end result is a View object which we can pass to the AlertDialog.Builder through the setView method. Finally, when we call show() the dialog is displayed with our image:

About

Summary

Displaying a dialog with an image essentially comes down to creating a layout file, using LayoutInflater to create an instance, and attaching that instance to the AlertDialog. With a custom layout file your dialog can be as rich as you want.

Advertisements
Create an Android Dialog with an Image

Rotating a Bitmap in Android

I’m learning a lot from my first experience with Android development, and find the SDK and APIs pretty easy to work with. I’ve found you can achieve some pretty impressive results with relatively few lines of code but sometimes I end up thinking a problem is harder than it actually turns out to be. Rotating bitmaps is one of them.

I have a need in my android app to pull an image from a web service, rotate it 90 degress, scale it and then display it in the centre of the screen. This is what I did to achive that goal.


// Get the image we want to work with from a URL
Bitmap myBitmap = BitmapFactory.decodeStream(downloadImageFromWeb());

// or just load a resource from the res/drawable directory:
Bitmap myBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.android1);

// find the width and height of the screen:
Display d = getWindowManager().getDefaultDisplay();
int x = d.getWidth();
int y = d.getHeight();

// get a reference to the ImageView component that will display the image:
ImageView img1 = (ImageView)findViewById(R.id.img1);

// scale it to fit the screen, x and y swapped because my image is wider than it is tall
Bitmap scaledBitmap = Bitmap.createScaledBitmap(myBitmap, y, x, true);

// create a matrix object
Matrix matrix = new Matrix();
matrix.postRotate(-90); // anti-clockwise by 90 degrees

// create a new bitmap from the original using the matrix to transform the result
Bitmap rotatedBitmap = Bitmap.createBitmap(scaledBitmap , 0, 0, scaledBitmap .getWidth(), scaledBitmap .getHeight(), matrix, true);

// display the rotated bitmap
img1.setImageBitmap(rotatedBitmap);

The key to the rotation is the Matrix object. According to the Android documentation “The Matrix class holds a 3×3 matrix for transforming coordinates”. And er, that’s it. The actual rotation is applied using the createBitmap overload that takes the bitmap to transform and the matrix instance that has had the postRotate method called on it. Buried in the middle is a call to scale the bitmap but that’s not the focus here.

Having written the code, you of course need an ImageView defined in your layout xml file which we can call setImageBitmap on as shown above. This is the layout I used.


<ImageView
android:background="#ffffffff"
android:id="@+id/img1"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_gravity="center"
android:maxWidth="250dip"
android:maxHeight="250dip"
android:adjustViewBounds="true"
/>

Note that the maxWidth and maxHeight properties ensure that I don’t scale the image up too much (I’m still experimenting as to what looks good across different screen sizes) though they don’t seem to have any effect unless you  include the adjustViewBounds=”true” attribute as well.

So, in the end, rotating a bitmap is trivial and nowhere near as complex as I originally assumed it might be – a pattern I’m starting to see repeated throughout my Android development experience.

Rotating a Bitmap in Android