Quiero a consulta de la orientación que el iPhone es actualmente. El uso de

[UIDevice currentDevice].orientation

funciona siempre y cuando el dispositivo no está de orientación bloqueada. Si está bloqueado, sin embargo, siempre se responde con el bloqueo de la orientación, no con la orientación real del dispositivo.

Hay un alto nivel de forma de obtener el real de la orientación del dispositivo?

InformationsquelleAutor Mark Probst | 2011-01-01

8 Comentarios

  1. 9

    Que la funcionalidad es correcta. Si siempre se devuelve la orientación del dispositivo, incluso si fue bloqueado, la orientación cambiado notificaciones sería el fuego. Esto anularía el propósito de la cerradura.

    para responder A su pregunta, no hay manera de leer la cruda valores del acelerómetro, sin el uso privado de la Api.

    Edición:

    Después de revisar la documentación, parece que el UIAccelerometer clase proporciona estos datos, incluso cuando la orientación es bloqueado. Este cambio se aplicó en iOS 4 o superior. Aunque usted puede utilizar esta información, usted todavía necesita el proceso para determinar la orientación. Esto no es una tarea fácil, ya que usted necesita para controlar los cambios constantemente y se les compara con los antiguos valores.

    También, echa un vistazo a esta guía para el manejo de eventos de movimiento. Esto puede proporcionar usted con otra ruta para la determinación de la orientación.

    • +1 Como un punto menor, usted podría simplemente supervisar el acelerómetro y el intento de determinar la orientación de ti sin el uso privado de la Api, pero que es un poco fuera de lugar. (Cerrado significa bloqueado después de todo.)
    • No veo por qué no puede supervisar el acelerómetro, que funciona por separado de la orientación de la pantalla del sistema.
    • No estoy de acuerdo con tu primera frase. Un dispositivo de orientación de la notificación es notificar a la orientación del dispositivo de la interfaz. Teóricamente, debería ser notificado, independientemente de que el bloqueo de la rotación.
    • Este juego de: itunes.apple.com/us/app/superbrothers-sword-sworcery/… ignora el bloqueo de orientación para una buena razón en una buena manera.
  2. 32

    También puede utilizar CoreMotion

    Orientación algoritmo de detección:

    • si abs( y ) < abs( x ) de tu iPhone está en posición horizontal, mirar signo de x para detectar derecho
      o a la izquierda

    • otra cosa que el iPhone está en posición vertical, mira signo de y para detectar arriba o boca abajo.

    • Si usted está interesado en la cara arriba o hacia abajo, buscar el valor de z.


    import CoreMotion

    var uMM: CMMotionManager!
    
    override func
    viewWillAppear( p: Bool ) {
        super.viewWillAppear( p )
        uMM = CMMotionManager()
        uMM.accelerometerUpdateInterval = 0.2
    
        // Using main queue is not recommended. So create new operation queue and pass it to startAccelerometerUpdatesToQueue.
        // Dispatch U/I code to main thread using dispach_async in the handler.
        uMM.startAccelerometerUpdatesToQueue( NSOperationQueue() ) { p, _ in
            if p != nil {
                println(
                    abs( p.acceleration.y ) < abs( p.acceleration.x )
                    ?   p.acceleration.x > 0 ? "Right"  :   "Left"
                    :   p.acceleration.y > 0 ? "Down"   :   "Up"
                )
            }
        }
    }
    
    override func
    viewDidDisappear( p: Bool ) {
        super.viewDidDisappear( p )
        uMM.stopAccelerometerUpdates()
    }
    • Una increíble respuesta simple… funcionó a la perfección. Gracias!
    • Buena respuesta, como UIAccelerometer ahora es obsoleto y no puede ser utilizado en Swift.
    • ¿Cómo sabes que la orientación si coloca el teléfono boca arriba o abajo en una tabla ? Sería 0 en ambos valores de x e y. Creo que esto podría ser resuelto con algunos datos de giroscopio sensor de datos.
    • La aceleración de la estructura de valor de z. Sólo se necesita comprobar el signo de z.
  3. 8

    Configurar el controlador de vista o lo que sea para apoyar la UIAccelerometerProtocol, y empezar a escuchar para que los cambios (se puede establecer a 10 hz).

    #define kAccelerometerFrequency        10.0 //Hz
    -(void)viewDidAppear:(BOOL)animated {
    DLog(@"viewDidAppear");
    [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
    UIAccelerometer* a = [UIAccelerometer sharedAccelerometer];
    a.updateInterval = 1 / kAccelerometerFrequency;
    a.delegate = self;
    }
    -(void)viewWillDisappear:(BOOL)animated {
    DLog(@"viewWillDisappear");
    UIAccelerometer* a = [UIAccelerometer sharedAccelerometer];
    a.delegate = nil;
    [[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];
    }
    #ifdef DEBUG
    +(NSString*)orientationToText:(const UIInterfaceOrientation)ORIENTATION {
    switch (ORIENTATION) {
    case UIInterfaceOrientationPortrait:
    return @"UIInterfaceOrientationPortrait";
    case UIInterfaceOrientationPortraitUpsideDown:
    return @"UIInterfaceOrientationPortraitUpsideDown";
    case UIInterfaceOrientationLandscapeLeft:
    return @"UIInterfaceOrientationLandscapeLeft";
    case UIInterfaceOrientationLandscapeRight:
    return @"UIInterfaceOrientationLandscapeRight";
    }
    return @"Unknown orientation!";
    }
    #endif
    #pragma mark UIAccelerometerDelegate
    -(void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
    UIInterfaceOrientation orientationNew;
    if (acceleration.x >= 0.75) {
    orientationNew = UIInterfaceOrientationLandscapeLeft;
    }
    else if (acceleration.x <= -0.75) {
    orientationNew = UIInterfaceOrientationLandscapeRight;
    }
    else if (acceleration.y <= -0.75) {
    orientationNew = UIInterfaceOrientationPortrait;
    }
    else if (acceleration.y >= 0.75) {
    orientationNew = UIInterfaceOrientationPortraitUpsideDown;
    }
    else {
    //Consider same as last time
    return;
    }
    if (orientationNew == orientationLast)
    return;
    NSLog(@"Going from %@ to %@!", [[self class] orientationToText:orientationLast], [[self class] orientationToText:orientationNew]);
    orientationLast = orientationNew;
    }
    #pragma mark -

    Es necesario definir UIInterfaceOrientation orientationLast como una variable miembro y listo.

    • Lo siento por chocar con esto, un Gran código. ¿Cómo podría usted comprobar UIDeviceOrientationFaceDown / UIDeviceOrientationFaceUp utilizando el Giroscopio … ?
    • este es un buen código, pero creo que es una vergüenza que son confusas/ofuscación de las diferencias entre deviceOrientation y interfaceOrientation..
  4. 5

    La UIAccelerometer clase sigue a la función cuando la orientación del dispositivo está bloqueado. Usted tendrá que trabajar fuera de sus propios métodos de convertir sus variables en la orientación de los valores, pero no debería ser especialmente complicado.

    Tener un juego con Apple AcceleromoterGraph aplicación de muestra para ver qué valores del acelerómetro salidas en diferentes orientaciones.

  5. 5

    El manejo de todos los 6 orientaciones

    Aunque no es a menudo la atención sobre FaceUp /FaceDown orientaciones, siguen siendo importantes.

    Teniendo en cuenta los mismos conduce a una más adecuada sensibilidad para los cambios de orientación, dejando pueden conducir a la metaestabilidad & histéresis.

    He aquí cómo he manejado –

    - (void)startMonitoring
    {
    [self.motionManager startAccelerometerUpdatesToQueue:self.opQueue withHandler:^(CMAccelerometerData * _Nullable accelerometerData, NSError * _Nullable error) {
    if (error != nil)
    {
    NSLog(@"Accelerometer error: %@", error);
    }
    else
    {
    float const threshold = 40.0;
    BOOL (^isNearValue) (float value1, float value2) = ^BOOL(float value1, float value2)
    {
    return fabsf(value1 - value2) < threshold;
    };
    BOOL (^isNearValueABS) (float value1, float value2) = ^BOOL(float value1, float value2)
    {
    return isNearValue(fabsf(value1), fabsf(value2));
    };
    float yxAtan = (atan2(accelerometerData.acceleration.y, accelerometerData.acceleration.x)) * 180 / M_PI;
    float zyAtan = (atan2(accelerometerData.acceleration.z, accelerometerData.acceleration.y)) * 180 / M_PI;
    float zxAtan = (atan2(accelerometerData.acceleration.z, accelerometerData.acceleration.x)) * 180 / M_PI;
    UIDeviceOrientation orientation = self.orientation;
    if (isNearValue(-90.0, yxAtan) && isNearValueABS(180.0, zyAtan))
    {
    orientation = UIDeviceOrientationPortrait;
    }
    else if (isNearValueABS(180.0, yxAtan) && isNearValueABS(180.0, zxAtan))
    {
    orientation = UIDeviceOrientationLandscapeLeft;
    }
    else if (isNearValueABS(0.0, yxAtan) && isNearValueABS(0.0, zxAtan))
    {
    orientation = UIDeviceOrientationLandscapeRight;
    }
    else if (isNearValue(90.0, yxAtan) && isNearValueABS(0.0, zyAtan))
    {
    orientation = UIDeviceOrientationPortraitUpsideDown;
    }
    else if (isNearValue(-90.0, zyAtan) && isNearValue(-90.0, zxAtan))
    {
    orientation = UIDeviceOrientationFaceUp;
    }
    else if (isNearValue(90.0, zyAtan) && isNearValue(90.0, zxAtan))
    {
    orientation = UIDeviceOrientationFaceDown;
    }
    if (self.orientation != orientation)
    {
    dispatch_async(dispatch_get_main_queue(), ^{
    [self orientationDidChange:orientation];
    });
    }
    }
    }];
    }

    Además, he añadido un threshold valor de 40.0 (en lugar de 45.0). Esto hace que los cambios menos sensible, la prevención de la histéresis en puntos de inflexión.

    Si sólo desea reaccionar a los cambios de la principal 4 orientaciones, acabo de hacer este

    if (UIDeviceOrientationIsPortrait(orientation) || UIDeviceOrientationIsLandscape(orientation))
    {
    //Do something
    }
  6. 2

    mi solución con coremotion,que funcionan incluso cuando el dispositivo tiene su orientación bloqueado.

        let motionManager: CMMotionManager = CMMotionManager()

    hizo en el método de carga

    motionManager.deviceMotionUpdateInterval = 0.01
    if motionManager.accelerometerAvailable{
    let queue = NSOperationQueue()
    motionManager.startAccelerometerUpdatesToQueue(queue, withHandler:
    {data, error in
    guard let data = data else{
    return
    }
    let angle = (atan2(data.acceleration.y,data.acceleration.x))*180/M_PI;
    print(angle)
    if(fabs(angle)<=45){
    self.orientation = AVCaptureVideoOrientation.LandscapeLeft
    print("landscape left")
    }else if((fabs(angle)>45)&&(fabs(angle)<135)){
    if(angle>0){
    self.orientation = AVCaptureVideoOrientation.PortraitUpsideDown
    print("portrait upside Down")
    }else{
    self.orientation = AVCaptureVideoOrientation.Portrait
    print("portrait")
    }
    }else{
    self.orientation = AVCaptureVideoOrientation.LandscapeRight
    print("landscape right")
    }
    }
    )
    } else {
    print("Accelerometer is not available")
    }

    espero que ayude.

  7. 1

    Uso de CMMotionManager puede ayudar, pero no en el sentido indicado anteriormente. La lógica anterior no es estable. He probado a fondo y se encontró que al ver los valores de acceleration.x/y/z no están ayudando a determinar la orientación.

    Lugar, tengo una manera de encontrar la orientación WRT el ángulo es decir,
    float angle = (atan2(accelerometerData.acceleration.y,accelerometerData.acceleration.x))*180/M_PI;

    Y para la orientación,-
    if(fabs(angle<=45)currOrientation=UIDeviceOrientationLandscapeRight;
    else if((fabs(angle)>45)&&(fabs(angle)<135))currOrientation=((angle>0)?UIDeviceOrientationPortraitUpsideDown:UIDeviceOrientationPortrait);
    else currOrientation = UIDeviceOrientationLandscapeLeft;

    Esto podría ser útil para alguien, aunque esto no me ayuda a encontrar 2 otras orientaciones decir UIDeviceOrientationFaceUp & UIDeviceOrientationFaceDown.

  8. 1

    Utilizando Satachito la gran respuesta es aquí el código que también detecta si el dispositivo está boca arriba o boca abajo

    import CoreMotion

    var mm: CMMotionManager!
    init() {
    self.mm = CMMotionManager()
    self.mm.accelerometerUpdateInterval = 0.2
    }
    public func startOrientationUpdates() {
    // Using main queue is not recommended. So create new operation queue and pass it to startAccelerometerUpdatesToQueue.
    // Dispatch U/I code to main thread using dispach_async in the handler.
    self.mm.startAccelerometerUpdates( to: OperationQueue() ) { p, _ in
    if let p = p {
    if(p.acceleration.x > -0.3 && p.acceleration.x < 0.3 && p.acceleration.z < -0.95) {
    print("face up")
    }
    else if(p.acceleration.x > -0.3 && p.acceleration.x < 0.3 && p.acceleration.z > 0.95) {
    print("face down")
    }
    else {
    print(
    abs( p.acceleration.y ) < abs( p.acceleration.x )
    ?   p.acceleration.x > 0 ? "Right"  :   "Left"
    :   p.acceleration.y > 0 ? "Down"   :   "Up"
    )
    }
    }
    }
    }
    public func endOrientationUpdates() {
    self.mm.stopAccelerometerUpdates()
    }

Dejar respuesta

Please enter your comment!
Please enter your name here