【问题标题】:Add a Layout on Orientation change in Xamarin.Forms在 Xamarin.Forms 中添加方向更改布局
【发布时间】:2014-09-18 03:24:23
【问题描述】:

我需要实现的是,在将屏幕从纵向更改为横向时将布局添加到现有页面。我已经设法使用 void OnSizeAllocated(double width, double height) 检测到方向变化。但我无法在此事件上添加布局。

我的示例 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");
        }
    }

它抛出无法在重新进入被阻止时修改集合错误。每次方向更改时,我都需要在 stacklayout 中添加一个新标签。我怎样才能以适当的方式实现它??

提前致谢

【问题讨论】:

    标签: c# android ios xamarin.forms


    【解决方案1】:

    当方向改变时,多次调用分配的大小。我认为您必须进行更多验证,例如检查孩子的数量以避免重复视图。

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

    只要我尝试过,就没有用于轮换的事件处理程序。当方向改变时,它会在代码中更改视图。

    即使您可以使用已接受的答案here.. 希望它符合您的目的..

    【讨论】:

      【解决方案2】:

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

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

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

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

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

      这样更快,但目前似乎存在内存泄漏,一些布局来回切换。仍在努力。无法相信,随着移动设备多年来一直在旋转屏幕,可以使用一种没有简单方法来执行此操作的开发工具。似乎它们可以让我们将几个不同的布局连接到一个页面,并让运行时根据环境自动选择。我不是开发人员,也许这比我想象的要困难得多。

      如果我可以轮换工作,我会尽量记住回来并发布代码。

      【讨论】:

        【解决方案3】:

        对于 Xamarin 形式,PCL 是检测方向变化的错误层。您需要使用特定于平台的代码来检测它们,然后将其传达给 PCL。 对于我现在正在做的一个项目,这是我的解决方案: 在 PCL 代码中:

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

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

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

        对于安卓:

        在 MainActivity.cs 中,从 MainActivity 实现 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 实现,但我不敢相信创建一个会这么难......

        【讨论】:

          猜你喜欢
          • 2014-07-28
          • 1970-01-01
          • 2020-08-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-10-05
          相关资源
          最近更新 更多