B4J Question [BANano] how to handle orientation change

Dave G

Active Member
Licensed User
I was able to handle orientation change in B4X and VueJS by creating panels/divs with UI views contained in each one and then when the orientation changed I could locate the two panels top and bottom (portrait) or left and right (landscape) to accommodate the usable space.

Thanks
 

alwaysbusy

Expert
Licensed User
Longtime User
It is not so obvious in JavaScript, but you can try to do it with a BANanoMediaQuery.

Something like this: (untested)
B4X:
' globals
Private Portrait As BANanoMediaQuery
Private Landscape As BANanoMediaQuery
...
Portrait.Initialize("(orientation: portrait)")
Landscape.Initialize("(orientation: landscape)")
...
Sub Portrait_Matched()
    
End Sub

Sub Landscape_Matched()
    
End Sub

Alwaysbusy
 
Upvote 0

Dave G

Active Member
Licensed User
With VueJS I created two DIVs, one for the entry fields and one for a grid. When VueJS detects a 'resized' event I perform a function that changes each DIV.
VueJS onresize:
      window.onresize = () => {
          this.resized(window.innerWidth, window.innerHeight)
      }
Code that changes Reactive variable curOrientation used in DIVs
resized function:
    resized(paWidth, paHeight){
      // set if changed
      if (paWidth > paHeight) {
        if (this.curOrientaion != 'L') this.curOrientaion = 'L'
      } else {
        if (this.curOrientaion != 'P') this.curOrientaion = 'P'
        }
    },
The DIV in the Template uses a function to get its Style
Example DIV definition:
  <div id='entryFields' :style="getDivStyle('E')">

The DIVs style change routine:
    getDivStyle: function(theDiv) {
      if (theDiv == 'E') { // entry fields
        if (this.curOrientaion == 'L') {
          return "background-color:black; width:50%; position:absolute; top:40px; left:0;"
        } else
          return "background-color:black; position:relative; left:0;"
      } else { // winch capacity grid
        if (this.curOrientaion == 'L') {
          return "background-color:grey; width:50%; position:absolute; top:40px; left:50%;"
          } else {
          return "background-color:grey; position:relative; left:0;"
        }
      }
    },
Don't know if this ties into what you're suggesting with catching _Matched events and the BANanoMediaQuery.

Thanks
 
Upvote 0

Dave G

Active Member
Licensed User
Ok. Getting the change of orientation events (Matched). Is there a way to group the Views into two separate DIVs and then change the DIVs style as I did with VueJS? Sorry to bother you, I'm hoping this will help others trying to do the same thing.

BTW, here's how I handled this in plain B4X:

Visual Designer = Script using Panels:
'All variants script
AutoScaleAll

If 100%x < 100%y Then
    ' portrait
    Panel1.SetLeftAndRight(0, 100%x)
    Panel2.SetLeftAndRight(0, 100%x)
    Panel1.SetTopAndBottom(0, lblConditions.Bottom + 10)
    Panel2.SetTopAndBottom(Panel1.Bottom, 100%y)
Else
    ' landscape
    Panel1.SetLeftAndRight(0, 50%x)
    Panel2.SetLeftAndRight(Panel1.Right, 100%x)
    Panel1.SetTopAndBottom(0, 100%y)
    Panel2.SetTopAndBottom(0, 100%y)
End If
 
Upvote 0

alwaysbusy

Expert
Licensed User
Longtime User
You can append 2 divs to e.g. the body tag and then load the layouts in them and then do some css to manipulate their position but I wonder why you can't just let the BANanoSkeleton resposive design do its work.

1. Create an SKRow
2. Add 2 SKColumns, each size = 6 columns (half of 12 possible columns)
Note: uncheck the 'Auto ID/Name if you plan to use these columns (panels) in your code
3. Add stuff in each SKColumn

Looks something like this:
1657792814436.png


B4X:
Sub BANano_Ready()
    Dim body As BANanoElement
    body.Initialize("body")
   
    body.LoadLayout("TwoPanels")
End Sub

Now, when the phone is in landscape, both 'panels' will be side by side. In portrait mode, panel 2 will wrap under panel 1.

Alwaysbusy
 
Last edited:
Upvote 0

Dave G

Active Member
Licensed User
You can append 2 divs to e.g. the body tag and then load the layouts in them and then do some css to manipulate their position but I wonder why you can't just let the BANanoSkeleton reposive design do its work.

1. Create an SKRow
2. Add 2 SKColumns, each size = 6 columns (half of 12 possible columns)
Note: uncheck the 'Auto ID/Name if you plan to use these columns (panels) in your code
3. Add stuff in each SKColumn

Looks something like this:
View attachment 131393

B4X:
Sub BANano_Ready()
    Dim body As BANanoElement
    body.Initialize("body")
  
    body.LoadLayout("TwoPanels")
End Sub

Now, when the phone is in landscape, both 'panels' will be side by side. In portrait mode, panel 2 will wrap under panel 1.

Alwaysbusy
Thanks. I'll give it try and let you all know.
Here are examples of B4X (Android phone) version of the Proof of Concept I'm working on. Images are scaled.
AndroidB4XLanscapeSM.jpg
AndroidB4XPortraitSMCrop.jpg
 
Last edited:
Upvote 0

Dave G

Active Member
Licensed User
Not much luck. Copied the existing layout, incorporated it into project, deleted all views, created a row, created two columns (panels), copied top columns from old layout into left panel, copied bottom view into right layout (see screen capture, and got a merged result in browser. The got it to display non-merged by making sure all views were in the Column, but it never shows in portrait with the left panel on top and right panel on bottom. I also did a screen capture of the layout without two panels (columns)
2panels.jpg
2panelsBrowser.jpg
withoutPanels.jpg
 
Upvote 0

Dave G

Active Member
Licensed User
Not much luck. Copied the existing layout, incorporated it into project, deleted all views, created a row, created two columns (panels), copied top columns from old layout into left panel, copied bottom view into right layout (see screen capture, and got a merged result in browser. The got it to display non-merged by making sure all views were in the Column, but it never shows in portrait with the left panel on top and right panel on bottom. I also did a screen capture of the layout without two panels (columns)View attachment 131410View attachment 131411View attachment 131412
I corrected the merged version. The right column/panel had wrong Horizontal Orientation (right arrow vs left arrow). So, now it displays with the two Columns/Panels above and below, not side by side. But, still doesn't change orientation when browser is resized, so it acts the same as my original layout.
 
Upvote 0

alwaysbusy

Expert
Licensed User
Longtime User
Is this one a phone? I ask because on a tablet the 'wrapping' may not kick in because column wrapping in a Responsive Framework in WebApps depends on the screen width. So if e.g. in portrait the screen width is still > x where x is the wrapping point, a responsive framework will still use the landscape mode because everything may still just fit fine. I will have to look at which point the Skeleton framework does start to wrap and maybe we can change that point.

Can you upload the layout file? I'll have a look.

Alwaysbusy
 
Upvote 0

Dave G

Active Member
Licensed User
Is this one a phone? I ask because on a tablet the 'wrapping' may not kick in because column wrapping in a Responsive Framework in WebApps depends on the screen width. So if e.g. in portrait the screen width is still > x where x is the wrapping point, a responsive framework will still use the landscape mode because everything may still just fit fine. I will have to look at which point the Skeleton framework does start to wrap and maybe we can change that point.

Can you upload the layout file? I'll have a look.

Alwaysbusy
It's on desktop, tablet, and phone. I have added code to detect orientation changes"
Added to detect orientation change:
    Private Portrait As BANanoMediaQuery 'Ignore
    Private Landscape As BANanoMediaQuery 'Ignore
...
' handle orientation change
Sub Portrait_Matched()
    LogMsg("Portrait_Matched")
    lblStatus.Text = "Portrait"
    Col2.Element.SetAttr("left", "1")
    Col2.Element.SetAttr("top", "601")
End Sub

Sub Landscape_Matched()
    LogMsg("Landscape_Matched")
    lblStatus.Text = "Landscape"
    Col2.Element.SetAttr("left", "601")
    Col2.Element.SetAttr("top", "1")
End Sub
I added the Col1 and Col2 changes in an attempt to cause the two Columns to change (didn't work). lblStatus shows Portrait or Landscape when I change orientation on any size device. On desktop is resize the browser window and it causes orientation change.

I'll attach the layout with the two large Columns once I figure how to do that.
 
Upvote 0

alwaysbusy

Expert
Licensed User
Longtime User
This is what I would do (updated layout attached to this post):

1. As you use rows within columns, you should wrap these inner rows in an SKContainer (Resize behavior = 100%)
2. Try to use the 'grid' in the abstract designer so there is enough space between each component. This is only in your layout but is needed for the BANano algorithm to determine which custom view is parent from what. (this is a B4J IDE limitation as you can not set the parent of a custom view other than main).
3. for your table, make sure the columns 'No response wrap' is checked
4. The Skeleton library (which is the base of the BANanoSkeleton library) appears to wrap responsive around 550px.
5. I would avoid mixing both the MediaQueries and the Response behavior.

Alwaysbusy

1658132360030.png
 

Attachments

  • WelcomePageLayout2.zip
    6.2 KB · Views: 158
Upvote 0

Dave G

Active Member
Licensed User
This is what I would do (updated layout attached to this post):

1. As you use rows within columns, you should wrap these inner rows in an SKContainer (Resize behavior = 100%)
2. Try to use the 'grid' in the abstract designer so there is enough space between each component. This is only in your layout but is needed for the BANano algorithm to determine which custom view is parent from what. (this is a B4J IDE limitation as you can not set the parent of a custom view other than main).
3. for your table, make sure the columns 'No response wrap' is checked
4. The Skeleton library (which is the base of the BANanoSkeleton library) appears to wrap responsive around 550px.
5. I would avoid mixing both the MediaQueries and the Response behavior.

Alwaysbusy

View attachment 131539
Thanks so much. Will look into it today and let you know.
 
Upvote 0

Dave G

Active Member
Licensed User
Thanks so much. Will look into it today and let you know.
I used your new layout with my app. I eliminated the code that reacted to MediaQueries. It does display the right SKcontainer on the right, but doesn't get repositioned to be under left container when it switches to Portrait. Instead it wraps columns such that the label is above the text fields as it did before. So, on a phone it becomes difficult to read. In regular B4A/I it would move the right panel under the left panel. This may not be possible with BANano, which is okay as this is a Proof of Concept for now.

You put a lot of work into this and I really appreciate it. I've found it difficult to nest a label or text inside the column. The way you did it makes it much easier to select and copy/move rows. I ran into a situation where if I selected a lot of rows with columns, such as my grid, I couldn't drag the entire group so I'd have to use arrow keys to move a little at a time and I did it too quickly I'd get an Out of Memory exception and have to close and reopen the project (I saved the layout every couple of moves so I didn't lose too much.

As mentioned above, I was able to created tight layouts that reacted to orientation in B4X and Vue.js. I haven't been able to create 'tight' (see above) layouts where there is little/no space between Views such that it 'packs' the layout on a narrow device such as a phone. This may be a limitation with BANano that would limit apps with a lot of Views to devices larger than a phone.

Thanks so much,

Dave
 
Upvote 0

alwaysbusy

Expert
Licensed User
Longtime User
This may not be possible with BANano
Works fine here with my layout wrapping the right panel under the left one. No idea why it doesn't for yours. As for the labels, just do the same there as on the right panel and set the 'no responsive wrap' to true.

1658250247592.png


Right panel under left panel.

1658250366942.png


This may be a limitation with BANano that would limit apps with a lot of Views to devices larger than a phone.
It is all a matter of design. BANano itself has no limitations at all and is most of the time a lot more lightweight than vue ones.

Haven't encountered such problems here and we make WebApps more complicated than yours. Key in WebDesign is also: do not fill your screen with to many objects. It only confuses users. I'm a strong believer in Googles Material Design concept. Better to split it up in separate screens.

Note that you can also split your whole design up in multiple layouts:

1. one for the two panels
2. multiple for each row in the left panel ( + you can reuse a lot of them as they are virtually the same)
3. same for the right panel

then it is just a matter of loading the separate layouts into the correct BANanoElements.

Alwaysbusy
 
Upvote 0

Dave G

Active Member
Licensed User
Works fine here with my layout wrapping the right panel under the left one. No idea why it doesn't for yours. As for the labels, just do the same there as on the right panel and set the 'no responsive wrap' to true.

View attachment 131611

Right panel under left panel.

View attachment 131612


It is all a matter of design. BANano itself has no limitations at all and is most of the time a lot more lightweight than vue ones.

Haven't encountered such problems here and we make WebApps more complicated than yours. Key in WebDesign is also: do not fill your screen with to many objects. It only confuses users. I'm a strong believer in Googles Material Design concept. Better to split it up in separate screens.

Note that you can also split your whole design up in multiple layouts:

1. one for the two panels
2. multiple for each row in the left panel ( + you can reuse a lot of them as they are virtually the same)
3. same for the right panel

then it is just a matter of loading the separate layouts into the correct BANanoElements.

Alwaysbusy
Again thanks. I used the layout you sent unchanged. The only thing I can think of is that something in my B4J code is messing this up. I used the standard BANano PWA template to start. I'll look it all over and let everyone know either way. I'll spend some more time with AD to see if I can master controlling the look and feel. Is the a design guide related to using AD e.g. use of Containers, Row, Column, etc?

BTW, the main screen is designed so everything is on one form because they need to see the results (matrix) as they make changes to the criteria (top or left). It was originally designed to be used in high stress situations where seconds count. The criteria screen recalculates the TR value and matrix without them having to click a button, just change a value and hit Tab or select something new from a Combo.

Again, thanks for all of the help. BTW, I'm close to doing a series of post regarding Brower-based B4X apps i.e. BANano. One installments will be all the little things I've learned by trail and error (mostly error) along the way. I'm planning on HTTP/Rest client and servers as well as Web Socket client and servers using the Winch Calc app that I'm in the process of porting to BANano. I'd like to do comparisons between B4X (android, iOS, Java), BANano, Vue.js, and Xamarin.

I've published the Winc Calc app developed with B4X on Google Play Store and Apple App Store back in 2/2020. The newer version I did with Vue and am now doing with BANano is more responsive and easier to use as I'm changing the Label for an Input to let them know what the edit is for the input. BTW, I much prefer BANano to Vue. I do not like the HTML-centric approach of Vue or that it doesn't have something like AD to help in the form setup. I also like that it isn't using some abstract mark up like Xamarin XAML or AXML.

Thanks for an amazing product.

Dave
 
Upvote 0

Dave G

Active Member
Licensed User
I created a fresh BANano PWA project, added the layout you sent to Files, change app to use that, compiled, ran and it doesn't change orientation. So, I'm guessing some b4xlib or jar is different than yours.
 
Last edited:
Upvote 0
Top