Alert Dialogs – Part 1
This tutorial will walk you through creating a simple log out dialog that prompts the user for a decision, takes arguments, handles orientation changes, and communicates the decision to the containing Activity.
Using Multiple Layouts in a ListView
Ever wanted multiple layouts in a ListView, perhaps a list of events with a header containing the date, and events for the day below? In this post I will show you one way to accomplish that. The full code for this project is available on Github. In the next post I'll show how to use the ViewHolder pattern to minimize findViewById(int) calls.
The keys to making this happen are Adapter.getItemViewType(int) and Adapter.getViewTypeCount()
getItemViewType should return an integer that identifies what type of View that will be created by getView(int, View, ViewGroup) for the specified item. Two views should return the same result if one can be converted to the other in getView
getViewTypeCount should return an integer with the number of types of Views that the Adapter will handle.
Behind the scenes Android uses the View type to determine what type of View should be passed in to the getView method. You can think of it as creating multiple buckets of Views that can be reused and thus avoid the penalty of inflating a new view each time a new list item becomes visible.
As the user scrolls down the ListView the framework will recycle rows that are no longer visible and add them to the appropriate bucket for reuse. When a new Header or Event item comes into view the framework will check to see if one of those views already exists in the bucket of recycled views, if so it will be passed in as the convertView to getView.
First, let's start with the Item interface that each row type will implement. getViewType will return the type of View for this row. getView will handle creating a new row or recycling an old one.
public interface Item {
public int getViewType();
public View getView(LayoutInflater inflater, View convertView);
}
Next, let's take a look at an Adapter implementation that takes a list of objects implementing Item. You don't have to use an enum, but I think it helps with code clarity here.
public class MyListAdapter extends ArrayAdapter<Item> {
private List<Item> items;
private LayoutInflater inflater;
public enum RowType {
// Here we have two items types, you can have as many as you like though
LIST_ITEM, HEADER_ITEM
}
public MyListAdapter(Context context, LayoutInflater inflater, List<Item> items) {
super(context, 0, items);
this.items = items;
this.inflater = inflater;
}
@Override
public int getViewTypeCount() {
// Get the number of items in the enum
return RowType.values().length;
}
@Override
public int getItemViewType(int position) {
// Use getViewType from the Item interface
return items.get(position).getViewType();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// Use getView from the Item interface
return items.get(position).getView(inflater, convertView);
}
}
Now we need some Items that we can add to the Adapter. Let's begin with the Header type, which is just a LinearLayout containing a TextView.
public class Header implements Item {
private final String name;
public Header(String name) {
this.name = name;
}
@Override
public int getViewType() {
return RowType.HEADER_ITEM.ordinal();
}
@Override
public View getView(LayoutInflater inflater, View convertView) {
if (convertView == null) {
// No views to reuse, need to inflate a new view
convertView = (View) inflater.inflate(R.layout.header, null);
}
TextView text = (TextView) convertView.findViewById(R.id.headerText);
text.setText(name);
return convertView;
}
}
Next we'll create the EventItem type, which consists of two TextViews in a LinearLayout and shares much of the same code with the Header item type above.
public class EventItem implements Item {
private final String str1;
private final String str2;
public EventItem(String text1, String text2) {
this.str1 = text1;
this.str2 = text2;
}
@Override
public int getViewType() {
return RowType.LIST_ITEM.ordinal();
}
@Override
public View getView(LayoutInflater inflater, View convertView) {
if (convertView == null) {
convertView = (View) inflater.inflate(R.layout.list_item, null);
}
TextView text1 = (TextView) convertView.findViewById(R.id.list_content1);
TextView text2 = (TextView) convertView.findViewById(R.id.list_content2);
text1.setText(str1);
text2.setText(str2);
return convertView;
}
}
All that is really left is to create a ListActivity and add some items to our new adapter.
public class MainActivity extends ListActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LayoutInflater inflater = LayoutInflater.from(this);
List<Item> items = new ArrayList<Item>();
items.add(new Header("Friday - November 30th 2012"));
items.add(new EventItem("8:30am" , "Start work"));
items.add(new EventItem("9:15am" , "Call Bob"));
items.add(new EventItem("11:00am", "Meeting with Joe"));
items.add(new EventItem("5:00pm" , "Freedom!"));
items.add(new Header("Saturday - December 1st 2012"));
items.add(new EventItem("8:30am" , "Keep sleeping"));
items.add(new EventItem("10:00am", "Wake up"));
items.add(new EventItem("11:00am", "Walk the dog"));
items.add(new EventItem("6:00pm" , "Dinner at John's"));
items.add(new Header("Sunday - December 2rd 2012"));
items.add(new EventItem("8:30am" , "Keep sleeping"));
items.add(new EventItem("10:00am", "Wake up"));
items.add(new EventItem("11:00am", "Walk the dog"));
items.add(new EventItem("6:00pm" , "Dinner at John's"));
items.add(new Header("Monday - December 3rd 2012"));
items.add(new EventItem("8:30am" , "Start work"));
items.add(new EventItem("9:15am" , "Call Bob"));
items.add(new EventItem("11:00am", "Meeting with Joe"));
items.add(new EventItem("5:00pm" , "Freedom!"));
MyListAdapter adapter = new MyListAdapter(this, inflater, items);
setListAdapter(adapter);
}
}
Using BuildConfig.DEBUG in Android Maven projects
I was setting up a project to build with Maven and I had some code that relied on the BuildConfig.DEBUG setting to enable Strict Mode and logging, but when I was running the release build of my project I found that it wasn't setting BuildConfig.DEBUG to False.
After some searching I found that the ability to set BuildConfig.DEBUG to True was added in Android Maven Plugin 3.3.2 and updated in 3.4.0.
If you are using 3.3.2 then you need to set the android.release property as a System Property.
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>properties-maven-plugin</artifactId>
<version>1.0-alpha-2</version>
<executions>
<execution>
<goals>
<goal>set-system-properties</goal>
</goals>
<configuration>
<properties>
<property>
<name>android.release</name>
<value>true</value>
</property>
</properties>
</configuration>
</execution>
</executions>
</plugin>
If you're using version 3.4.0 of the Android Maven Plugin it can be configured by a standard Maven property with <android.release>true</android.release> in the properties section.
<profile> <id>release</id> <activation> <property> <name>performRelease</name> <value>true</value> </property> </activation> <properties> <android.release>true</android.release> </properties> ...
Android with Eclipse – Conversion to Dalvik format failed with error 2
Today I was playing around with eclipse.ini trying to speed it up a bit (using this StackOver post), but when I restarted Eclipse I got the dreaded "Conversion to Dalvik format failed with error 2" message when building an Android project. I tried running a Clean, running "Fix Project Properties", and refreshing, but had no luck.
Eventually I found Issue #9883 which noted that removing "-XX:+AggressiveOpts" from eclipse.ini fixed the issue. I updated the eclipse.ini and everything started building fine again!
As an aside, here is my eclipse.ini (Windows 7 64bit w/Java 7):
-startup plugins/org.eclipse.equinox.launcher_1.3.0.v20120522-1813.jar -vm C:\Program Files\Java\jdk1.7.0\jre\bin\server\jvm.dll --launcher.library plugins/org.eclipse.equinox.launcher.win32.win32.x86_64_1.1.200.v20120522-1813 -product org.eclipse.epp.package.java.product --launcher.defaultAction openFile --launcher.XXMaxPermSize 1024M -showsplash org.eclipse.platform --launcher.XXMaxPermSize 1024m --launcher.defaultAction openFile -vmargs -server -Xss500k -Xms128m -Xmx384m -Xss4m -XX:MaxPermHeapExpansion=10m -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=70 -XX:+UseCMSInitiatingOccupancyOnly -XX:+UseParNewGC -XX:+CMSConcurrentMTEnabled -XX:ConcGCThreads=2 -XX:ParallelGCThreads=2 -XX:+CMSIncrementalPacing -XX:CMSIncrementalDutyCycleMin=0 -XX:CMSIncrementalDutyCycle=5 -XX:GCTimeRatio=49 -XX:MaxGCPauseMillis=20 -XX:GCPauseIntervalMillis=1000 -XX:+UseCMSCompactAtFullCollection -XX:+CMSClassUnloadingEnabled -XX:+DoEscapeAnalysis -XX:+UseCompressedOops -XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses
AdMob – Adjusting AdView height when using SMART_BANNER
I recently ran into a situation where I needed to find the height of an AdMob ad and adjust another view based on its size. The problem with simply calling View.getHeight() is that it will return zero until the View is actually laid out on the screen, even in onResume() it will return zero.
The solution is to use an ViewTreeObserver.OnGlobalLayoutListener and listener for when the height of the view is non-zero.
mAdView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
int height = mAdView.getHeight();
if (height > 0) {
// Here I adjust the bottom margin of an ImageView
RelativeLayout.LayoutParams imageParams = (RelativeLayout.LayoutParams) mImageView.getLayoutParams();
imageParams.setMargins(0, 0, 0, height);
mImageView.setLayoutParams(imageParams);
// We can remove the GlobalLayoutListener now that we found the height
// This is important because if we didn't remove the listener when we modified
// the view it would cause an infinite loop
mAdView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
}
});
Custom error icon for EditText on Android
I've been working on updating my Reddit in Pictures app and while I was adding error checking to the dialogs I found I wasn't a fan of the default error indicator icon.
The default setError method uses the drawable com.android.internal.R.drawable.indicator_input_error which is a red circle with a transparent exclamation point.
I wasn't a fan of the transparency in the exclamation point so I whipped up one with a white background in Inkscape.
Here's what it looks like with the updated image:
![]()
Here is a zip file with the SVG and different sizes in PNG format (xhdpi, hdpi, mdpi, ldpi).
Reddit In Pictures

Reddit In Pictures - Imgur Album view
For the last two weeks I've been working on a new Android application in my spare time, an image browser for Reddit that I'm calling Reddit In Pictures
The main features:
- Browse any subreddit
- Swipe between images to go backwards or forwards (new images are loaded automatically)
- Ads can be disabled.
- Toggle Not-Safe-For-Work (Nsfw) images on/off
- Supports Imgur URLs and albums
- Sort by age and category (Hot, Top - All Time, etc)
- View a post summary with title, upvotes, subreddit, comments, submitter
- Pinch-to-zoom on any image
- View animated Gifs
- Share posts with other apps (e.g. Facebook)
- View the full post on the Reddit Mobile site (or open it in another Reddit mobile app)
- Images are cached to avoid repeated downloads, available cache size will vary by device.

I am trying something new with this app i'm calling "RateWare". Ads can be disabled at any time via the settings menu, in exchange for disabling ads I ask that users rate the app in the Google Play Store. It works on the honor system, you don't have to e-mail me for a key, all I'm really looking for here is more ratings and more reviews - whether they be positive or negative. It's a bit of a hybrid between freemium and ad supported apps.
I tried to find other examples of RateWare on the market, but I was unsuccessful, if anyone has encountered other examples I'd love to hear of them.
My plan is to release the free version with the features above, and then a Pro version that includes additional features like:
- Logging in
- Loading subscribed reddits
- Upvoting and downvoting posts
- Saving posts
- Saving images
I'm more a fan of the freemium revenue model over a free version with ads and a pro version that simply has ads removed, and I think users will prefer it as well.
The main problem I see with simply removing ads in a paid version is that it's a poor experience from the user's perspective. They're paying to remove the annoying parts of app they're already using, and aside from the warm fuzzies from supporting a developer they get nothing else. By removing ads and adding features the transaction feels much more even handed, I'm not paying solely to stop being annoyed, I'm getting more a better app as well.
Diablo 3 Character Builder for Android
This one is a collaboration between my brother and I, it is called Diablo 3 Builder (for Android), and like it sounds, it is for creating character builds. We released it under the developer moniker "We Make Stuff".
It features:
- Support for all classes and followers
- High quality images for all skills and runes
- Choose active skills and runes
- Choose passive skills
- Choose followers and their skills
- Save and Load builds
- Load builds from the Battle.net Skill Calculator, just click a link!
- Easily share your build with friends
This was a lot more involved than the last project and it made it quite a bit more fun.
My brother wrote a scraper for the D3 website to turn the information into JSON we could then include with the app, and then we both worked on the other components.
We used:
- ViewPagerIndicator for the title effect on the ViewPager
- Gson for parsing the JSON (had used it in other projects)
- ActionBarSherlock for the ActionBar
- Maven for builds
- BitBucket w/git for version control
Some of the cool stuff:
- Made the app accept battle.net Skill Calculator links, e.g. if you open http://us.battle.net/d3/en/calculator/barbarian#bcUQgj!YVg!aZZZZZ on your phone the app will show in the list to consume the link. Intent filters are awesome.
- You can share builds from within the app in battle.net link format via Messaging and other apps.
- Added Action Mode selection for clearing list items. This was more fun for me than really cool...but I've never been a fan of the popup context menus, so I decided to figure out how to use action modes like G-mail/Messaging.
The app is doing pretty well on the market so far IMO, we have around 5,000 downloads and only positive reviews. It was definitely fun to write and I learned quite a bit.
Easy Tip and Split Calculator
I actually released this application on the Google Play Store a while back, but I neglected to post about it.
I had been talking about Android development since I bought my first Android phone, the OG Droid, but a few months ago I decided to challenge myself to actually release an app.
Tip Calculators are a dime a dozen in the Market, but most are poorly designed and require too much work for what should be a simple task. My main goals were to make it easy to use and to learn more about Android development. The app shows:
- Creating custom controls with custom attributes (a HorizontalNumberPicker)
- Using ActionbarSherlock
- Using Maven for builds
- Handling currency with BigDecimal
- Handling orientation changes
- Using an input filters on a text field
- Simple menu item in ActionBar
[1] Screenshot
[2] Market Link
[3] Source Code The app has no ads and requires no permissions.
Checkable Menu Items on Android
I needed to create a checkable menu in an Android app recently, luckily the framework makes it nice and simple.
First, create an XML file under /res/menu/. In this example I've named my menu "main.xml" and we have a menu item that opens a sub-menu when clicked.
android:checkableBehavior has three valid values:
- single - Only one item from the group can be checked (radio buttons)
- all - All items can be checked (checkboxes)
- none - No items are checkable
You can specify whether an item starts out checked with android:checked="[true/false]"
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:id="@+id/change_category" android:showAsAction="withText" android:title="Category">
<menu>
<group android:id="@+id/categories" android:checkableBehavior="single">
<item android:id="@+id/category_hot" android:title="Hot"/>
<item android:id="@+id/category_new" android:title="New"/>
<item android:id="@+id/category_controversial" android:title="Controversial"/>
<item android:id="@+id/category_top" android:title="Top"/>
</group>
</menu>
</item>
</menu>
Then in the Activity we override the OnCreateOptionsMenu method to inflate our menu and add it to the View.
public enum Category { HOT, NEW, RISING, CONTROVERSIAL, TOP; }
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
super.onCreateOptionsMenu(menu);
// If you are using ActionBarSherlock, call getSupportMenuInflater() instead
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main, menu);
MenuItem categoryHot = menu.findItem(R.id.category_hot);
MenuItem categoryControversial = menu.findItem(R.id.category_controversial);
MenuItem categoryNew = menu.findItem(R.id.category_new);
MenuItem categoryTop = menu.findItem(R.id.category_top);
switch (mCategory)
{
case CONTROVERSIAL: categoryControversial.setChecked(true); break;
case HOT: categoryHot.setChecked(true); break;
case NEW: categoryNew.setChecked(true); break;
case TOP: categoryTop.setChecked(true); break;
}
return true;
}
Next, we override onOptionsItemSelected to respond to clicks in the menu.
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
item.setChecked(true);
switch (item.getItemId())
{
case R.id.category_controversial: mCategory = Category.CONTROVERSIAL; break;
case R.id.category_hot: mCategory = Category.HOT; break;
case R.id.category_new: mCategory = Category.NEW; break;
case R.id.category_top: mCategory = Category.TOP; break;
}
return super.onOptionsItemSelected(item);
}
See the full source code for the project on Github: https://github.com/antew/android_checkable_menus

