Master/detail layout is not handled correctly when app starts in portrait mode

52 views
Skip to first unread message

P5music

unread,
Sep 29, 2020, 5:07:50 AM9/29/20
to CodenameOne Discussions
My codename app has master/detail layout.
A TableLayout is used for that, in landscape mode.
It is used also in portrait mode with different proportions.

If the app starts in landscape mode, the master and the detail are visible, and subsequent orientation changes are handled correctly and the user interface is succesfully reconstructed.

If the app starts in portrait mode, only the master is visible by design (that's OK) but after the orientation change the user interface is not reconstructed completely
because
the master is just at full size, while the detail is not reconstructed.

This is the code of a method that is called at startup and when orientation changes:

private void setContainers()
{
    mainEditingContainer.remove();

//these lines are to handle fab correctly
    if (fabBoundContainer!=null) fabBoundContainer.remove();
    if (fabFirstTime) {fabBoundContainer=fab.bindFabToContainer(itemListContainer);}


//mainForm.setLayout(BoxLayout.x()); not useful to reset the TableLayout

//the issue is present also without these revalidations
    mainEditingContainer.revalidate();
    editingContainer.revalidate();
    fabBoundContainer.revalidate();   
    mainForm.revalidate();

    if (isPortrait() && conditions)  //not relevant here
    {
        new EditingForm(appData,myData,mainForm,editingContainer,other parameters).show();
      }

    if (isPortrait() && !(conditions)) { // only the master in this mode
        //tl=new TableLayout(1,2);         not useful
        //mainForm.setLayout(tl);         not useful

        mainForm.add(tl.createConstraint().heightPercentage(100).widthPercentage((int) (1 * 100)), fabBoundContainer);
    }

    if(isTablet() && !isPortrait() ) {    //master-detail in landscape mode
        //tl=new TableLayout(1,2);    not useful
        //mainForm.setLayout(tl);    not useful
        
        mainForm.add(tl.createConstraint().heightPercentage(100).widthPercentage((int) (leftContainerRatio * 100)), fabBoundContainer).add(mainEditingContainer);
    }

    mainEditingContainer.revalidate();
    editingContainer.revalidate();
    fabBoundContainer.revalidate();
    mainForm.revalidate();

    if (fabFirstTime) fabFirstTime=false;
}

Some commented lines are with some tentative workaround but not successful.

What's wrong? How can I achieve the complete reconstruction of UI in landscape mode, when the app is started in portrait and then rotates? 
I remind you that if the app starts in landscape mode, there are no issues at any subsequent device rotation (just a BrowserComponent is not resizing, this will be addressed separately).
Thanks in avance

Shai Almog

unread,
Sep 29, 2020, 11:23:37 PM9/29/20
to CodenameOne Discussions
It's hard to tell from the code. The "not relevant here" code looks very suspicious though.

Did you try just stepping over this in the debugger with the simulator?
I assume you reproduced it there so just step over the lines and see what's going on. Are the components physically added but not visible?
Are they added to the wrong location or not sized correctly?

P5music

unread,
Sep 30, 2020, 4:19:39 AM9/30/20
to CodenameOne Discussions
Forget the "not relevant" part, because conditions are not satisfied for it to be executed.

What I experience is that
when the app starts in landscape mode (simulator was intentionally left in that state)
the user interface correctly displays just the master container at full screen (so the detail container is not added yet)
if I juggle with orientation changes the two modes correctly alternate

but the app starts in portrait mode (simulator was intentionally left in that state)
when an orientation change occurs
and now the simulator is in landscape mode
(containers are removed)

I see that the master detail TableLayout is not working because just the master container is at full screen.
if I juggle with orientation changes nothing changes.
Debug shows that the right code is executed at orientation change, that is
  if(isTablet() && !isPortrait() ) 
{
...
}

If I step into, I see that mainForm has BorderLayout and not TableLayout:
CallingForm[x=0 y=0 width=2048 height=1534 name=null, layout = BorderLayout, scrollableX = false, scrollableY = false, components = [Container, Toolbar], title = Label[x=0 y=47 width=1536 height=0 name=null, text = , gap = 2], visible = true]

but at startup this is executed (I tried also executing it every time, see commented lines) 
tl=new TableLayout(1,2);
mainForm.setLayout(tl);
mainForm.setScrollable(false);

I see also 
Exception in thread "AWT-EventQueue-0" Failed to get location on screen:component must be showing on the screen to determine its location
in the console after the execution of the method.

Shai Almog

unread,
Sep 30, 2020, 11:07:45 PM9/30/20
to CodenameOne Discussions
So this must be the problem.
I guess border layout is what you use when in landscape and you don't update it when moving to portrait. It's hard to tell but you can just override form.setLayout() with a call to super. Then place a breakpoint there to see who invokes it.

P5music

unread,
Oct 1, 2020, 4:28:43 AM10/1/20
to CodenameOne Discussions
Sorry, but the problem arises only when the app starts in portrait mode, and then an orientation change occurs.
However, even if the problem does not arise when starting in landscape mode,
layout is set as TableLayout at startup in both cases (or even set every time the method above is called, in a different version). 
And whatever instruction I add to set the layout it is not changed, it stays BorderLayout.
Overriding setLayout shows that nothing strange is happening, but the layout is not set.
What is going on with that form?


Shai Almog

unread,
Oct 3, 2020, 12:53:07 AM10/3/20
to CodenameOne Discussions
I have no idea. If you have a reproducible problem you can extract to a test case I can run please file an issue and embed the test case in the issue.
I'll have a look.

P5music

unread,
Oct 3, 2020, 3:50:14 AM10/3/20
to CodenameOne Discussions

P5music

unread,
Oct 8, 2020, 6:37:29 AM10/8/20
to CodenameOne Discussions
The issue is now closed because it was not even to be opened. It has some code that reproduces the issue of this thread.
Have you tested and reproduced the issue?
Can you provide a solution for this thread?

Shai Almog

unread,
Oct 8, 2020, 11:54:46 PM10/8/20
to CodenameOne Discussions
I ran it but couldn't reproduce the issue. The same component always takes over the entire screen. I obviously had to make changes to the code since the sample wasn't self contained.

P5music

unread,
Oct 9, 2020, 2:16:53 AM10/9/20
to CodenameOne Discussions
So in your case the issue is even worse, if I understand. Isn't it?
If "the same component always take the entire screen" you do not even see the master detail splitting of the screen if starting in landscape mode, which I can see. If you start in portrait mode and just see the same component always taking the entire space after rotating then you clearly see the issue.
The containers are not important, because the issue is clearly present if you start in portrait mode and then rotate the device.
So what can be done?
Thanks

Shai Almog

unread,
Oct 10, 2020, 1:42:32 AM10/10/20
to CodenameOne Discussions
I re-ran it and I was able to see what you're describing. In my case this didn't work because leftContainerRatio was 1.33.

P5music

unread,
Oct 10, 2020, 4:00:47 AM10/10/20
to CodenameOne Discussions
Ok, now it is solved.
I was calculating the ratio only at startup but after rotation it was not updated.
Thank you
Reply all
Reply to author
Forward
0 new messages