Ich arbeite an einer iPad-App mit AutoLayout. Wenn der Benutzer einen bestimmten Modus aktiviert ("Heads-Up" -Modus), möchte ich nur die Ausrichtung Hochformat (oder umgekehrt) unterstützen, und außerdem, wenn sich das Gerät im Gerät befindet Landschaft möchte ich automatisch in den Hochformatmodus wechseln.
In der Draufsichtsteuerung habe ich Folgendes:
- (NSUInteger) supportedInterfaceOrientations {
if (self.modeHeadsUp) {
return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown;
} else {
return UIInterfaceOrientationMaskAll;
}
}
- (BOOL) shouldAutorotate {
return TRUE;
}
Basierend auf Antworten, die ich hier an anderer Stelle gesehen habe, scheint die Antwort scheint zu sein, dass ich "application setStatusBarOrientation" verwenden sollte. Daher habe ich in der Methode, in der der Benutzer den Modus "Heads-Up" ausgewählt hat, Folgendes hinzugefügt:
UIApplication *application = [UIApplication sharedApplication];
[application setStatusBarOrientation:UIInterfaceOrientationPortrait
animated:YES];
Dies scheint jedoch einfach nichts zu tun. Ich kann das Gerät zwar physisch verschieben, um es in das Hochformat zu drehen, dies geschieht jedoch nicht automatisch.
Wenn Sie nach dem Ausführen des obigen Codes im Querformatmodus versuchen, die Ausrichtung programmgesteuert festzulegen, bleibt beim Abfragen der Anwendung "statusBarOrientation" mit folgendem Code die Landschaft "4":
UIApplication *application = [UIApplication sharedApplication];
int orientation = [application statusBarOrientation];
self.movesTextView.text = [NSString stringWithFormat:@"ORIENTATION %d", orientation];
Es schien, als würde Autolayout möglicherweise nicht mit der setStatusBarOrientation ausgelöst werden. Ich habe also versucht, diesen Code nachträglich hinzuzufügen, ohne dass dies Auswirkungen hatte:
[super updateViewConstraints];
[self.view updateConstraints];
Mir ist klar, dass Apple die Geräteorientierung in den Händen des Benutzers belassen möchte. Ich möchte jedoch den Querformatmodus unterstützen, wenn Sie sich nicht im "Heads-Up" -Modus befinden.
Vermisse ich etwas, um die Orientierungsänderung erzwingen zu können?
Für iOS 7 und 8:
Ziel c:
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft];
[[UIDevice currentDevice] setValue:value forKey:@"orientation"];
Swift 3+:
let value = UIInterfaceOrientation.landscapeLeft.rawValue
UIDevice.current.setValue(value, forKey: "orientation")
Ich nenne es in - viewDidAppear:
.
Benutze das. Perfekte Lösung für das Orientierungsproblem..ios7 und früher
[[UIDevice currentDevice] setValue:
[NSNumber numberWithInteger: UIInterfaceOrientationPortrait]
forKey:@"orientation"];
Sie müssen attemptRotationToDeviceOrientation (UIViewController)
aufrufen, damit das System Ihre supportedInterfaceOrientations
aufruft, wenn sich die Bedingung geändert hat.
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft]; [[UIDevice currentDevice] setValue:value forKey:@"orientation"];
funktioniert, aber Sie müssen zurückkehren, sollten Sie mit YES in Ihrem View-Controller angeben
- (BOOL)shouldAutorotate
{
return self.shouldAutoRotate;
}
Wenn Sie das tun, wird Ihre VC sich automatisch drehen, wenn der Benutzer das Gerät dreht ... Daher habe ich es geändert in:
@property (nonatomic, assign) BOOL shouldAutoRotate;
- (BOOL)shouldAutorotate
{
return self.shouldAutoRotate;
}
und ich rufe an
- (void)swithInterfaceOrientation:(UIInterfaceOrientation)orientation
{
self.rootVC.shouldAutoRotate = YES;
NSNumber *value = [NSNumber numberWithInt: orientation];
[[UIDevice currentDevice] setValue:value forKey:@"orientation"];
}
um eine neue ausrichtung mit einem schaltknopf zu erzwingen. ____. Sollte autoRotate auf NO gesetzt werden, fügte ich meiner rootVC hinzu
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
self.shouldAutoRotate = NO;
}
PS: Diese Problemumgehung funktioniert auch in allen Simulatoren.
Dies funktioniert für mich bei Xcode
6 & 5.
- (BOOL)shouldAutorotate {
return YES;
}
- (NSUInteger)supportedInterfaceOrientations {
return (UIInterfaceOrientationMaskPortrait);
}
Der einzige Weg, der für mich funktioniert hat, ist die Präsentation von Dummy-Modal-View-Controllern.
UIViewController* dummyVC = [[UIViewController alloc] init];
dummyVC.view = [[UIView alloc] init];
[self presentModalViewController:dummyVC animated:NO];
[self dismissModalViewControllerAnimated:NO];
Ihr VC wird nach aktualisierten Schnittstellenausrichtungen gefragt, wenn der Modal-View-Controller geschlossen wird.
Merkwürdig ist, dass UINavigationController genau dies tut, wenn untergeordnete Ansichtscontroller mit verschiedenen unterstützten Schnittstellenorientierungen (Push-to-Popping) auf iOS 6.1, 7.0 getestet werden.
Mit dieser Lösung können Sie eine bestimmte Schnittstellenorientierung erzwingen, indem Sie den Wert von UIDevice.current.orientation
vorübergehend überschreiben und das System dann auffordern, die Schnittstelle entsprechend der Drehung des Geräts zu drehen:
Wichtig: Dies ist ein Hack und könnte jederzeit aufhören zu arbeiten
Fügen Sie im Root-View-Controller Ihrer App Folgendes hinzu:
class RootViewController : UIViewController {
private var _interfaceOrientation: UIInterfaceOrientation = .portrait
override var supportedInterfaceOrientations: UIInterfaceOrientationMask { return UIInterfaceOrientationMask(from: _interfaceOrientation) }
override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation { return _interfaceOrientation }
override func viewDidLoad() {
super.viewDidLoad()
// Register for notifications
NotificationCenter.default.addObserver(self, selector: #selector(RootViewController.handleInterfaceOrientationChangeRequestedNotification(_:)), name: .interfaceOrientationChangeRequested, object: nil)
}
deinit { NotificationCenter.default.removeObserver(self) }
func handleInterfaceOrientationChangeRequestedNotification(_ notification: Notification) {
guard let interfaceOrientation = notification.object as? UIInterfaceOrientation else { return }
_interfaceOrientation = interfaceOrientation
// Set device orientation
// Important:
// • Passing a UIDeviceOrientation here doesn't work, but passing a UIInterfaceOrientation does
// • This is a hack, and could stop working at any moment
UIDevice.current.setValue(interfaceOrientation.rawValue, forKey: "orientation")
// Rotate the interface to the device orientation we just set
UIViewController.attemptRotationToDeviceOrientation()
}
}
private extension UIInterfaceOrientationMask {
init(from interfaceOrientation: UIInterfaceOrientation) {
switch interfaceOrientation {
case .portrait: self = .portrait
case .landscapeLeft: self = .landscapeLeft
case .landscapeRight: self = .landscapeRight
case .portraitUpsideDown: self = .portraitUpsideDown
case .unknown: self = .portrait
}
}
}
extension Notification.Name {
static let interfaceOrientationChangeRequested = Notification.Name(rawValue: "interfaceOrientationChangeRequested")
}
Stellen Sie sicher, dass alle Schnittstellenausrichtungen unter "Bereitstellungsinformationen" überprüft werden:
Fordern Sie Änderungen an der Benutzeroberfläche an, wenn Sie diese benötigen:
NotificationCenter.default.post(name: .interfaceOrientationChangeRequested, object: UIInterfaceOrientation.landscapeRight)
Fügen Sie diese Anweisung in AppDelegate.h
hinzu.
//whether to allow cross screen marker
@property (nonatomic, assign) allowRotation BOOL;
Schreiben Sie diesen Abschnitt in AppDelegate.m
auf.
- (UIInterfaceOrientationMask) application: (UIApplication *) supportedInterfaceOrientationsForWindow: application (UIWindow *) window {
If (self.allowRotation) {
UIInterfaceOrientationMaskAll return;
}
UIInterfaceOrientationMaskPortrait return;
}
Ändern Sie die allowRotation
-Eigenschaft der Delegatenanwendung
Wenn Sie einen UIViewController haben, der im Portrait-Modus bleiben soll, fügen Sie einfach diese Überschreibung hinzu und Sie sind fertig.
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
return UIInterfaceOrientationMask.Portrait
}
Das Beste daran ist, dass es keine Animation gibt, wenn diese Ansicht angezeigt wird. Sie befindet sich bereits in der richtigen Ausrichtung.
Wenn Sie die Hauptansicht Ihrer App für Hochformat sperren möchten, aber Popup-Ansichten in Querformat öffnen möchten und tabBarController als rootViewController verwenden, können Sie diesen Code in Ihrer AppDelegate verwenden.
AppDelegate.h
@interface AppDelegate : UIResponder <UIApplicationDelegate, UITabBarControllerDelegate>
@property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) UITabBarController *tabBarController;
@end
AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Create a tab bar and set it as root view for the application
self.tabBarController = [[UITabBarController alloc] init];
self.tabBarController.delegate = self;
self.window.rootViewController = self.tabBarController;
...
}
- (NSUInteger)tabBarControllerSupportedInterfaceOrientations:(UITabBarController *)tabBarController
{
return UIInterfaceOrientationMaskPortrait;
}
- (UIInterfaceOrientation)tabBarControllerPreferredInterfaceOrientationForPresentation:(UITabBarController *)tabBarController
{
return UIInterfaceOrientationPortrait;
}
Es funktioniert sehr gut.
In Ihrem viewController möchten Sie in Landschaft dargestellt werden, verwenden Sie einfach Folgendes:
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskLandscape;
}
- (BOOL)shouldAutorotate {
return YES;
}
Der Basis-UINavigationController sollte den folgenden Callback haben, damit die untergeordneten Elemente entscheiden können, welche Ausrichtung sie wünschen.
-(NSUInteger)supportedInterfaceOrientations {
UIViewController *topVC = self.topViewController;
return topVC.supportedInterfaceOrientations;
}
-(BOOL)shouldAutorotate {
UIViewController *topVC = self.topViewController;
return [topVC shouldAutorotate];
}
hier ist ein VOLLSTÄNDIGES ARBEITEN-Beispiel für iOS 7, 8, 9, 10, wie Sie die Ausrichtung der App auf ihr aktuelles Gegenteil ändern
Ziel c
- (void)flipOrientation
{
NSNumber *value;
UIInterfaceOrientation currentOrientation = [[UIApplication sharedApplication] statusBarOrientation];
if(UIInterfaceOrientationIsPortrait(currentOrientation))
{
if(currentOrientation == UIInterfaceOrientationPortrait)
{
value = [NSNumber numberWithInt:UIInterfaceOrientationPortraitUpsideDown];
}
else //if(currentOrientation == UIInterfaceOrientationPortraitUpsideDown)
{
value = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
}
}
else
{
if(currentOrientation == UIInterfaceOrientationLandscapeRight)
{
value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft];
}
else //if(currentOrientation == UIInterfaceOrientationLandscapeLeft)
{
value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeRight];
}
}
[[UIDevice currentDevice] setValue:value forKey:@"orientation"];
[UIViewController attemptRotationToDeviceOrientation];
}
Swift 3
func flipOrientation() -> Void
{
let currentOrientation : UIInterfaceOrientation = UIApplication.shared.statusBarOrientation
var value : Int = 0;
if(UIInterfaceOrientationIsPortrait(currentOrientation))
{
if(currentOrientation == UIInterfaceOrientation.portrait)
{
value = UIInterfaceOrientation.portraitUpsideDown.rawValue
}
else //if(currentOrientation == UIInterfaceOrientation.portraitUpsideDown)
{
value = UIInterfaceOrientation.portrait.rawValue
}
}
else
{
if(currentOrientation == UIInterfaceOrientation.landscapeRight)
{
value = UIInterfaceOrientation.landscapeLeft.rawValue
}
else //if(currentOrientation == UIInterfaceOrientation.landscapeLeft)
{
value = UIInterfaceOrientation.landscapeRight.rawValue
}
}
UIDevice.current.setValue(value, forKey: "orientation")
UIViewController.attemptRotationToDeviceOrientation()
}
Ich hatte ein ähnliches Problem wie Sie. Ich muss die Ausrichtung des Geräts für einige Bildschirme (wie Login) sperren und die Drehung in anderen zulassen.
Nach ein paar Änderungen und folgenden Antworten habe ich es gemacht:
shouldAutorotate
-Methode in diesem VC überschreiben:-(BOOL)shouldAutorotate{
return NO;
}
Ich hoffe, das funktioniert für Sie.
Das hat mir perfekt geholfen ....
NSNumber *value = [NSNumber numberWithInt:UIDeviceOrientationPortrait];
[[UIDevice currentDevice] setValue:value forKey:@"orientation"];
Für diejenigen wie mich, die um @Sunny Shah kämpften, akzeptierte Antwort, um an iPads zu arbeiten. Sie müssen das Kontrollkästchen "Vollbild erforderlich" in den Projekteinstellungen aktivieren. Beachten Sie, dass dies Ihre App daran hindert, im Multitasking-Modus zu arbeiten, der möglicherweise akzeptabel ist oder nicht.
Versuchen Sie dies zusammen mit Ihrem Code.
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
sobald der Benutzer eine Option auswählt, rufen Sie diese Methode auf, da sich der Benutzer im Querformat befinden kann. Dann kann er nur den Hochformatmodus in demselben Ansichtscontroller festlegen. Die Ansicht sollte daher automatisch in den Hochformatmodus verschoben werden
-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration