Friday, 7 December 2012

Android: show a View as pressed without using a Selector resource

It's possible to show a View as pressed or unpressed (when in the pressed or default state respectively) by having two versions of the View's background image, putting the two images in a selector drawable, and then assigning the selector to be the background of your View. However, sometimes you might not have two versions of the image or you might not want to bloat the size of your apk by having two(+) versions of each image. In such a situation, here's an alternative way of showing a View as pressed (or not), i.e. show a black-ish, transparent overlay over the View.

The first step is to define a black, transparent colour in your res/values/colors.xml file as follows:

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <color name="black_transparent">#70000000</color>
</resources>

The second step is to create a res/drawable/selector_foreground_black_transparent.xml file defined as follows:

<?xml version="1.0" encoding="utf-8"?>
<selector
  xmlns:android="http://schemas.android.com/apk/res/android" >
  <item
    android:state_pressed="true"
    android:drawable="@color/black_transparent" />
  <item
    android:drawable="@android:color/transparent" />
</selector>

The third and final step is two wrap your View - the one you want to be displayed as pressed or not - in a FrameLayout something as follows:

<FrameLayout
  android:id="@+id/layout_my_view"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:foreground="@drawable/selector_foreground_black_transparent"
  android:foregroundGravity="fill" >
  <View
    android:id="@+id/my_view"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/my_view_bg" />
</FrameLayout>

That's it. The only other thing to keep in mind is to put a click listener on your FrameLayout instead of putting it on your View.

No comments: