Fork me on GitHub

Wednesday, September 18, 2013

Unit of measurement of TextView.setTextSize()

The Soundcorset metronome and tuner, in which I wrote it with Scaloid, is keep growing and hits 70,000 downloads. Until recently, it has a strange problem that it displays very large text for some devices, so that some button texts are clipped away out of the layout. After some code investigation, I found that it is very tricky pitfall because the code does not seems to have any problem at first:
STextView("Hello").textSize(20 sp)  // not correct!
The unit specification like 20 sp is very common in Scaloid. The implicit function sp converts the number from the sp unit to the pixel unit. The code above looks fine because the most of the Android API receives a size as the pixel unit. But there was a single exception. The method TextView.setTextSize(float) does not receives a size as the pixel unit, it receives sp unit instead. It may cause a mistake because the most of other APIs handles a size as the pixel unit, even in TextView.getTextSize()!!! So I overridden STextView.textSize so that the APIs have consistency in pixel units:
@inline def textSize  (p: Int) =  textSize_=(p)
@inline def textSize_=(p: Int) = { 
  basis.setTextSize(android.util.TypedValue.COMPLEX_UNIT_PX, p)
Now we can safely use the method textSize with the implicit unit conversions:
STextView("Hello").textSize(20 sp)  // correct :-D
I patched the current snapshot, and it will be available at the next release of Scaloid.

Sunday, September 1, 2013

Syntactic sugar for multiple device configuration

The most common question about Scaloid that I received is that how to adapt multiple device configuration.

Basically, a layout written in Scaloid is just an ordinary Scala code, so you can just freely composite the layout according to the device configuration:
if(width > 900 dip) STextView("The display is wider than 900 dips!")

This is simple, concise and intuitive in compared to XML description. Moreover, this promotes the 'responsive design', which adapts various screen dimensions with single layout description.

The only problem was that we have to manually prepare required variables, such as width in the example above. To address this issue, I wrote a package of helper methods that can be used to determine device configurations such as screen layout and resolution in dot-per-inch. All you need is just importing org.scaloid.util.Configuration._.
import org.scaloid.util.Configuration._

if(long) SButton("This button is shown only for a long screen "
  + "dimension ("+ width + ", " + height + ")")
if(landscape) this += new SLinearLayout {
  SButton("Buttons for")
  SButton("landscape layout")
  if(dpi >= HDPI) SButton("You have a high resolution display!")
The source code is pretty straightforward. Look at the source code to figure out how it works.