How to make a LWUIT List to render its items accordingly to each item contents?

127 Views Asked by At

I have a LWUIT List filled with items that represents Flight objects, each Flight item displays its flight number, each of it legs departure and arrival times and the price for a ticket.

Some flights have two legs (a leg meaning a segment of a flight involving a stopover, change of aircraft, or change of airline) so these flight items needs to be rendered with each leg departure time and arrival time along with the code for the origin and destination on each leg.

At first the items with only one leg are rendered normally, but when I scroll the list and the items with more than one leg are beginning to be rendered, the items are rendered wrongly with the information cut and what is worse is that all of the items on the list are affected by this, even the ones with only one leg.

In this screenshot you can see how the list items look before reaching the items with more than one leg:

Flight item with only one leg being rendered normally

Then when I scroll the List and reach the items with more than one leg, all of the items are rendered with their leg times information cut and in place the time info of the first item with more than one leg pasted on top of their information:

Flight item with only one leg but has its information cut and replaced with the same information as the first flight with more than one leg

Below I provide my List Renderer class:

package com.yallaya.screens.elements;

import com.dotrez.model.Flight;
import com.dotrez.model.Segment;
import com.sun.lwuit.Component;
import com.sun.lwuit.Container;
import com.sun.lwuit.Font;
import com.sun.lwuit.Label;
import com.sun.lwuit.List;
import com.sun.lwuit.layouts.BoxLayout;
import com.sun.lwuit.list.ListCellRenderer;
import com.yallaya.Main;

/*
 * Renderer for a List of Flights to display
 */
public class FlightItem extends Container implements ListCellRenderer {

    /*
     * Components for this List Item
     */
    private Label flightNumberLbl = new Label("");
    private Label origin1Lbl = new Label("");
    private Label destination1Lbl = new Label("");
    private Label origin2Lbl = new Label("");
    private Label destination2Lbl = new Label("");
    private Label priceLbl = new Label("");

    /*
     * Constructor for this List Item
     */
    public FlightItem() {

        this.setLayout(new BoxLayout(BoxLayout.Y_AXIS));
        this.getStyle().setBgColor(0xf0f0f0);
        this.getStyle().setBgTransparency(255);
        this.getStyle().setMargin(0, 0, 0, 0);
        this.getStyle().setPadding(5, 5, 0, 0);

        flightNumberLbl.getStyle().setMargin(14, 0, 0, 0);

        origin1Lbl.getStyle().setPadding(0, 0, 24, 0);
        origin1Lbl.getStyle().setMargin(0, 0, 0, 0);

        destination1Lbl.getStyle().setPadding(0, 0, 24, 0);
        destination1Lbl.getStyle().setMargin(0, 0, 0, 0);

        origin2Lbl.getStyle().setPadding(0, 0, 24, 0);
        origin2Lbl.getStyle().setMargin(0, 0, 0, 0);

        destination2Lbl.getStyle().setPadding(0, 0, 24, 0);
        destination2Lbl.getStyle().setMargin(0, 0, 0, 0);

        priceLbl.getStyle().setPadding(0, 0, 24, 0);
        priceLbl.getStyle().setMargin(14, 0, 0, 0);
        priceLbl.getStyle().setFont(Font.createSystemFont(Font.FACE_SYSTEM, Font.STYLE_BOLD, Font.SIZE_MEDIUM));

        this.addComponent(flightNumberLbl);
        this.addComponent(origin1Lbl);
        this.addComponent(destination1Lbl);
        this.addComponent(origin2Lbl);
        this.addComponent(destination2Lbl);
        this.addComponent(priceLbl);

    }

    public void updateColorItem(boolean isSelected){
        if(isSelected){
            this.getStyle().setBgColor(0x9a3d96);
            flightNumberLbl.getStyle().setFgColor(0xffffff);
            origin1Lbl.getStyle().setFgColor(0xffffff);
            destination1Lbl.getStyle().setFgColor(0xffffff);
            origin2Lbl.getStyle().setFgColor(0xffffff);
            destination2Lbl.getStyle().setFgColor(0xffffff);
            priceLbl.getStyle().setFgColor(0xffffff);
        }
        else{
            this.getStyle().setBgColor(0xffffff);
            flightNumberLbl.getStyle().setFgColor(0x9a3d96);
            origin1Lbl.getStyle().setFgColor(0x555555);
            destination1Lbl.getStyle().setFgColor(0x555555);
            origin2Lbl.getStyle().setFgColor(0x555555);
            destination2Lbl.getStyle().setFgColor(0x555555);
            priceLbl.getStyle().setFgColor(0x555555);
        }
    }

    /*
     * Functions called to render this List Item
     */
    public Component getListCellRendererComponent(List list, Object value, int index, boolean isSelected) {

        Flight tmp = (Flight) value;
        int displayIndex = index + 1;
        flightNumberLbl.setText(displayIndex +  ". " + Main.localize("VUELO") + " #" + tmp.getFlightNumber());
        Segment tmpSeg = (Segment) tmp.getSegments().elementAt(0);

        String originStr = Main.localize("SALIDA") + " " + "(" + tmpSeg.getOrigin().getCode() + ")" + ": " + tmpSeg.getDepartureTimeString();
        String destinationStr = Main.localize("LLEGADA") + "(" + tmpSeg.getDestination().getCode() + ")" + ": " + tmpSeg.getArrivalTimeString() + "";

        origin1Lbl.setText(originStr);
        destination1Lbl.setText(destinationStr);

        if(tmp.getSegments().size() > 1){

            tmpSeg = (Segment) tmp.getSegments().elementAt(1);

            originStr = Main.localize("SALIDA") + " " + "(" + tmpSeg.getOrigin().getCode() + ")" + ": " + tmpSeg.getDepartureTimeString();
            destinationStr = Main.localize("LLEGADA") + "(" + tmpSeg.getDestination().getCode() + ")" + ": " + tmpSeg.getArrivalTimeString() + "";

            origin2Lbl.setText(originStr);
            destination2Lbl.setText(destinationStr);
        }
        /************************************************************************/
        /******************* UPDATE PIECE OF CODE STARTS HERE *******************/
        /************************************************************************/
        else{
            origin2Lbl.setText("");
            destination2Lbl.setText("");
        }
        /************************************************************************/
        /******************* UPDATE PIECE OF CODE ENDS HERE *******************/
        /************************************************************************/

        priceLbl.setText("$" + tmp.getAdultFare() + " " + tmp.getCurrency().getCode());

        updateColorItem(isSelected);

        return this;
    }

    /*
     * Function called to get this component when it get focus
     */
    public Component getListFocusComponent(List list) {
        return this;
    }

}

In other platforms this problem I believe is called "ghosting" but I haven't found a way to avoid it in LWUIT for Nokia Asha.

I know since the same renderer is used to render all of the items then this could be the cause of the problem, in which case I need a way to render one item differently if required.

How can I avoid for every item in my list to be altered when one of the items must display a different length of information?

EDIT

I updated my code, now if the current Flight object does not have more than one leg then I set the labels for the second leg with empty strings, this solves the problem on the items with only one leg.

So with that I change the topic of my question to the issue that remains on the Flight items with more than one leg, the items are not resized correctly and haven't found a way to adjust each to their contents, all of them are painted the same size.

How to make sure the items height adjust correctly?

EDIT 2

I've tried to alter the height of the renderer inside the if clause where I check how many legs (referred as segments in the model) by using the this.setHeight(800);:

    if(tmp.getSegments().size() > 1){
        .....
        flightHolder.setHeight(800);
        this.setHeight(800);
    }
    else{
        .....
        flightHolder.setHeight(200);
        this.setHeight(200);
    }

but couldn't get a different height size at all with that method.

Then I tried to use this.preferredH(800); and finally got a change in size:

    if(tmp.getSegments().size() > 1){
        ......
        flightHolder.setPreferredH(800);
        this.setPreferredH(800);
    }
    else{
        ...........
        flightHolder.setPreferredH(200);
        this.setPreferredH(200);
    }

but all of the items are rendered with 800, which I guess is due to the last flight having more than one leg but I really don't know, I was hoping setting a bigger height for flights with more than one leg and then resetting to a smaller height for those with only one would work but it seems the height is forced the same on every item, can someone confirm this to me?

1

There are 1 best solutions below

3
On

Okay. Try this:

First you need to declare a global variable to hold the default row height. Then in the constructor do .setPreferredHeight(to that default height global variable).

Now in your:

if(tmp.getSegments().size() > 1){

Set the global variable row height to be *(multiplied) by the number of segments and you should have the correct row height.

You can do similar with the margins/padding, using the number of segments to position the elements accordingly.

I hope this helped and let me know how you get on.

Fenix