Xamarin:锁定方向后是否检测设备旋转?对于iOS和/或Android?

时间:2018-07-03 14:30:22

标签: xamarin xamarin.forms xamarin.ios xamarin.android

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

有没有一种方法可以检测设备旋转而不依赖于方向变化?

2 个答案:

答案 0 :(得分:1)

在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();
}

在Android上:

[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());
}

OrientationChangedIOrientationService中的事件:

event EventHandler<Orientation> OrientationChanged;

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

答案 1 :(得分:0)

对于 iOS AppDelegate.cs 中,覆盖以下方法

public override UIInterfaceOrientationMask GetSupportedInterfaceOrientations(UIApplication application,UIWindow forWindow)
    {
        if (Xamarin.Forms.Application.Current == null || Xamarin.Forms.Application.Current.MainPage == null)
        {
            return UIInterfaceOrientationMask.Portrait;
        }

        var mainPage = Xamarin.Forms.Application.Current.MainPage;

        if (mainPage is YourPage || (mainPage is NavigationPage &&
                                                 ((NavigationPage)mainPage).CurrentPage is YourPage) || (mainPage.Navigation != null &&
        mainPage.Navigation.ModalStack.LastOrDefault() is YourPage))
        {
            if (Configuration.IsFullScreen)
            {
                return UIInterfaceOrientationMask.Landscape;
            }
        }
        return UIInterfaceOrientationMask.Portrait;
    }

依赖服务中,编写以下方法

 public void ChangeLandscapeOrientation()
 {
     UIDevice.CurrentDevice.SetValueForKey(new NSNumber((int)UIInterfaceOrientation.LandscapeLeft), new NSString("orientation"));
     UINavigationController.AttemptRotationToDeviceOrientation();
 }

在需要时调用 ChangeLandscapeOrientation 方法。

对于 Android 依赖服务中,编写以下方法将方向更改为横向

public void ChangeLandscapeOrientation()
{
    var activity = (Activity)Xamarin.Forms.Forms.Context;
    {
        activity.RequestedOrientation = ScreenOrientation.Landscape;
        var attrs = activity.Window.Attributes;
        _originalFlags = attrs.Flags;
        attrs.Flags |= Android.Views.WindowManagerFlags.Fullscreen;
        activity.Window.Attributes = attrs;
    }
}

下面的代码将方向更改为“纵向”

public void ChangePortraitOrientation()
{
    var activity = (Activity)Xamarin.Forms.Forms.Context;
    {
        activity.RequestedOrientation = ScreenOrientation.Portrait;
        var attrs = activity.Window.Attributes;
        attrs.Flags = _originalFlags;
        activity.Window.Attributes = attrs;
    }
}

希望有帮助!