Wednesday, February 25, 2009

Multi columns in listView

Hi all,

I read some articles on multicolumn in a list view with android.
As I worked on this subject, I can show you where I could get.

I tried to work on resolution independant list view, so I tried to place the columns relativelyto the screen, rather than relying on absolute coordinates. This way, the result should be correct, whatever the phone ( /notebook ? ) resolution, or whether you are on landscape or portrait mode.

The difficult part is to find the correct layout to pass to your adapter.
My first try was to have a column on the left side and a column on the right side.
Sound easy, but my first tries couldn't make it.

That was my first try for an line layout :



<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
        android:layout_height="wrap_content"
        android:layout_width="fill_parent">
<TextView
        android:id="@+id/PlayerName"
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:text="Nom"
        />
<TextView
        android:id="@+id/PlayerScore"
android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:gravity="right"
        android:text="score"
        />
</LinearLayout>



But it failed... Both entries were stacked on the left of the screen...

I tried both to set the gravity and the layout_gravity to 'right', but it didn't change anything.

The solution was with the width of my second text view. 
I imagine that I couldn't have the two textview width set to 'wrap content', because it couldn't fill a whole line.

So the trick was to have one textView width set to fill parent, the second one to wrap _content, and to have the text placed on the right of the second textView, using the gravity parameter.
But, for some reason, you can't set the first textview width to 'fill_parent'.
I imagine that in this case, the first textview will take all the parent width, and won't let any place for the second one. And when the second textView width is set to 'fill_parent', it will take all the place, but taking into account the space taken but by the first, already initialised, textview.

Here's the working code anyway :


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
        android:layout_height="wrap_content"
        android:layout_width="fill_parent">
<TextView
        android:id="@+id/PlayerName"
        android:textColor="#ffFFffFF"
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:text="Nom"
        />
<TextView
        android:id="@+id/PlayerScore"
android:layout_height="wrap_content"
        android:layout_width="fill_parent"
        android:gravity="right"
        android:layout_marginRight="25dip"
        android:textColor="#ffFFffFF"
        android:text="score"
        />
</LinearLayout>



Just a note : I add a right margin for the second text view, to reserve some space for the listview scrollbar ( without it, the text was behind the scrollbar ) !

Then I tried to have a three columns layout, with one column on the left, one column in the middle, and the last one on the right.
To be honest, I tried anything I could think of in tweaking the precedent code, with no success !

Until I tried to use a relative layout instead of a linear layout !

With a relative layout, the first try was the good one :


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" 
                android:layout_height="wrap_content"
 >
<TextView
        android:id="@+id/Center"
android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:layout_centerHorizontal="true" 
        android:textColor="#ffFFffFF"
        android:text="Center"
        />
<TextView
        android:id="@+id/PlayerName"
        android:textColor="#ffFFffFF"
        android:layout_height="wrap_content"
        android:layout_width="fill_parent"
        android:layout_toLeftOf="@+id/Center"
        android:text="Nom"
        />
<TextView
        android:id="@+id/PlayerScore"
android:layout_height="wrap_content"
        android:layout_width="fill_parent"
        android:layout_toRightOf="@+id/Center"
        android:layout_marginRight="25dip"
        android:textColor="#ffFFffFF"
        android:gravity="right"
        android:text="score"
        />
</RelativeLayout>




Now I still have a question in the back of my mind. 
This reminds me my early web development, where I tried to tweak HTML code to have resoution independant pages. HTML was designed for that !
And some years after that, every serious website is designed to be view in a fixed resolution.

So my question : is it worth it ?
For the moment, only one android device exist, so resolution independance is not a question.
And I feel like all the upcoming phones will have the same resolutions, and that every layout will be design with absolute pixel values... Wait and see ?


2 comments:

malachi said...

Hi. I found this post while trying to design my first android app. At first I needed two columns, so this was perfect, but then the user demanded a third and I switched to a fixed width layout that I found described elsewhere... how unsatisfying.

However, a few days later I found a tip in the android documentation:

Tip: To create a proportionate size layout on the screen, create a container view group object with the layout_width and layout_height attributes set to fill_parent; assign the children height or width to 0 (zero); then assign relative weight values to each child, depending on what proportion of the screen each should have.

That seemed to do the trick for me. I just thought your readers might find it handy if they stumbled across your site looking for a solution like I did.

thanks,
malachi

AndroidBlogger said...

Hi Malachi, and thanks for this tip...

Actually, in this article, I finished with an implementation for 3 columns !
I did it with a different version from yours : I have one column on the left, one on the middle, and one on the right.

The difference is that you can have some content bigger than one third of the screen width :
In my test, I had a name on the left, just a one digit number on the middle ( the level reached) , and a score on the right.
As there is only one digit in the middle column, it is a very small column, and you can have a name bigger than 1/3 of the screen in the left column !
I found it useful, as it was more suited to my problem, but it may not be always the case, so it's nice you made this comment : the reader can now choose the solution best suited for his problem !

And you can also point out that your solution allow to adapt to any number of column, as I am stuck with 3 !

Thanks again !