Android Saga: Applying an image as the background pattern of a ListView

06/23/2012 § 2 Comments


This is the first (I hope) of many episodes of an epic saga where an iOS developer (me) adventures himself in the (so far painful) Android developers world.

Before we get started, let’s get synced. Long before mankind (back in 2007), when Android was on a very early stage, I got all fired up and started one (if not THE) first Android community in Brazil. It turns out I ended up working with iOS on the next year (which won my heart) and since then I have not write a single line of Android code. So, today I am nothing but an iOS developer struggling to build an Android application that actually feels as good as an iOS app.

We all know iOS has such appealing features that Android still lacks, like smooth scrolling apps, list views that are able to nicely bounce, a simulator that is a piece of cake and system upgrades ;P

But I am not going to write bad stuff about Android trying to make iOS shine. I am actually following an advice of a friend of mine (idevzilla). After hearing me mumbling for a couple days, he got tired and told me to go share the experience of coming out from the iOS platform and diving into the Android SDK.

Personally I hope Android experts will come to me and show me better ways of writing Android code so that I can get the user experience I want for my Android app.

Since every awesome app is made of tiny little details, let’s get started with one: apply an image as the background pattern of a ListView (equivalent to UITableView).

Let’s start with Android.

After an hour researching on how to do this, I found out that Android requires the creation of a XML file that describes a bitmap which the source is the image I want to use as the pattern and the tile mode is repeat. This file must be placed under a drawable folder.

res/drawable/app_background.xml

<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
 android:src="@drawable/background_pattern"
 android:tileMode="repeat" />

Then we need to create a set of styles for the ListView that use this bitmap and tell the app it should use those styles.

Running the app I saw that nice background. Then I scrolled down the list and it became black. I lifted my finger and then the background was there again (WTF!?).

It happens by default an Android View has a transparent background and transparency involves a lot of calculation when rendering your application on screen. In order to avoid blending and make the rendering faster while scrolling, the ListView widget uses a cache mechanism. This mechanism consists on “turning opaque the view hierarchy”. So I researched a little more until I found out that I needed to set the cache color hint to “transparent”. This solves the issue but also disables the optimization we just discussed.

res/values/styles.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="app_theme" parent="android:Theme">
 <item name="android:windowBackground">@drawable/app_background</item>
 <item name="android:listViewStyle">@style/TransparentListView</item>
 <item name="android:expandableListViewStyle">@style/TransparentExpandableListView</item>
</style>

<style name="TransparentListView" parent="@android:style/Widget.ListView">
 <item name="android:cacheColorHint">@android:color/transparent</item>
</style>

<style name="TransparentExpandableListView" parent="@android:style/Widget.ExpandableListView">
 <item name="android:cacheColorHint">@android:color/transparent</item>
</style>
</resources>

AndroidManifest.xml

<application
 android:icon="@drawable/ic_launcher"
 android:label="@string/app_name"
 android:theme="@style/app_theme">

Okay. This works out. BUT…I want the background to scroll together with the ListView so the user feels he is actually moving the list down or up.

Unfortunately the only way I found to achieve this goal is to forget about that styles.xml file and undo the changes to the AndroidManifest.xml file. Instead, we need to create a layout file for the list item (equivalent to UITableViewCell) and add the following to the root Layout element:

 android:cacheColorHint="@android:color/transparent"
 android:background="@drawable/app_background"

This however will not disable any highlights caused by the list selectors…but this post already got too long.

Let’s ignore this issue for a moment and see how iOS handles this.

self.tableView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"background-pattern.png"]];

That is all for today.

Advertisements

Where Am I?

You are currently browsing entries tagged with Style at iOS Guy.