CodenameOne icon indicating copy to clipboard operation
CodenameOne copied to clipboard

RFE: improvement to CN.lockOrientation implementation (with example code)

Open jsfan3 opened this issue 5 years ago • 6 comments

First, I thank Steve for this comment, it was resolutive: https://stackoverflow.com/questions/63256117/changing-the-screen-orientation-lock-on-ios#comment111885399_63269202

I created my own native interface, designed for my specific use case, which makes the screen lock functionality on Android and iOS virtually identical. Until now it hadn't been possible. I copy my code, you can use it for your tests and to evaluate how to modify CN.lockOrientation. My use case is very specific, because it takes into account only two of the four possible orientations on iOS, because it assumes the use of a specific build hint and because it assumes that the app is always locked horizontally or vertically. If you make a change to CN.lockOrientation, however, you will have to take into account all possible cases of use, including the fact that after locking the app in one orientation the developer wants to unlock it completely. My code tests an initial lock to portrait (which is what I'm interested in), I didn't try it to landscape.

I copy my test case with all the files.

build hint: ios.interface_orientation=UIInterfaceOrientationPortrait:UIInterfaceOrientationLandscapeRight

MyApplication.java

    public void init(Object context) {
       [...]

        Log.p("Initially lock the screen orientation to portrait.");
        OrientationLocking.lockToPortrait();
    }

    public void start() {
        if (current != null) {
            current.show();
            return;
        }
        // we assume that the screen is initially locked to portrait
        // build hint: ios.interface_orientation=UIInterfaceOrientationPortrait:UIInterfaceOrientationLandscapeRight
        Form hi = new Form("Test orientation locking", BoxLayout.y());
        hi.getContentPane().setSafeArea(true);
        hi.getToolbar().hideToolbar();
        Button lockPortraitBtn = new Button("Lock to portrait");
        Button lockLandscapeBtn = new Button("Lock to landscape");
        SpanLabel exampleText = new SpanLabel("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam volutpat hendrerit nunc, sed gravida sem rutrum id. Sed volutpat, leo nec consectetur placerat, erat justo posuere nulla, sit amet dignissim felis mauris nec magna. Praesent vestibulum leo in nulla elementum, ut vestibulum diam euismod. Phasellus venenatis vitae risus ac porttitor. Ut nec turpis in nulla imperdiet eleifend. Nam bibendum risus in leo consequat, eu suscipit risus facilisis. Pellentesque porttitor mi in dignissim suscipit. Quisque ac massa vitae sem dapibus bibendum quis sit amet augue. Nulla facilisi. Sed dignissim nulla nec iaculis blandit. Nulla facilisis, neque eget finibus cursus, lorem ex eleifend diam, sed blandit magna justo id odio. Sed cursus lorem non lorem auctor efficitur. ");
        hi.addAll(GridLayout.encloseIn(2, lockPortraitBtn, lockLandscapeBtn), exampleText);
        hi.show();

        lockPortraitBtn.addActionListener(l -> {
            Log.p("Lock the screen orientation to portrait.");
            OrientationLocking.lockToPortrait();
        });

        lockLandscapeBtn.addActionListener(l -> {
            Log.p("Lock the screen orientation to landscape.");
            OrientationLocking.lockToLandscape();
        });
    }

OrientationLocking.java

import com.codename1.io.Log;
import com.codename1.system.NativeLookup;
import com.codename1.ui.CN;

/**
 * Orientation locking
 */
public class OrientationLocking {

    private static boolean isLocked = false;
    private static OrientationLockingNative nativeInterface = NativeLookup.create(OrientationLockingNative.class);

    public static void lockToPortrait() {
        if (CN.isPortrait() && isLocked) {
            Log.p("The device orientation is already locked to portrait");
            return;
        }
        CN.unlockOrientation();
        CN.lockOrientation(true);
        if (nativeInterface != null && nativeInterface.isSupported()) {
            nativeInterface.iOS_RotationToPortrait();
        }
        isLocked = true;
    }

    public static void lockToLandscape() {
        if (!CN.isPortrait() && isLocked) {
            Log.p("The device orientation is already locked to landscape");
            return;
        }
        CN.unlockOrientation();
        CN.lockOrientation(false);
        if (nativeInterface != null && nativeInterface.isSupported()) {
            nativeInterface.iOS_RotationToRightLandscape();
        }
        isLocked = true;
    }

}

OrientationLockingNative.java

import com.codename1.system.NativeInterface;

/**
 * @deprecated
 */
public interface OrientationLockingNative extends NativeInterface {
    
    public void iOS_RotationToPortrait();
    public void iOS_RotationToRightLandscape();
    
}

net_informaticalibera_test_orientationlocking_OrientationLockingNativeImpl.m

#import "net_informaticalibera_test_orientationlocking_OrientationLockingNativeImpl.h"
#import "CodenameOne_GLViewController.h"

@implementation net_informaticalibera_test_orientationlocking_OrientationLockingNativeImpl


-(void)iOS_RotationToPortrait{
    dispatch_async(dispatch_get_main_queue(), ^{
        UIInterfaceOrientation currentOrientation = [UIApplication sharedApplication].statusBarOrientation;
        NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
        [[UIDevice currentDevice] setValue:value forKey:@"orientation"];
        [UIViewController attemptRotationToDeviceOrientation];
    });
}

-(void)iOS_RotationToRightLandscape{
    dispatch_async(dispatch_get_main_queue(), ^{
        UIInterfaceOrientation currentOrientation = [UIApplication sharedApplication].statusBarOrientation;
        NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeRight];
        [[UIDevice currentDevice] setValue:value forKey:@"orientation"];
        [UIViewController attemptRotationToDeviceOrientation];
    });
}

-(BOOL)isSupported{
    return YES;
}

@end

jsfan3 avatar Aug 09 '20 23:08 jsfan3

Hi can I work on this?

bayehyg avatar Jun 02 '24 02:06 bayehyg

@bayehyg go for it. Keep in mind the code changed since the original submission so it might need some adapting. You will need a device and a Mac to test this.

shai-almog avatar Jun 02 '24 05:06 shai-almog

@shai-almog I don't have a Mac, are there other issues I can help with that don't require a Mac?

bayehyg avatar Jun 02 '24 20:06 bayehyg

@bayehyg I suggest going over this list: https://github.com/codenameone/CodenameOne/labels/good%20first%20issue As a general rule of thumb, everything that requires native iOS code would require a Mac to test.

shai-almog avatar Jun 03 '24 05:06 shai-almog

Can you assign to this to me , i can work on this .

Arunodoy18 avatar Nov 12 '25 01:11 Arunodoy18

Thanks. We're no longer seeking contributions for this issue. We're working on improved test coverage to enable this change.

shai-almog avatar Nov 12 '25 02:11 shai-almog