How to ask user to change orientation to portrait if he/she rotates phone to landscape mode

We have a project in which we cannot display the designs in landscape mode because of its very less height. Our designs in this project need the user to hold the phone in portrait mode. Can we show some sort of a screen overlay to users when the user rotates the phone to landscape mode? When the user returns back to portrait mode the overlay must go away and the scene must display normally.

We have about 12 scenes in the project which need to have this behavior. All our design break in landscape mode because of limited height and it is important for us to inform the user that the site is optimized for portrait mode and that he/she should rotate to portrait mode.

Can someone please write the code in a hype project so we can implement it? This is urgent as we need to deliver the project on a tight deadline. Thanks in advance.

What is the the project is running in. Ie browser, App

browser

@sgibm

I've assembled some links that go over your subject - none of which I've utilized - I'm just the librarian ;->

@DBear's suggestion:


From stackoverflow, some ideas, including detecting device rotation: (as per a [post](http://forums.tumult.com/t/possible-to-disable-landscape-portrait-mode-per-layout/1645/4) by @Daniel in March 2015):
1 Like

thank you for the links. I did check these links prior to my posting here but the code didnt work for me. I tried it on layout load event.

I mean dbear’s technique worked to some extent - it worked only if the scene was loaded in the orientation. If the orientation was changed after the scene was loaded then it didnt work. Nor was there any way for us to revert back to the scene once the orientation was switched back.

I tried this on layout load just to make it work on orientation change but this didnt work. I am not good at coding. Can anyone please check why this didnt work or suggest a way out?

This is the code we wrote within the js function that was being called on layout load:
window.onresize = function (event) {

if (window.innerHeight > window.innerWidth) {
alert(“You are now in portrait”);
} else {

myElement = document.getElementById('form2widget');
myElement.innerHTML = "Please use Portrait Orientation";

}

}

Try this

window.addEventListener("orientationchange", function(e) {
       
       
      if(window.innerHeight < window.innerWidth){
        alert("Please use Portrait!");
    }
        
        
    });

yes this almost works. Except for the fact that we dont need alerts because alerts dont go away when we rotate back to portrait mode. Alerts need to be closed by the user. So the user can close the alert and still see the broken design/site. Conversely, the user can rotate back to portrait mode and still see the alert asking him/her to switch to portrait!

In landscape mode We need a message box (not an alert that can be closed by user by clicking on a button) to tell the user to go to portrait mode but the message box should go away as soon as user rotates to portrait mode. Until then the message cannot be closed by the user.

How would we do that in code?

It's just an example. Put what ever you want there..

i understand. I was hoping you would give me some code that I could plug in to solve my issue. Do you think we should start a timeline which brings in the window on top and then play the reverse timeline when the user rotates to portrait mode.

Any ideas?

Thanks anyways because your reply helped a lot - as usual :slight_smile:

An idea that might help You further along. A text field (“Please Use Portrait Orientation”) with an ID of ‘portraitAlert’ is shown or hidden depending on the orientation…

window.addEventListener("orientationchange", function(e) {
       if(window.innerHeight < window.innerWidth){
        hypeDocument.getElementById('portraitAlert').style.display = "block";
      }   else if (window.innerHeight > window.innerWidth){
        hypeDocument.getElementById('portraitAlert').style.display = "none";
      }   
    });

orientationTest.hype.zip (14.1 KB)

@sgibm

Here is a quick document that I have made just using the layout options to show an overlay when you go to landscape mode. I would also make sure the viewport width is set to device width (in the Document inspector)

forceOrientation.hype.zip (59.1 KB)

You will be able to grasp it as it’s quite basic.

Creating a layout (I chose iPad because these are preset in Hype) I created 2 layouts (Portrait and Landscape) The portrait one I place the content I want users to see (I put this in a persistent symbol so I wouldn’t have to copy and paste. If I change in one it auto updates in the other. Across scenes too)

I then did a quick animation on the landscape one with elements above the rest so that it overlays them. Thus stopping any clicks, etc. This animation will play automatically on device rotation. (Main Timeline runs on layout / scene load) user can do nothing but follow the crude message to turn back. He then gets the portrait mode where he can carry on. I have added another scene (duplication) so you can see the same approach is copied and I just added a few extra message and changed the message on the overlay.

Hope this helps!

1 Like

@DBear… Utilizing a visual block is a nice touch.

Thank you @JimScott

@sgibm Here is another example cause I’m feeling nice. This one makes it a bit easier to use in your project I would guess. It involves the “animation” having it’s own scene and then calling that scene when the orientation changes using the tweaked code examples above.

forceOrientationv2-DBear.hype.zip (35.3 KB)

This is the tweaked (and commented) code for those who are following to see:

    // initialise the scene variable (just in case it's in use somehwere else)
    var scene = "";
		
    // set it to the current scene so we can point to it later
    scene = hypeDocument.currentSceneName();
		
    // Puts the scene name inside the element on screen with a class of "scene-name"
    document.querySelector('.scene-name').innerHTML = scene;
	
    // orientation listener
    window.addEventListener('orientationchange', function(event) {
        if(window.innerHeight < window.innerWidth){
            // shows the alert scene if the orientation is landscape
            hypeDocument.showSceneNamed('alert', hypeDocument.kSceneTransitionPushLeftToRight, 0.3)
        } else if (window.innerHeight > window.innerWidth) {
            // changes back to the portrait orientation and shows the scene we recorded earlier so the same code can be used every scene.
            hypeDocument.showSceneNamed(scene, hypeDocument.kSceneTransitionRightToLeft, 0.3)
        }
    });

Add this to a new function and run on scene load wherever you need to detect and alert on change.

Thanks @DBear and @JimScott

I liked @DBear's solution because i dont have to add elements to every scene but @JimScott's version could be workable too - i have to try it.

I tried @DBear 's code and it worked like a charm. The only issue - and it is a big issue for me - is that if the device is already in landscape mode when the scene is loaded then it fails - the alert scene is not run. I tried to put the if-then condition in the function but it still breaks. I know I must be doing something stupid in my code but i cant figure out. Here is what i tried:

  var scene = "";
  
  scene = hypeDocument.currentSceneName();
  
  console.log(scene);
  
  document.querySelector('.scene-name').innerHTML = scene;

  window.addEventListener('orientationchange', function(event) {
  	if(window.innerHeight < window.innerWidth){
  		hypeDocument.showSceneNamed('alert', hypeDocument.kSceneTransitionPushLeftToRight, 0.3)
  	} else if (window.innerHeight > window.innerWidth){
  		hypeDocument.showSceneNamed(scene, hypeDocument.kSceneTransitionRightToLeft, 0.3)
  	}

	});
	
	if(window.innerHeight < window.innerWidth){
  		hypeDocument.showSceneNamed('alert', hypeDocument.kSceneTransitionPushLeftToRight, 0.3)
  	} else if (window.innerHeight > window.innerWidth){
  		hypeDocument.showSceneNamed(scene, hypeDocument.kSceneTransitionRightToLeft, 0.3)
  	}

Any ideas how to resolve this issue?
Is this issue because we are recursively calling scenes within scene load function? Should we use another eventlistener instead of directly loading other scenes within scene load functions?

@sgibm
I ran into the same problem with all of these approaches... but You didn't mention it as an issue for You until now. My assumption is that the listener is listening for a "change" in orientation. If the device starts out in landscape orientation there is no change to register, so the code does nothing.

As a work around I just simply fired the core aspect of the code_(window.innerHeight < window.innerWidth...)_
in the "On Scene Load". Problem: the code then runs for Desktops, etc. So you would need to check to see what device~user-agent before running the code.

Edit:
I reinserted the code again into "On Scene Load" (separate function) it works fine on initial load. Here is some info about testing for mobile devices.

if(window.innerHeight < window.innerWidth){
hypeDocument.getElementById('portraitAlert').style.display = "block";
} else if (window.innerHeight > window.innerWidth){
hypeDocument.getElementById('portraitAlert').style.display = "none";
}

Yes - if we just use the code without the listener for orientation change then it works initially but stops working for change in orientation by user later. The challenge is to make both things work simultaneously which for some reason does not work if i handle it the way i did in my code. In my code i added the if-then construct in addition to the event listener and it breaks. What do you think is causing that code to break? Maybe @DBear or @MarkHunte have some clue?

@sgibm

Here is my test piece that I’ve been using for this topic: orientationTest_v2.hype.zip (17.2 KB)

Both the initial check for orientation & the event listener are in the “Scene Load” handler. I’ve only used one scene in this trial. I will create a 2nd scene later to see if the functionality is impaired, right now I’m out of time.

Note: There are also some buttons in this project as part of another experiment, but it doesn’t impact the working result.

Hi @sgibm

Good catch on that bug. Here is another tweaked version of the code.

2 things.

  1. Create a New function (on Scene Load) and in it place the following:
V=0;

Basically we are creating a variable and initialising it to zero. I have used “V” for variable. It can be whichever letter you want.

  1. Create (or change the one you have) another function and in it put:

// take the original conditional and place it outside the listener and add on the condition "V==0". This is to stop it firing infinitely. Also add another condition the checks if the innerWidth is less than 1200 (for example) to stop it firing on a desktop.
if (window.innerWidth > window.innerHeight && window.innerWidth < 1200 && V==0) {
        hypeDocument.showSceneNamed('alert', hypeDocument.kSceneTransitionPushLeftToRight, 0.3)
    // Now increase the variable by 1 thus breaking the "loop"
        V++;
}

// here we have the original listener only we are gonna reload the scene (document)
window.addEventListener('orientationchange', function() {

    // every time we change orientation the scene will reload therefore firing this overall function all over again and the other function where the variable is initialised back to zero.
    location.reload();

});

This will take into account the innerWidth and innerHeight from the start thus checking the orientation and if it starts in landscae mode the conditional will play the “alert” scene. If it starts in a portrait position then it will do nothing.

3 Likes