首页 > 解决方案 > Xamarin:锁定方向时检测设备旋转?对于 iOS 和/或 Android?

问题描述

我正在开发一个播放类似于 YouTube 类型应用程序的视频的 Xamarin.Forms 应用程序。我希望视频在设备旋转时全屏显示(就像 youtube 一样),但我也希望将方向锁定为纵向。我发现的每篇文章或教程都指向使用自定义渲染来检测方向变化以确定设备何时旋转,但是当方向被锁定时,这些事件不会触发。

有没有一种方法可以在不依赖方向变化的情况下检测设备旋转?

标签: xamarinxamarin.formsxamarin.iosxamarin.android

解决方案


在 iOS 上,您将通过以下方式获得设备方向:

var orientation = UIDevice.CurrentDevice.Orientation;

在 Android 上,您需要询问窗口管理器:

var windowManager = ApplicationContext.GetSystemService(Context.WindowService).JavaCast<IWindowManager>();
var orientation = windowManager.DefaultDisplay.Rotation;

您不需要自定义渲染器,但您在服务定位器中注册的服务就足够了。这可能看起来像。

在共享代码中:

public enum Orientation
{
    None,
    PortraitUp,
    PortraitDown,
    LandscapeLeft,
    LandscapeRight
}

public interface IOrientationService
{
    Orientation GetCurrentOrientation();
}

在安卓上:

[assembly: Dependency(typeof(AndroidOrientationService))]

public class AndroidOrientationService : IOrientationService
{
    private readonly IWindowManager _windowManager;
    public AndroidOrientationService()
    {
        _windowManager = ApplicationContext.GetSystemService(Context.WindowService).JavaCast<IWindowManager>();
    }

    public Orientation GetCurrentOrientation()
    {
        switch (_windowManager.DefaultDisplay.Rotation)
        {
            case SurfaceOrientation.Rotation0:
                return Orientation.PortraitUp;
            case SurfaceOrientation.Rotation180:
                return Orientation.PortraitDown;
            case SurfaceOrientation.Rotation90:
                return Orientation.LandscapeLeft;
            case SurfaceOrientation.Rotation270:
                return Orientation.LandscapeRight;
            default:
                return Orientation.None;   
        }
    }   
}

同样在 iOS 上:

[assembly: Dependency(typeof(IosOrientationService))]

public class IosOrientationService : IOrientationService
{
    public Orientation GetCurrentOrientation()
    {
        switch (UIDevice.CurrentDevice.Orientation)
        {
            case UIDeviceOrientation.LandscapeLeft:
                return Orientation.LandscapeLeft;
            case UIDeviceOrientation.LandscapeRight:
                return Orientation.LandscapeRight;
            case UIDeviceOrientation.Portrait:
                return Orientation.PortraitUp;
            case UIDeviceOrientation.PortraitUpsideDown:
                return Orientation.PortraitDown;
            default:
                return Orientation.None;
        }
    }
}

然后在您的代码中,您应该能够获得如下方向:

var orientationService = DependencyService.Get<IOrientationService>();
var orientation = orientationService.GetCurrentOrientation();

编辑:检测方向变化

如果你想检测 iOS 上的方向变化,你可以通过为UIDeviceOrientation.

UIDevice.Notifications.ObserveOrientationDidChange(OnOrientationChanged);

同样,在 Android 上,您可以使用SensorManager来收听SensorType.Orientation更改。它有更多的活动部件,但看起来如下所示。

您需要创建一个ISensorEventListener类:

class MyOrientationListner : Java.Lang.Object, ISensorEventListener
{
    public event EventHandler OrientationChanged;

    public void OnAccuracyChanged(Sensor sensor, SensorStatus accuracy)
    {
    }

    public void OnSensorChanged(SensorEvent e)
    {
        OrientationChanged?.Invoke(this, EventArgs.Empty);    
    }
}

然后你需要从当前获取传感器管理器Context并开始监听方向变化事件:

_sensorManager = context.GetSystemService(Context.SensorService).JavaCast<SensorManager>();
var sensor = _sensorManager.GetDefaultSensor(SensorType.Orientation);
var listener = new MyOrientationListner();
listener.OrientationChanged += OnOrientationChanged;
_sensorManager.RegisterListener(listener, sensor, SensorDelay.Normal);

private void OnOrientationChanged(object sender, EventArgs e)
{
    OrientationChanged?.Invoke(this, GetCurrentOrientation());
}

OrientationChanged中的事件在哪里IOrientationService

event EventHandler<Orientation> OrientationChanged;

然后,您可以在需要的地方收听该事件。


推荐阅读