SlidingDrawer in action
Android

SlidingDrawer is dead. Long live SlidingDrawer!

Well, after doing some work-related Android development I went to see to fitting a SlidingDrawer to some basic content but alas things have changed since I first used it for the Letchworth app. Though deprecation doesn’t mean immediate incompatibility it does signal that it can be dropped from being supported at all in the near future.

SlidingDrawer in action

SlidingDrawer in action – sliding out extra content

Naturally the Android developer suggestion was to just resurrect the code as its source code is available, but I kept hitting issues that weren’t elaborated in existing tips online. After finally collecting enough of a trail from various sources, I think I have all the steps you would need in one place (assuming that you’ve experienced using SlidingDrawer):

  1. Copy SlidingDrawer into your package. I will for this example copy and rename appropriately the class to MySlider and place it in package com.foo.prettyui
  2. Add to /res/values/attr.xml a copy of the sliding drawer styleables. For ease of reuse, refer the name value to your class name – in this case ‘MySlider’
    <?xml version="1.0" encoding="UTF-8"?>
    <resources>
    	<declare-styleable name="MySlider">
    		<attr name="handle" format="reference" />
    		<attr name="content" format="reference" />
    		<attr name="orientation"  format="integer" />
    		<attr name="bottomOffset" format="dimension" />
    		<attr name="topOffset" format="dimension" />
    		<attr name="allowSingleTap" format="boolean" />
    		<attr name="animateOnClick" format="boolean" />
    	</declare-styleable>
    </resources>
  3. Change your cloned code into using the styleable attributes that you have just declared – ie: replace all instances of R.styleable.SlidingDrawer_bottomOffset to R.styleable.MySlider_bottomOffset in MySlider.java. At the end of this stage you should check if it all compiles – hopefully things are fine which would mean it’s ready to use
  4. How to use it: you need to add the package MySlider is in by adding it as another namespace at the top of with the xml declaration (alongside the android schema). For this example
    xmlns:prettyui="http://schemas.android.com/apk/res/com.foo.prettyui" I’ve declared prettyui as my new namespace – you will need to use this for any of the SlidingDrawer MySlider styleable atributes – namely handle and content (the minimum required), so to continue:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    xmlns:prettyui="http://schemas.android.com/apk/res/com.foo.prettyui"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    ..OTHER STUFF..
     
    <com.foo.prettyui.MySlider
            android:layout_alignParentBottom="true"
            android:id="@+id/questionanswer_related_drawer"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            prettyui:handle="@+id/slider_button"
            prettyui:content="@+id/slider_section">
    ..YOUR SLIDING DRAWER STUFF..
    ..WHICH SHOULD INCLUDE 2 LAYOUTS WITH THE IDS AS STATED IN HANDLE/CONTENT..
    </com.foo.prettyui.MySlider>
     
    ..MORE STUFF..
    </RelativeLayout>
  5. The above layout attributes can be reused if you decide to extend your SlidingDrawer, say if you wish to allow it to set its height to wrap_content

So, from my phone (API level 17) onwards SlidingDrawer is officially dead. Long live SlidingDrawer!

Standard
Android Selected Button/List Screenshots
Android

Android says “what selector?” – list items & buttons

The Butt is On

I’ve been optimizing and cleaning up the AlertMe for Android app to put into the Google Play marketplace, and after using drawable shapes I figured that it was time to throw away those duplicate button images. The original used a technique familiar with web developers/designers: change the whole image according to the state of an element, in this case a button:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item 
        android:state_enabled="false"
        android:drawable="@drawable/ic_home_status_home" /><!-- default state -->
    <item 
        android:state_pressed="true" 
        android:state_enabled="true"
        android:drawable="@drawable/ic_home_status_home_pressed" /><!-- pressed state -->
    <item 
        android:state_focused="true" 
        android:state_enabled="true"
        android:drawable="@drawable/ic_home_status_home_focus" /><!-- focus/hover state -->
    <item 
        android:state_enabled="true"
        android:drawable="@drawable/ic_home_status_home" /><!-- default state, just in case -->
</selector>

All 3 images; a bit repetitive, no?

All rather neat so far. Now, developing for mobile you start to appreciate things like space – particularly when you phone is rather low on it (true story) – and the same image is kind of wasteful. Images are the worst to keep around for mobile application because they can only compress so far – while text is rather easy. When I did the Letchworth Beer Fest app I used shapes to define a background rectangle and a single image over the top, so now I save on 2 less images and a cleaner looking ‘button’ to boot:

<!-- excerpt for 'pressed' state: -->
<item android:state_pressed="true" android:state_enabled="true">
    <layer-list>
        <item>
            <shape>
                <gradient
                    android:startColor="@color/button_pressed_light"
                    android:endColor="@color/button_pressed_dark"
                    android:angle="270" /><!-- gradient box, just because -->
                <stroke
                    android:width="1dp"
                    android:color="@color/button_pressed_dark" /><!-- 1dp border -->
                <corners android:radius="3dp" /><!-- neat - round corners -->
                <padding
                    android:left="10dp"
                    android:top="10dp"
                    android:right="10dp"
                    android:bottom="10dp" />
            </shape>
        </item><!-- end box -->
        <item><!-- now overlay the image on top: -->
            <bitmap
                android:src="@drawable/ic_home_status_home"
                android:gravity="center" />
        </item>
    </layer-list>
</item>
<!-- now an excerpt for default state -->
<item android:state_enabled="true">
    <layer-list>
    <item>
        <shape>
            <solid android:color="@color/button_default_light" /><!-- can be anything, but I've made it transparent -->
            <corners android:radius="4dp" />
            <padding
                android:left="10dp"
                android:top="10dp"
                android:right="10dp"
                android:bottom="10dp" />
        </shape>
    </item>
    <item>
        <bitmap
            android:src="@drawable/ic_home_status_home"
            android:gravity="center" />
    </item>
    </layer-list>     
</item>

List item select?

When I tried to use the same states for list items in my odd/even rendered lists, I switched over from setBackgroundColor to setBackgroundResource. However I found there wasn’t a change in the pressed or focus states. Some Googling later I found these states worked for me:

<?xml version="1.0" encoding="utf-8"?>
<!-- for the 'odd' background; you can guess there is another file using '@color/menu_even' -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_enabled="false" android:state_pressed="false">
        <shape>
            <solid android:color="@color/menu_odd" />
        </shape>
    </item>
    <item android:state_pressed="true" android:state_enabled="true">
        <shape>
            <gradient
                android:startColor="@color/button_pressed_light"
                android:endColor="@color/button_pressed_dark"
                android:angle="270" />
        </shape>
    </item>
    <item android:state_focused="true" android:state_enabled="true">
        <shape>
            <gradient
                android:startColor="@color/button_selected_light"
                android:endColor="@color/button_selected_dark"
                android:angle="270" />
        </shape>
    </item>
    <item android:state_selected="true" android:state_pressed="false">
        <shape>
            <gradient
                android:startColor="@color/button_selected_light"
                android:endColor="@color/button_selected_dark"
                android:angle="270" />
        </shape>
    </item>
    <item android:state_enabled="true">
        <shape>
            <solid android:color="@color/menu_odd" />
        </shape>
    </item>
</selector>

The result is now a more unified look-and-feel as the button and list item states use the same focused and pressed highlighting colours.

Android Selected Button/List Screenshots

Screenshots of the a pressed button (left) and a focused list item (right)

Standard