Fork me on GitHub

Monday, January 28, 2013

A CSS-like styling on Android

Android SDK provides styles and themes to reuse common properties on XML layout. However, XML is verbose, and requires endless findByViewId(...) to reference it in your code.

Today I released Scaloid 0.8, which features a new way of styling Android components. Before saying too much words, let's start with an example:
new SVerticalLayout {
  STextView("I am 10 dip tall")
  STextView("Me too")
  STextView("I am taller than you")
  SEditText("Yellow input field")
  SButton("Red alert!")
}

This code displays five components on the screen:



Then, let me add a style:

new SVerticalLayout {
  style {
    case b: SButton => b.textColor(Color.RED).onClick(toast("Bang!"))
    case t: STextView => t.textSize(10 dip)
    case v => v.backgroundColor(Color.YELLOW)
  }

  STextView("I am 10 dip tall")
  STextView("Me too")
  STextView("I am taller than you").textSize(15 dip) // overriding
  SEditText("Yellow input field")
  SButton("Red alert!")
}

This code results the layout shown below:

Even if you are new to Scaloid, you may easily get the point of the code. As you expected, if you clicked the button, the toast message "Bang!" is shown.

In styles of Android SDK or even in CSS, only static properties can be assigned (such as color, margin, font, etc ...). However, Scaloid can do anything with the component, such as assigning onClick behavior, adding a new component, or replacing the component itself with another component.

For example, Scaloid styles can append another view component to the layout. let's start with a very simple code:
new SVerticalLayout {
  SEditText("Name")
  SEditText("Address")
}

Needless to say, this shows an input field with the default value "Name", as shown below:


Then, we add a style like this:
new SVerticalLayout {
  style {
    case t: SEditText =>
      STextView(t.text)
      t.text("").onFocusChange(toast("You entered: " + t.text))
  }
   
  SEditText("Name")
  SEditText("Address")
}
In this time, you can see:

The value "Name" is moved to a new text view. Also, if you moved the focus, the toast "You entered: ..." will be shown.

The signiture of the style function is style(stl: View => View). That means the style specification should return a view component, that is actually visualized on the screen. Therefore you can return another component to replace the original. For example:
new SVerticalLayout {
  style {
    case t: SEditText => new STextView().text(t.text)
  }
 
  SEditText("You cannot edit me")
}

Then every SEditText field is relpaced by a STextView component.


Type-safety for your pleasure

Thanks to Scala language, all of these examples are type-safe, which means that auto-completion of your IDE will suggest valid candidates, and if you made a mistake, IDE will warn you and the code will not be compiled at all.


Thursday, January 24, 2013

Scaloid 0.7.1 is released

This version contains a quick fix of a bug that occurs when it compiled with Scala 2.10 (pocorall/scaloid#8).

From this version, compiled artifact of Scaloid will be released for Scala 2.10. However, Scaloid still can be built with Scala 2.9.

Wednesday, January 23, 2013

Scaloid powered Soundcorset metronome & tuner


I recently released all-in-one metronome and tuner application, called Soundcorset metronome & tuner. It covers all of the basic features required to metronomes and tuners, and I will grow it constantly.

Using Scaloid, the UI layout is written incredibly concise without any XML. For example, the image shown below is the screenshot of the main activity:


In "bpm" section, the code is written as:

this += new SLinearLayout {
  SButton("-", bpm -= 1).textSize(25 dip).<<(55 dip, FILL_PARENT).>>
  SButton("+", bpm += 1).textSize(25 dip).<<(55 dip, FILL_PARENT).>>
  this += new SVerticalLayout {
    STextView(R.string.bpm)
    bpmText = STextView().textSize(25 dip)
    latinBpmText = STextView("Allegro")
  }.<<.wrap.marginLeft(10 dip).>>
}.<<.>>

A simple 9 lines of code actually build the UI and wire the logic. Look at the statement "bpm -= 1" at the line 3. This simple and intuitive code actually play the beat a little slowly, move slidebar, and change the number indicates the bps. All these chores are hidden behind the assignment overload function:

def bpm_=(b: Int) {
  // move the progress bar and do more
}

Then Scala language permits fancy expressions such as "bpm += 10".