在Xamarin.Forms的方向更改中添加布局

我需要实现的是,将屏幕从纵向更改为现有页面添加布局。 我已经设法检测使用void OnSizeAllocated(双倍宽度,双倍高度)的方向更改。 但是我不能在这个事件上添加一个布局。

我的示例C#代码是

public class MyLayoutView : ContentPage { StackLayout portraitcontent = null; StackLayout landscapecontent = null; StackLayout footer = null; public MyLayoutView () { portraitcontent = new StackLayout (); landscapecontent = new StackLayout (); footer = new StackLayout (); this.Padding = new Thickness(0, Device.OnPlatform(20, 0, 0), 0, 0); this.BackgroundColor = Color.FromHex ("#ffffff"); this.Content = new StackLayout { Children = { portraitcontent , landscapecontent , footer } }; } } 

OnSizeAllocated方法

  protected override void OnSizeAllocated(double width, double height) { base.OnSizeAllocated(width, height); if (width < height) { // In Portrait portraitcontent .IsVisible = true; landscapecontent.IsVisible = false; Debug.WriteLine ("Application Is in portrait"); } else { // In Landscape portraitcontent .IsVisible = false; landscapecontent.IsVisible = true; landscapecontent.Children.Clear (); Label LandscapeLabel= new Label { Text = "<Each Time Text Changes>", HorizontalOptions = LayoutOptions.StartAndExpand, TextColor=Xamarin.Forms.Color.FromHex("#000000") }; landscapecontent.Children.Add(LandscapeLabel); Debug.WriteLine ("Application Is in Landscape"); } } 

在reenterancy被阻塞的错误抛出不能修改集合 。 每当方向更改时,我需要在堆栈布局中添加一个新标签。 我怎样才能以适当的方式实现它?

提前致谢

在定位更改时,分配的大小会被多次调用。 我认为你必须做更多的validation,比如检查孩子的数量,以避免重复的观点。

  if(landscapecontent.Children.Count>1) { //Don't add any views } 

只要我尝试没有事件处理程序的旋转。 Itz在代码中破解方向改变时改变视图。

即使你可以使用这里接受的答案..希望它为你的目的..

重写OnSizeAllocated可能不是最好的方法。 我只是把它放在我的代码中,从纵向到横向调用这个方法大约25次。

我正在尝试的另一件事是在窗体页面上挂钩一个事件处理程序:

 this.SizeChanged += (sender, e) => setOrientation(this); // Connect Orientation Switcher 

为了跟踪真正的页面旋转,并避免处理器的不必要的工作,我创build了一个类variables来存储当前状态,然后将其添加到高度/宽度比较。

 void setOrientation (Page p) if ( isPortrait && (p.Width > p.Height) ) { do stuff } if ( !isPortrait && (p.Width < p.Height) ) { do stuff } 

这是更快,但目前似乎有一些内存泄漏与一些布局来回切换。 仍在努力。 不能相信,随着移动已经多年的屏幕旋转,开发工具将可用,没有股票简单的方法来做到这一点。 看起来像他们可以让我们挂钩几个不同的布局到一个页面,并运行时自动select基于环境。 我不是一个开发者,也许这比我看起来要困难得多。

如果我得到轮换工作,我会尽量记得回来,并张贴代码。

对于Xamarin格式,PCL是检测方位变化的错误层。 您需要使用特定于平台的代码来检测它们,然后将其通知给PCL。 对于刚才我正在处理的一个项目,这里是我的解决scheme:在PCL代码中:

 public interface IOrientation { AppOrientation CurrentOrientation { get; } IObservable<AppOrientation> Orientation { get; } } public enum AppOrientation { Unknown = 0, Portrait, Landscape } 

在任何视图(xaml页面),我可以观察方向变化:我使用autofac来初始化ctor中的IOrientation,使用任何Ioc或服务parsing最适合您的方式。

 public HomePage(IViewResolver resolver,IOrientation orientation) { InitializeComponent(); _resolver = resolver; this.SetContent(); orientation.Orientation.ObserveOn(SynchronizationContext.Current) .Subscribe(x => this.SetContent()); } 

对于Android:

在MainActivity.cs中,closuresMainActivity实现IOrientation。 public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsApplicationActivity , IErrorReporting,IOrientation和ctor的某处: _lastOrientation = this.Resources.Configuration.Orientation;

  #region IOrientation private Android.Content.Res.Orientation _lastOrientation; private readonly Subject<AppOrientation> _orientation = new Subject<AppOrientation>(); public AppOrientation CurrentOrientation { get { return _lastOrientation == Android.Content.Res.Orientation.Portrait ? AppOrientation.Portrait : _lastOrientation == Android.Content.Res.Orientation.Landscape ? AppOrientation.Landscape : AppOrientation.Unknown; } } public IObservable<AppOrientation> Orientation { get { return _orientation; } } public override void OnConfigurationChanged(Configuration newConfig) { base.OnConfigurationChanged(newConfig); if (newConfig.Orientation == this._lastOrientation) return; this._lastOrientation = newConfig.Orientation; this._orientation.OnNext(this.CurrentOrientation); } #endregion 

在iOS中扩展AppDelegate的public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate ,IOrientation和ctor中的某处: _lastOrientation = UIDevice.CurrentDevice.Orientation;

 #region IOrientation private UIDeviceOrientation _lastOrientation = UIDeviceOrientation.Unknown; private readonly Subject<AppOrientation> _orientation=new Subject<AppOrientation>(); public AppOrientation CurrentOrientation { get { return (_lastOrientation == UIDeviceOrientation.LandscapeLeft || _lastOrientation == UIDeviceOrientation.LandscapeRight) ? AppOrientation.Landscape : (_lastOrientation == UIDeviceOrientation.Portrait || _lastOrientation == UIDeviceOrientation.PortraitUpsideDown) ? AppOrientation.Portrait : AppOrientation.Unknown; } } public IObservable<AppOrientation> Orientation { get { return _orientation; } } #endregion 

我没有WP的实施,但我不能相信这将是很难创造一个….