webpage repeatedly page when start web is horizontal(Landscape) layout

Hello everybody

I’m create project for web app on android
I’m followed the example project on web site is “http://documentation.xojo.com/index.php/Videos” a title is “Designing a Mobile Web App (January 21, 2014) Example Projects”
if I’m start run layout is vertical(Portrait) does not problem
but if start run layout is horizontal(Landscape) web page repeatedly load

help me please
thank you.

I can confirm, both on an Android phone and an iPhone. When you first load the app while in landscape orientation, it displays the portrait page. This seems to be because the OrientationChanged event doesn’t fire at session startup. It only fires when the device is rotated after the page is loaded. Rotating back and forth works as expected from then on (except upside-down portrait doesn’t work at all - another issue).

But if you refresh the page while in landscape orientation, then the constant reloading occurs. If you then rotate to portrait then back to landscape, then the reloading stops and it works correctly.

It also does this on an iPad (constant reloading when starting off in landscape orientation). However, the upside-down portrait orientation does work correctly.

Seems like the upside-down portrait issue seems to be because smartphones don’t support/allow that mode. Probably to prevent confusion when actually using it as a phone (speaker and mic in proper position).

I couldn’t find anything in Feedback about the constant reloading issue - I’ll work on adding a case.

<https://xojo.com/issue/32374>

When Now there is a way to solve this problem.

I have experienced two issues with iPhone orientation:

  1. If the iPhone is turned upside-down (i.e. Angle=180) then OrientationChanged does not fire. <https://xojo.com/issue/32169> Greg responded that it is expected behaviour as the iPhone does not report the upside-down orientation.

  2. If the user connects to the App with the iPhone in landscape orientation then OrientationChanged does fire but Angle is initially reported as 0, and not 90 or -90. Turning the device to portrait and back again causes the correct angle to be reported. There should be a JavaScript workaround for this but I didn’t find one yet.

The iPad seem to work as expected in both cases.

Would it not be possible to detect initial orientation with page.width and page.height ? Something like

if page.height>page.width then //portrait else //Landscape end if
Just an idea. Not tested.

Hello Michel
I think you would need to get the device width and height using JavaScript and send it back to the server. Page width and height would be the size of the page you are sending to the browser so they would not give you the initial device orientation. Hopefully someone with a better knowledge of JavaScript than mine might be able to offer a solution.

[quote=66957:@Richard Corlett]Hello Michel
I think you would need to get the device width and height using JavaScript and send it back to the server. Page width and height would be the size of the page you are sending to the browser so they would not give you the initial device orientation. Hopefully someone with a better knowledge of JavaScript than mine might be able to offer a solution.[/quote]

I checked on my Mac and reported width and height are actually the size of the browser window. Hence my suggestion. Did not have time to upload a test app, but seems worth a try.

I have been doing some more testing using Paul Lefebvre’s MobileWebApp example project.

  1. Launching the app with the iPhone in portrait orientation, StartUpPage width=320 and height=460. Launching with the device in landscape orientation gives width=320 and height=548, and the iPhonePortaitPage is displayed on its side.

  2. When OrientationChanged fires, it calls a method Session.ShowPage which calls the Show method of iPhoneLandscapePage which in turn causes OrientationChanged to fire again, hence the continuous reloading. This is the problem reported by Wittawat in his original post. It should be easy enough to set a flag to stop the looping.

No, showing a page does not fire the OrientationChanged event - it is (supposed to be) fired by the session in reaction to the physical device orientation changing.

No, then angle is correctly reported at startup. Other factors just made it seem like it wasn’t. See the new example project (below).

The problem appears to be that for a new session, OrientationChanged fires before Session.Open and therefore before the session is ready (or something along those lines), and trying to show a page at this point (session first started) causes a new session to be started. And that cycle will continually repeat. Or it may be something else - only the Xojo engineers can tell us for sure. But I do know that trying to show a page from OrientationChanged during it’s first execution in a new session is where the problem lies.

The reason it was only happening when in landscape mode is the first line in the OrientationChanged event was skipping the rest of the instructions if the angle didn’t appear to have changed. But for a new session, the last saved angle is always going to be zero, so the rest of the instructions do not execute when starting off in portrait. You can make the same bug occur in portrait by removing that first line so that the entire OrientationChanged event runs every time.

The solution (or workaround) is along the lines of what Richard suggested - a flag. I used a flag to prevent the showing of any page from the OrientationChanged event until the session Open event had fired. I also fixed the problem of displaying the correct page no matter which orientation you started in. See the feedback case (<https://xojo.com/issue/32374>) for an updated version of the project that now works (along with logging code that shows the order of the events).

The only way I can see the OrientationChanged event firing in response to a page being shown is if you are using ShowUrl and completely loading the app again.

Something to keep in mind though. You may be able to alleviate the endless loop by keeping track of the last orientation angle in a property and only act on it if it actually changed.

If lastAngle <> angle then
  LastAngle = Angle
  // do something
End If

Paul had included this code in his original example project, but each time OrientationChanged fired, a new session had been launched and so the previous LastAngle property was no longer available. Jay’s workaround fixes this.

I also found that instantiating all the WebPages explicitly avoided this issue of multiple sessions launching repeatedly.

But I am still seeing the initial value of Angle reported as 0 and the page on its side when the app is launched from a landscape orientation. This is with 2013r4.1.

If a web page is being displayed on its side, then even the browser hasn’t recognized the orientation change. There’s not much we can do about that.

FWIW, I’ve been experimenting with this and have not been able to reproduce this on a tablet (iPad or Android). I’m beginning to wonder if, since you a phone is typically in portrait mode when the browser is launched, if this is the expected behavior, and not a bug after all.

I believe it should be possible to get the initial orientation from the device’s body width using JavaScript, but the only code I could find so far seems to be Android-specific.

Unbelievable. An obvious bug that anyone trying to write a mobile-friendly web app is going to encounter. Closed as “not a bug”, and the attachment with workarounds posted to Feedback by @Jay Madren has been removed. How is endlessly refreshing while in landscape mode not a bug?

That could be a path to a workaround.

OK. Long time no see. I tried to implement simple code in Session.OrientationChange to show different pages depending on the value of Angle. I implemented Greg’s idea of having a PreviousAngle property so I do

If PreviousAngle <> Angle then

It does not work. A new session seems to be created each time a landscape webpage is displayed.

I have to seriously question the reason why <https://xojo.com/issue/32374> could be closed as “by design”.

A bug is a bug, is a bug. By design or not.

OK. Here is the workaround I used . I post it here to help the poor souls who stumble on the same issue in the future.

I had already added the PreviousAngle as Integer to the session, which is set in the OrientationChanged Event.

I added a multiple 1000 ms WebTimer to each page (WebPageAndroidPortrait and WebPageAndroidLandscape) with this in the Action event (on WebPageAndroidPortrait) :

Sub Action() Handles Action Dim ref As WeakRef ref = New WeakRef(session) If ref.Value <> Nil Then if Session(ref.Value).PreviousAngle = 90 or Session(ref.Value).PreviousAngle = 90 then WebPageAndroidLandscape.show self.close End If end if End Sub

Of course, the code needs to be modified to PreviousAngle 0 and 180, as well as show WebPageAndroidPortrait for the WebTimer on WebPageAndroidLandscape

I don’t know if this could be implemented, but it would make more sense to have OrientationChanged on webPages, instead of session. Or if “by design”, the OrientationChanged event fired only once, and did not create undue new sessions.