Как установить ориентацию ContentPage в Xamarin.Forms

Я использую Xamarin.Forms для создания кросс-платформенного приложения, все мои ContentPages находятся внутри PCL .

Я ищу способ установить и заблокировать orientation одного ContentPage на Landscape , желательно, не создавая другого действия в каждом из проектов, специфичных для платформы.

Поскольку мой ContentPage.Content установлен в ScrollView , я попытался установить ScrollOrientation в Horizontal , однако это не сработало.

Я также попытался использовать RelativeLayout , но я не могу увидеть свойство Orientation .

 public class PlanningBoardView : ContentPage //Container Class. { public PlanningBoardView() { scroller = new ScrollView (); Board = new PlanningBoard(); scroller.Orientation = ScrollOrientation.Horizontal; scroller.WidthRequest = Board.BoardWidth; scroller.Content = Board; Content = scroller; } } 

Последнее, что я пробовал, это использовать версию Xalarin Studio Intellisense и Dac's Xamarin Forms API для просмотра различных доступных мне макетов, ни одно из которых не имело свойства Orientation .

Я боюсь, что единственный способ сделать это – создать вторую платформенную Activity только для этого ContentPage и установить ориентацию на ландшафт.

Хотя этот метод будет работать, он делает навигацию между экранами намного сложнее.

Это в настоящее время тестируется на Android.

Ненавижу это сказать, но это можно сделать только с помощью настраиваемых рендерингов или кода, специфичного для платформы

В android вы можете установить свойство RequestedOrientation для MainActivity для ScreenOrientation.Landscape .

В iOS вы можете переопределить GetSupportedInterfaceOrientations в классе AppDelegate чтобы вернуть одно из значений Xamarin.Forms.Application.Current.MainPage когда Xamarin.Forms.Application.Current.MainPage – это ContentPage, в который вы вошли.

Android

 [assembly: Xamarin.Forms.ExportRenderer(typeof(MyCustomContentPage), typeof(CustomContentPageRenderer))] public class CustomContentPageRenderer : Xamarin.Forms.Platform.Android.PageRenderer { private ScreenOrientation _previousOrientation = ScreenOrientation.Unspecified; protected override void OnWindowVisibilityChanged(ViewStates visibility) { base.OnWindowVisibilityChanged(visibility); var activity = (Activity)Context; if (visibility == ViewStates.Gone) { // Revert to previous orientation activity.RequestedOrientation = _previousOrientation == ScreenOrientation.Unspecified ? ScreenOrientation.Portrait : _previousOrientation; } else if (visibility == ViewStates.Visible) { if (_previousOrientation == ScreenOrientation.Unspecified) { _previousOrientation = activity.RequestedOrientation; } activity.RequestedOrientation = ScreenOrientation.Landscape; } } } 

IOS

 public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate { 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 MyCustomContentPage || (mainPage is NavigationPage && ((NavigationPage)mainPage).CurrentPage is MyCustomContentPage) || (mainPage.Navigation != null && mainPage.Navigation.ModalStack.LastOrDefault() is MyCustomContentPage)) { return UIInterfaceOrientationMask.Landscape; } return UIInterfaceOrientationMask.Portrait; } } 

Код Dealdiane хорошо работает для меня с небольшими изменениями:

 protected override void OnWindowVisibilityChanged(ViewStates visibility) { base.OnWindowVisibilityChanged( visibility ); IRotationLock page = Element as IRotationLock; if ( page == null ) return; var activity = (Activity) Context; if ( visibility == ViewStates.Gone ) { // Revert to previous orientation activity.RequestedOrientation = _previousOrientation; } else if ( visibility == ViewStates.Visible ) { if ( _previousOrientation == ScreenOrientation.Unspecified ) { _previousOrientation = activity.RequestedOrientation; } switch ( page.AllowRotation() ) { case RotationLock.Landscape: activity.RequestedOrientation = ScreenOrientation.SensorLandscape; break; case RotationLock.Portrait: activity.RequestedOrientation = ScreenOrientation.SensorPortrait; break; } } } 

Это также можно сделать, отправив сообщение из проекта Form для размещения проекта с использованием класса MessagingCenter. Без использования пользовательского средства визуализации или службы зависимостей, как указано ниже,

 public partial class ThirdPage : ContentPage { protected override void OnAppearing() { base.OnAppearing(); MessagingCenter.Send(this, "allowLandScapePortrait"); } //during page close setting back to portrait protected override void OnDisappearing() { base.OnDisappearing(); MessagingCenter.Send(this, "preventLandScape"); } } 

Изменение mainactivity для получения сообщения и установки RequestedOrientation

 [Activity(Label = "Main", ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation,ScreenOrientation = ScreenOrientation.Portrait)] public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsApplicationActivity { //allowing the device to change the screen orientation based on the rotation MessagingCenter.Subscribe<ThirdPage>(this, "allowLandScapePortrait", sender => { RequestedOrientation = ScreenOrientation.Unspecified; }); //during page close setting back to portrait MessagingCenter.Subscribe<ThirdPage>(this, "preventLandScape", sender => { RequestedOrientation = ScreenOrientation.Portrait; }); } 

Подробнее читайте в своем блоге: http://www.appliedcodelog.com/2017/05/force-landscape-or-portrait-for-single.html