Friday, March 5, 2010

View states & selector resources

The beginning

when i was about to create a button with different looks than the default, i thought of an ImageButton that will change it's image when it's state changes. i opened the ImageButton reference page and found it to be well explained. basicly we should use an xml file with the following content:

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

saved in the res/drawable/ folder. then reference this file in the source property of our ImageButton (android:src).

Done .. works like a charm.

the trouble started when i tried to do the same with the ToggleButton.

first problem: we need to assign a drawable to the checked state of the ToggleButton. i'm looking for an attribute for the checked state; one like ("android:state_pressed"). the place to look for attributes is in the R.attr reference page. i found what i was looking for .. "android:state_checked" .. as expected.
So, I added the following line inside the selector tag:

<item android:state_pressed="true"
    android:drawable="@drawable/button_pressed" />

second problem: the ToggleButton has no source property (android:src attribute) .. so where are we supposed to reference the selector file?!

i found a android:button attribute for it in its parent CompoundButton that takes a drawable. i tried referencing the selector file there and it worked.
.. but why?
.. here starts our journey ..

<selector> story

what is a selector? .. every tag in the xml layout corresponds to a class in the android skd. i found it to be "StateListDrawable". this class extends the Drawable class.

if that means anything, it means that we can reference a selector file (StateListDrawable) wherever a drawable can be referenced. like what we did in android:background.

time for a little test.
i referenced the selector file in the android:background attribute of a RelativeLayout .. and it worked as expected. the background changed with the state of the RelativeLayout (pressed, focused or normal)!!

but still .. why? does the RelativeLayout has states? .. why does it has states anyway?!

state_* story

after delving into the sdk reference for a while i developed a vog idea that the View class (the parent of them all) is where these states are defined. the documentation doesn't say much (any to be specefic!) .. so i had a look at the code of the View class. yes,they are defined there. now i'm sure it's the view class.

the View class changes its state flag according to the user actions. when the view needs to draw itself, it asks the Drawable (or StateListDrwawable) to give it the drawable for the current state.

the View class defines the following states:

  • state_enabled
  • state_focused
  • state_selected
  • state_pressed
  • state_window_focused
  • state_last
  • state_first
  • state_middle
  • state_single
so all its children supports those states.

but wait .. where is the state_checked? where is it defined?
i looked for it in the ToggleButton class code and didn't find any. i found it in it's parent the CompoundButton class.

i guess that means that we can write a custom view which defines it's own states like state_foo or state_bar. then create a selector file with these states.

pretty amazingly flexable .. right!!
i'm realy in love with this OS ..

Summary

  1. the <selector> tag corresponds to the StateListDrawable class. this class extends the Drawable class.
  2. we can reference a selector file wherever a drawable can be referenced.
  3. we can use a selector file with any type of View (LinearLayout, Button, TextView ..etc)
  4. we can define our own states for our own cutom views (which we will be descussing in a later post).

Friday, February 19, 2010

Hello World!

may be because i'm a developer, i feel unsafe if i began anything new in my life without saying "Hello World!" .. i don't know what would happen to me if i didn't .. probably nothing .. bbut .. lets play safe here .. after all, there must be a good reason for every book ever written in programming to always begin with a "Hello World!"

So this is a Hello World .. then lets make it simple ..

i'm in love with android os ..
i'm not an expert in it .. i'm just beginning to be one ..
i'm here to talk about it .. about how i learn to develop applications for it .. about problems i face while developing ..
and of course about questions i have regarding it all.
in short .. this is a developer's notes.

that's all for today ..

it's really a hello world .. isn't it?!

P.S. I am NOT going to talk about myself or my life (not interesting anyway) or share my photos here (or anywhere ..) .. i'm not good at that stuff and never will be .. it's a programming ONLY notes