Android Question Why does this app layout fail in split screen?

agraham

Expert
Licensed User
Longtime User
I am trying to make an app adapt to split-screen mode, which is by default approximately square on my Android 10 Xaiomi Mi Max 3 but it doesn't work as I expect - perhaps I expect wrong!

It only ever loads the landscape or portrait variants, even when in split screen mode.

Also if you hold the device in portrait mode with this app as the top split-screen app and reduce the vertical height of the app by pushing the splitter bar up then the layout remains the portrait layout but the anchoring of the lower buttons fails and they are not shown.

Maybe it's me but I don't get this at all :(
 

Attachments

  • SplitScreenTest.zip
    9.6 KB · Views: 97

Erel

B4X founder
Staff member
Licensed User
Longtime User
Use as few as possible variants. Better to use anchors and designer script.
It only ever loads the landscape or portrait variants, even when in split screen mode.
It does change here between landscape and portrait when I change orientation in split mode. The orientation is just one factor, there are other factors that will affect the chosen variant.

Also if you hold the device in portrait mode with this app as the top split-screen app and reduce the vertical height of the app by pushing the splitter bar up then the layout remains the portrait layout but the anchoring of the lower buttons fails and they are not shown.
This is how the OS behaves. It doesn't update the activity size all the time. There are several "stop points".
 
Upvote 0

agraham

Expert
Licensed User
Longtime User
It does change here between landscape and portrait when I change orientation in split mode
I know it does, but I expect it to load the squarer split screen variant in split screen mode but it never does. I want a totally different view layout for the squarer split-screen mode with some views not visible but I will be reduced to having to do this programatically which is going to be very clumsy. I am on the verge of throwing this bl..dy thing out of the widnow and curling up ready to die!
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
The "activity" size will not be an exact square so the variant chooser will give some penalty score to the square variant.

Add this designer script:
B4X:
Button1.Text = 100%x
Button2.Text = 100%y
Change the square size to 320 x 322 (or the opposite for landscape).

However I will repeat that the less variants you use, the better.
 
Upvote 0

agraham

Expert
Licensed User
Longtime User
Change the square size to 320 x 322 (or the opposite for landscape).
Nope, nothing I can do persuades it to open the split screen layout. In split screen portrait mode the size is 1080 x 814 and even setting a layout of that exact ratio, 320 x 241, does not make it load that layout.
However I will repeat that the less variants you use, the better.
In general I agree but I think that the three aspect ratios of portrait, landscape and squarish should all be capable of having their own layouts automatically loaded which I seem unable to do. In particular the split screen squarish mode, being only half the area of the other two warrants having its own unique layout.
 
Last edited:
Upvote 0

agraham

Expert
Licensed User
Longtime User
My frustration was blinding me to an obvious solution. This is a rough hack for the device held in portrait mode and it works nicely, reverting to the portrait layout if you stretch the app in split screen mode.
B4X:
    Dim aspect As Double = Activity.Width / Activity.Height
    If aspect > 1 Then
        Activity.LoadLayout("Layout2")
    Else
        Activity.LoadLayout("Layout1")   
    End If
 
Upvote 0

agraham

Expert
Licensed User
Longtime User
I think this is why LoadLayout will never load a split screen sized variant.
Java:
public float calcDistance(LayoutValues device) {
    ...
    float sameOrientation = ((Math.signum(w - h) == Math.signum((device.Width - device.Height))) ? false : 100);
    return Math.abs(w - device.Width) + Math.abs(h - device.Height) + 100.0F * Math.abs(this.Scale - device.Scale) + sameOrientation;
It is always comparing the layout size to the device values but in split screen mode the variant size for either width or height are effectively half of the device size so either a portrait or landscape sized variant will always take precedent.
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
That's true. It chooses the variant based on the device size. This is important when you load layouts to smaller panels, for example as list items.

I can only repeat again that you should use as few as possible variants. This is a feature that was introduced before anchors and designer script were available. It wouldn't have been added if the other two were already available.
 
Upvote 0

agraham

Expert
Licensed User
Longtime User
I can only repeat again that you should use as few as possible variants.
I can only repeat again that I agree with you in general. However for split screen and other forthcoming foldable devices an app can find itself in quite a wide variety of sizes and aspect ratios and will have to adapt itself to a wide range of available display areas. While I haven't fully analysed the above code I think, in practice, in any one layout on any single device only one portrait and one landscape variant can ever be chosen. I'd like to be wrong!

As you can probably tell from my recent posts I have been adapting my flagship mapping program app to work in split screen which, owing to the density of controls in normal portrait and landscape modes, requires only a differently laid out subset of the normal views to be available in order to be usable. As the present layout variant detection will never be able to load a split screen variant the only alternative is to programmatically detect whether split screen mode is in use and load an entirely different layout. I foresee a similar problem when a foldable is used when the effective device size will double when an app is stretched across the entire display area and may want to take advantage of the extra space.

I guess that in theory a designer script should be able to detect that it is a split screen size and aspect ratio and adjust things accordingly. I haven't considered this up to now so I shall have a play at doing this.

As an aside split screen in Android 10, where both apps can be active at the same time, is impressively useful on a large screen device! I have had two mapping apps, mine and AlpineQuest displaying simultaneously, both GPS tracking and moving the maps, one a 50K overview and the other a detailed 10K street level view. It is less impressive on earlier devices where only one of the apps can be active.
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
I guess that in theory a designer script should be able to detect that it is a split screen size and aspect ratio and adjust things accordingly. I haven't considered this up to now so I shall have a play at doing this.
It should work.
Don't miss the ActivitySize keyword which returns the container size in inches.

There is also nothing bad with creating two layout files in this case.
 
Upvote 0

agraham

Expert
Licensed User
Longtime User
Let me have a more precise attempt at articulating my concern now I have looked a bit deeper. I may still be talking nonsense of course, but it's better informed nonsense!

My concern was not being able to add a variant for an Activity in a layout file that could be chosen by LoadLayout in split screen mode.

It looks to me as though LoadLayout always checks for variant matches using Device LayoutParams (even for Panels and other Views which puzzles me, but I know that I don't fully understand how layouts work). From solving a coordinate problem in ScaleImageView in split screen mode I wonder if LoadLayout should be using the LayoutParams of the Window that the Activity is in instead of the Device. This should then allow the smaller variant suitable for the reduced size window to be identified and loaded otherwise it will always be discarded because it is much smaller than the normal landscape and portrait variants which will always better match the full device screen.

This is prompted by the fact that the co-ordinate adjustment I had to make in ScaleImageView was to offset my co-ordinate values relative to the Window the Activity was in and not to the Screen as I did originally. Otherwise ScaleImageView functioned correctly when in the top or left part of a split screen but not in the bottom or right part.
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
It looks to me as though LoadLayout always checks for variant matches using Device LayoutParams
True. This is by design.

Note that anchors and designer script are based on the container. It is only the variant selection algorithm that is based on the device screen.
I'll give you an example that will explain the reasoning behind it:
You are creating an app with xCLV. The best way to create the list items layouts is with the designer. The items container will be wide and short as these are list items. Still you can use different variants for tablets and phones or for portrait and landscape. There is mostly no relation between the container size and the overall layout.
Without making things more confusing it is also relevant to AutoScaleAll which scales the layout based on the variant size compared to the device size.

Even if you are not convinced:
1. It will never change as it will break many apps.
2. You should use anchors and designer script anyway.
 
Upvote 0

agraham

Expert
Licensed User
Longtime User
1. It will never change as it will break many apps.
I understand that
2. You should use anchors and designer script anyway.
You can't for a split screen layout unless designer script can somehow tell that it is not laying out the full size portrait or landscape variant but only a subset of it. By itself ActivitySize means nothing without a device size to compare it to. Having a DeviceSize keyword in designer script would help, as would having some more arithmetic functions like Pow(n1,n2) which would let you calculate diagonals. You could check the aspect ratio by 100%x/100%y and guess that you were in split screen mode but a SplitScreen keyword, like Landscape, would be better.
 
Upvote 0

agraham

Expert
Licensed User
Longtime User
The container is resized in split screen mode so anchors should work.
Sorry, I don't see the relevance of this to the conversation. I know they work. I've used them in the example in my split screen tutorial. The issue is, because for any given device we only ever get one portrait or one landscape variant selected in a layout file whether in split screen or not, identifying in the designer script that we are in split screen so we can position and display only a subset of the views appropriate to the smaller area we have to play with.

At this time I guess I just make a separate layout file for the splits creen variant and choose which to load programmatically. I was hoping to be able to cope with it in one layout file with variants as that makes adding and removing views a lot more convenient than maintaining two layout files.
 
Upvote 0

agraham

Expert
Licensed User
Longtime User
There's nothing like an example. Perhaps you will tell me that this is the only way of doing it.

Here is the UI from my mapping program that I want to run in split screen alongside another mapping program. I would ideally like all the variants to be in the Main bal file but at the moment I have to have a separate Square bal layout file as if I put this variant in the Main file it is never selected. In this case the split screen Square layout is similar to the Main portrait layout but note the absence of tglbtnAdjacent which is not needed in split screen as the views it changes are not shown, and its replacement by chkSideBySide which is needed in split screen mode.
 

Attachments

  • SplitScreenLayout.zip
    15.8 KB · Views: 89
Last edited:
Upvote 0
Top