Friday 4 November 2011

Android Annoyances: RadioGroup

I have a RadioGroup with two RadioButtons in it. In the code, I want to know which of the buttons was selected. Here is the way to find out that information using Android API:

int index = group.indexOfChild(group.findViewById(group.getCheckedRadioButtonId()));

Pure elegance…

Tuesday 25 October 2011

Android Annoyances: Text Length

It is incomprehensible to me why there are properties that you can set in an XML attribute but not in code. Here is one quite obvious example.

I have an EditText control for text input and I want to limit the length of input to just two characters. No problem, I can do that easily in XML layout:

android:maxLength="2"

The problem is: in some circumstances I want to limit input to only 1 character, and can only do that in code. Surely enough, if there is such an XML attribute, there should be a setMaxLength() method, right? Wrong. The guys who designed Android API just didn’t think it might be needed.

Rubbish.

Saturday 22 October 2011

Quartz 2D Article

When developing for iOS, a few times I was working on a bespoke graph, either copying a design created by someone else or implementing strict design guidelines. I decided to share the experience I've gained then in a series of articles. Here they are:

Part 1. Preparing the environment, drawing the grid lines.
Part 2. Drawing a bar graph, with gradient fill.
Part 3. Drawing a line graph, with gradient fill.
Part 4. Making graphs interactive.
Part 5. (to be published soon) Drawing text on graphs (labels etc).

Sunday 9 October 2011

GWT, GXT and Compilation Problem

I found an excellent book that finally explained me the differences between a number of extensions to Google Web Toolkit, and served as an excellent introduction into Ext GWT, a.k.a. GXT.

I started playing with the framework, and it is powerful and beautiful. It seemed to be quite sluggish when developing locally, but when deployed to the server it works much better, I don’t see any problems with performance.

However, my first attempt to deploy my project to the AppEngine wasn’t successful, I’ve got a rather esoteric error message:

java.lang.IncompatibleClassChangeError: Found interface com.google.gwt.core.ext.typeinfo.JClassType, but class was expected

Fortunately, there is already a raised issue for this. It looks like after GWT reached version 2.2, a number of other solutions became incompatible with it, and that seems to be the case with GXT as well.

The solution was to downgrade GWT to version 2.1. Then I had to replace this line of code in the project’s module:

<inherits name='com.google.gwt.user.theme.clean.Clean'/>

with this one:

<inherits name='com.google.gwt.user.theme.standard.Standard'/>

After this, the project has deployed successfully. However, today I tried to run it locally, and GWT plugin in the browser can’t connect to the local server. I guess the reason is that I downgraded the GWT itself but haven’t downgraded the plugin. A bit of a mess.

I’ll need to tell the GXT folks about this problem when I have more time.

Friday 7 October 2011

Android Annoyances: Layout Rules

Quite often, working with Android, I have a strong feeling that a method is missing that actually should exist in the API. Say, there can be a getter but no setter. In some cases, I understand that the property I am trying to change is read-only, but in the other cases there is an impression that someone who was designing the API just didn’t spend enough time thinking on it.

Here is one of the recent stories.

Android doesn’t give us many opportunities for controlling the positioning of views and controls. This is understandable: taking into account the wide array of screen sizes and densities, we’d better trust the automatic layout and pray that it does something good for us. However, we can still achieve quite a lot by manipulating layout parameters, and RelativeLayout is probably the most helpful in this respect.

RelativeLayout.LayoutParams method offers us a couple of useful methods:

addRule(int verb)
addRule(int verb, int anchor)

Using them, we can dynamically, in the code, put a view on top of another view, or align it, say, to parent bottom.

Great, so we can add a rule that we need. Surely, there should be a possibility to remove the rule that we don’t need anymore, right? Say, we’ve aligned a view to parent bottom first, but then we want to place it above another view. We might try to do it like this:

params.addRule(RelativeLayout.ABOVE, R.id.someview);

But this won’t work: the view will stay aligned to the parent bottom. There should be a method to remove a rule that was added - but go try to find it in the API. It doesn’t exist.

Quite typically, Android still leaves us a possibility to achieve what we want but at the price of writing some ugly code - and spending time to discover that ugly solution. Here is how I managed to remove the rule that I don’t need anymore:

params.getRules()[RelativeLayout.ALIGN_PARENT_BOTTOM] = 0;

If you know a better way, please let me know.

Tuesday 27 September 2011

Android Annoyances: Finding a View Size

I find Android development a lot more time consuming than iOS development of similar complexity, and the two main reasons for this are the unintuitive API and poor documentation. Here is one simple example.

You can create an Android user user interface either declaratively, in an XML layout, or in code. This works fine in many cases, but at some point you’ll want to do something more creative, for example to modify an existing layout dynamically depending on some options. For this, you’ll probably need to know the sizes and positions of the already existing parts of the user interface.

Considering the wide variability of screen sizes and densities of Android devices, finding out where exactly a view is located and which exactly size does it have should be an easy task, shouldn’t it?

Let’s say, I want to know the height of a view in order to do some adjustments before the user sees the activity. If we check Android online documentation, we’ll find that every View has a method named getHeight(). So this is what we can use, right? The comment says: “Return the height of your view”. Sure, this is exactly what we want.

Let’s create a standard Android project and then modify it a little bit. Here is the layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<TextView  android:id="@+id/hello"
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="@string/hello"
    />
</LinearLayout>

And here is the code of the activity:

public class SizeTestActivity extends Activity 
{
    private View hello;

    @Override
    public void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        hello = findViewById(R.id.hello);

        Log.i("In onCreate", "" + hello.getHeight());
    }
}

If you run this code though, you will discover that the height of the hello view is exactly 0. Hmmmm… Okay, Android needs some time to complete the layout, it is probably just not ready to report a view’s dimensions yet. But surely, there is a life cycle method that runs a bit later and in which we should be able to find out the view’s height. Let’s look into the documentation again.

We’ll find that the next method that runs after onCreate is onStart, and it is “Called when the activity is becoming visible to the user.”. Surely, the layout should be completed by then, and we’ll certainly find the view’s height in that method. Let’s add it to the activity:

@Override
public void onStart()
{
    super.onStart();

    Log.i("In onStart", "" + hello.getHeight());
}

Run the app, and you’ll see that the view’s height is… 0.

Okay, but there is still one more lifecycle method that runs before the user sees the interface, it is called onResume, and the documentation says about it: “Called when the activity will start interacting with the user. At this point your activity is at the top of the activity stack, with user input going to it.”. Hey, there is no way the view’s dimensions will still be unknown at that point. Let’s try:

@Override
public void onResume()
{
    super.onStart();

    Log.i("In onResume", "" + hello.getHeight());
}

Guess what you’ll see in the log? 0.

Well, maybe there is something wrong with the view that I am trying to measure? Does it have any height at all? Let’s try this: add to the layout a button:

<Button 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content"
    android:text="Check Size"
    android:onClick="checkSize"
    />

Then add to the activity a method to handle the button’s clicks:

public void checkSize(View v)
{
    Log.i("In checkSize", "" + hello.getHeight());
}

Click the button when the activity is running, and you’ll see that the view’s height is actually 29, not 0. So is there any possibility to know this before the user can interact with the activity? There is actually a solution. It’s a bit ugly, and you’ll need to spend some time searching the forums in order to find it, but it does exist. Modify the onCreate method like this:

@Override
public void onCreate(Bundle savedInstanceState) 
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    hello = findViewById(R.id.hello);

    hello.post(new Runnable() 
    {   
        @Override
        public void run() {
            Log.i("In onCreate", "" + hello.getHeight());
        }
    });
}

You will see that the height is now reported properly, and that line of code in the Runnable runs a split of a second after onResume.

Well, this is exactly what I mean by unintuitive API and poor documentation.

Saturday 10 September 2011

New Website

Finally, I decided to leave the old website Sundraw.ws where it is, with its contents, to use a new domain name for this website, and to create a completely new content here, with an emphasis on my current specialisation, mobile development.

It am planning to keep this blog updated with my findings, discoveries, and any interesting stuff that happens in my life of a Mobile Developer.

Saturday 20 August 2011

Just started...

Finally, I am going to create a proper blog here. The plan is to move here the contents of my website sundraw.ws, which is abandoned for quite a few years now, and then add to it the new content reflecting my new interests and my on-going work in the hustle and bustle of mobile development in London.

Keep in touch!