Xamarin: определить вращение устройства, когда ориентация заблокирована? Для iOS и / или Android? - PullRequest
0 голосов
/ 03 июля 2018

Я работаю над приложением Xamarin.Forms, которое воспроизводит видео, похожее на приложение типа YouTube. Я хочу, чтобы видео вращалось в полноэкранном режиме, когда устройство вращается (как это делает YouTube), но я также хочу, чтобы ориентация была привязана к портрету. Каждый найденный мной пост или учебник указывает на использование пользовательских средств визуализации для определения изменения ориентации, чтобы определить, когда устройство вращается, но когда ориентация заблокирована, эти события не запускаются.

Есть ли способ обнаружения вращения устройства без зависимости от изменения ориентации?

Ответы [ 2 ]

0 голосов
/ 04 июля 2018

Для 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 В Dependency Service напишите приведенный ниже метод, чтобы изменить ориентацию на Landscape

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;
    }
}

Надеюсь, это поможет!

0 голосов
/ 03 июля 2018

На iOS вы бы получили ориентацию устройства с:

var orientation = UIDevice.CurrentDevice.Orientation;

На Android вам нужно спросить у Window Manager:

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

Где OrientationChanged - событие в IOrientationService:

event EventHandler<Orientation> OrientationChanged;

Затем вы можете прослушать это событие, где это необходимо.

...