如何以编程方式将 UI 元素正确添加到 iOS 的视图中?
How do I properly add UI elements into a view programmatically for iOS?
我在 Visual Studio 2013 年使用 Xamarin.iOS 在 C# 中以编程方式构建一个简单的用户界面。我知道使用设计器视图要容易得多,但它现在不适合我。
到目前为止,我已经设法让 MPMoviePlayerController 和 TextView 显示出来,但是 TextView 不会滚动,即使我添加了这样做的要求。
TextView 与视频重叠,因为我可以听到后台播放的音频。 UILabel 也不见了。
我想添加每个 UI 元素作为主视图的子视图,将以堆栈顺序显示元素,在顶部显示视频,在视频和带滚动条的文本视图下方显示标签。
在某种程度上,我希望它们可以一层一层地相互堆叠。我做错了什么或遗漏了什么?
using System;
using System.Drawing;
using Foundation;
using UIKit;
using MediaPlayer;
public partial class VideoViewController : UIViewController
{
MPMoviePlayerController moviePlayer;
UILabel label;
UITextView textView;
public VideoViewController() : base("VideoViewController", null)
{
}
public override void DidReceiveMemoryWarning()
{
// Releases the view if it doesn't have a superview.
base.DidReceiveMemoryWarning();
// Release any cached data, images, etc that aren't in use.
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
// Perform any additional setup after loading the view, typically from a nib.
moviePlayer = new MPMoviePlayerController(NSUrl.FromString("http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4")); // Use FromString() to play video directly from web.
moviePlayer.View.Frame = new CoreGraphics.CGRect(0, 20, this.View.Frame.Size.Width, 180); // size of the video frame
moviePlayer.ScalingMode = MPMovieScalingMode.AspectFit; // show the video relative to the video size dimensions
moviePlayer.PrepareToPlay();
moviePlayer.Play();
this.View.AddSubview(moviePlayer.View); // add the view after video starts playing to display it
// UILabel
label = new UILabel();
label.Text = "Tutorial";
label.Font.WithSize(36);
this.View.AddSubview(label.ViewForBaselineLayout);
// UITextView
textView = new UITextView();
textView.Editable = false;
textView.ScrollEnabled = true;
textView.UserInteractionEnabled = true;
textView.ViewForBaselineLayout.Frame = new CoreGraphics.CGRect(0, 0, this.View.Frame.Size.Width, this.View.Frame.Size.Height*3);
textView.Text = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. [shorten text for this post] "; // shorten text for this post
this.View.AddSubview(textView);
}
}
}
我猜你想要这样:
using System;
using System.Drawing;
using Foundation;
using UIKit;
using MediaPlayer;
using CoreGraphics;
namespace CHANGE_THIS_TO_YOUR_NAME_SPACE
{
public partial class VideoViewController : UIViewController
{
MPMoviePlayerController moviePlayer;
UILabel label;
UITextView textView;
public VideoViewController () : base ("VideoViewController", null)
{
}
public override void DidReceiveMemoryWarning ()
{
// Releases the view if it doesn't have a superview.
base.DidReceiveMemoryWarning ();
// Release any cached data, images, etc that aren't in use.
}
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
// Perform any additional setup after loading the view, typically from a nib.
moviePlayer = new MPMoviePlayerController (NSUrl.FromString ("http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4")); // Use FromString() to play video directly from web.
moviePlayer.View.Frame = new CGRect (0, 20, View.Frame.Size.Width, 180); // size of the video frame
moviePlayer.ScalingMode = MPMovieScalingMode.AspectFit; // show the video relative to the video size dimensions
moviePlayer.PrepareToPlay ();
moviePlayer.Play ();
View.Add (moviePlayer.View); // add the view after video starts playing to display it
// UILabel
label = new UILabel (new CGRect(0,200, View.Frame.Size.Width, 50));
label.Text = "Tutorial";
label.Font.WithSize (36);
View.Add (label.ViewForBaselineLayout);
// UITextView
textView = new UITextView ();
textView.Editable = false;
textView.ScrollEnabled = true;
textView.UserInteractionEnabled = true;
textView.ViewForBaselineLayout.Frame = new CGRect (0, 250, View.Frame.Size.Width, View.Frame.Size.Height * 3);
textView.Text = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. [shorten text for this post] "; // shorten text for this post
View.Add (textView);
}
}
}
基本上,当您使用 CGRect
和 new CGRect(x-coord, y-coord, width, height)
设置视图的框架时,您几乎已经完成了。由于所有视图均为 0,0,因此它们彼此重叠。 UITextView
也不会滚动,因为您已将其高度设置为屏幕高度的三倍。如果你想让它滚动,内容(文本)需要延伸到框架之外。
iOS9介绍UIStackView
观看来自 WWDC 2015 的视频:https://developer.apple.com/videos/wwdc/2015/?id=218 但如果您支持 iOS7/8,则有一些第三方实现。 Xamarin.Forms 有一个堆栈布局,所以这也可能是一个选项。
一个改进的解决方案是不设置视图的框架,而是像这样使用自动布局约束:
using System;
using System.Drawing;
using Foundation;
using UIKit;
using MediaPlayer;
using CoreGraphics;
namespace CHANGE_THIS_TO_YOUR_NAME_SPACE
{
public partial class VideoViewController : UIViewController
{
MPMoviePlayerController moviePlayer;
UILabel label;
UITextView textView;
public VideoViewController () : base ("VideoViewController", null)
{
}
public override void DidReceiveMemoryWarning ()
{
// Releases the view if it doesn't have a superview.
base.DidReceiveMemoryWarning ();
// Release any cached data, images, etc that aren't in use.
}
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
// Perform any additional setup after loading the view, typically from a nib.
moviePlayer = new MPMoviePlayerController (NSUrl.FromString ("http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4")); // Use FromString() to play video directly from web.
moviePlayer.View.TranslatesAutoresizingMaskIntoConstraints = false;
// moviePlayer.View.Frame = new CGRect (0, 20, View.Frame.Size.Width, 180); // size of the video frame
moviePlayer.ScalingMode = MPMovieScalingMode.AspectFit; // show the video relative to the video size dimensions
moviePlayer.PrepareToPlay ();
moviePlayer.Play ();
View.Add (moviePlayer.View); // add the view after video starts playing to display it
// UILabel
// label = new UILabel (new CGRect(0,200, View.Frame.Size.Width, 50));
label = new UILabel ();
label.TranslatesAutoresizingMaskIntoConstraints = false;
label.Text = "Tutorial";
label.Font.WithSize (36);
View.Add (label.ViewForBaselineLayout);
// UITextView
textView = new UITextView ();
textView.TranslatesAutoresizingMaskIntoConstraints = false;
textView.Editable = false;
textView.ScrollEnabled = true;
textView.UserInteractionEnabled = true;
// textView.ViewForBaselineLayout.Frame = new CGRect (0, 250, View.Frame.Size.Width, View.Frame.Size.Height * 3);
textView.Text = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. [shorten text for this post] "; // shorten text for this post
View.Add (textView);
SetUpAutoLayoutConstraints ();
}
private void SetUpAutoLayoutConstraints()
{
View.AddConstraints (new [] {
NSLayoutConstraint.Create(moviePlayer.View, NSLayoutAttribute.Width, NSLayoutRelation.Equal, View, NSLayoutAttribute.Width, 1, 0),
NSLayoutConstraint.Create(moviePlayer.View, NSLayoutAttribute.Height, NSLayoutRelation.Equal, View, NSLayoutAttribute.Width, 0.5625f, 0), // setting it to this to keep your aspect ratio
NSLayoutConstraint.Create(moviePlayer.View, NSLayoutAttribute.Top, NSLayoutRelation.Equal, View, NSLayoutAttribute.Top, 1, 20),
NSLayoutConstraint.Create(moviePlayer.View, NSLayoutAttribute.Left, NSLayoutRelation.Equal, View, NSLayoutAttribute.Left, 1, 0)
});
View.AddConstraints (new [] {
NSLayoutConstraint.Create(label, NSLayoutAttribute.Width, NSLayoutRelation.Equal, View, NSLayoutAttribute.Width, 1, 0),
NSLayoutConstraint.Create(label, NSLayoutAttribute.Height, NSLayoutRelation.Equal, null, NSLayoutAttribute.NoAttribute, 1, 50),
NSLayoutConstraint.Create(label, NSLayoutAttribute.Top, NSLayoutRelation.Equal, moviePlayer.View, NSLayoutAttribute.Bottom, 1, 0),
NSLayoutConstraint.Create(label, NSLayoutAttribute.Left, NSLayoutRelation.Equal, View, NSLayoutAttribute.Left, 1, 0)
});
View.AddConstraints (new [] {
NSLayoutConstraint.Create(textView, NSLayoutAttribute.Width, NSLayoutRelation.Equal, View, NSLayoutAttribute.Width, 1, 0),
NSLayoutConstraint.Create(textView, NSLayoutAttribute.Bottom, NSLayoutRelation.Equal, View, NSLayoutAttribute.Bottom, 1, 0),
NSLayoutConstraint.Create(textView, NSLayoutAttribute.Top, NSLayoutRelation.Equal, label, NSLayoutAttribute.Bottom, 1, 0),
NSLayoutConstraint.Create(textView, NSLayoutAttribute.Left, NSLayoutRelation.Equal, View, NSLayoutAttribute.Left, 1, 0)
});
}
}
}
这会让您的视图适应屏幕尺寸,例如在 iphone4,5,6,6+ iPad 上正确布局。如果它太大,你的 UITextView
会滚动。
关于自动布局的好教程here
我在 Visual Studio 2013 年使用 Xamarin.iOS 在 C# 中以编程方式构建一个简单的用户界面。我知道使用设计器视图要容易得多,但它现在不适合我。
到目前为止,我已经设法让 MPMoviePlayerController 和 TextView 显示出来,但是 TextView 不会滚动,即使我添加了这样做的要求。
TextView 与视频重叠,因为我可以听到后台播放的音频。 UILabel 也不见了。
我想添加每个 UI 元素作为主视图的子视图,将以堆栈顺序显示元素,在顶部显示视频,在视频和带滚动条的文本视图下方显示标签。
在某种程度上,我希望它们可以一层一层地相互堆叠。我做错了什么或遗漏了什么?
using System;
using System.Drawing;
using Foundation;
using UIKit;
using MediaPlayer;
public partial class VideoViewController : UIViewController
{
MPMoviePlayerController moviePlayer;
UILabel label;
UITextView textView;
public VideoViewController() : base("VideoViewController", null)
{
}
public override void DidReceiveMemoryWarning()
{
// Releases the view if it doesn't have a superview.
base.DidReceiveMemoryWarning();
// Release any cached data, images, etc that aren't in use.
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
// Perform any additional setup after loading the view, typically from a nib.
moviePlayer = new MPMoviePlayerController(NSUrl.FromString("http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4")); // Use FromString() to play video directly from web.
moviePlayer.View.Frame = new CoreGraphics.CGRect(0, 20, this.View.Frame.Size.Width, 180); // size of the video frame
moviePlayer.ScalingMode = MPMovieScalingMode.AspectFit; // show the video relative to the video size dimensions
moviePlayer.PrepareToPlay();
moviePlayer.Play();
this.View.AddSubview(moviePlayer.View); // add the view after video starts playing to display it
// UILabel
label = new UILabel();
label.Text = "Tutorial";
label.Font.WithSize(36);
this.View.AddSubview(label.ViewForBaselineLayout);
// UITextView
textView = new UITextView();
textView.Editable = false;
textView.ScrollEnabled = true;
textView.UserInteractionEnabled = true;
textView.ViewForBaselineLayout.Frame = new CoreGraphics.CGRect(0, 0, this.View.Frame.Size.Width, this.View.Frame.Size.Height*3);
textView.Text = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. [shorten text for this post] "; // shorten text for this post
this.View.AddSubview(textView);
}
}
}
我猜你想要这样:
using System;
using System.Drawing;
using Foundation;
using UIKit;
using MediaPlayer;
using CoreGraphics;
namespace CHANGE_THIS_TO_YOUR_NAME_SPACE
{
public partial class VideoViewController : UIViewController
{
MPMoviePlayerController moviePlayer;
UILabel label;
UITextView textView;
public VideoViewController () : base ("VideoViewController", null)
{
}
public override void DidReceiveMemoryWarning ()
{
// Releases the view if it doesn't have a superview.
base.DidReceiveMemoryWarning ();
// Release any cached data, images, etc that aren't in use.
}
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
// Perform any additional setup after loading the view, typically from a nib.
moviePlayer = new MPMoviePlayerController (NSUrl.FromString ("http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4")); // Use FromString() to play video directly from web.
moviePlayer.View.Frame = new CGRect (0, 20, View.Frame.Size.Width, 180); // size of the video frame
moviePlayer.ScalingMode = MPMovieScalingMode.AspectFit; // show the video relative to the video size dimensions
moviePlayer.PrepareToPlay ();
moviePlayer.Play ();
View.Add (moviePlayer.View); // add the view after video starts playing to display it
// UILabel
label = new UILabel (new CGRect(0,200, View.Frame.Size.Width, 50));
label.Text = "Tutorial";
label.Font.WithSize (36);
View.Add (label.ViewForBaselineLayout);
// UITextView
textView = new UITextView ();
textView.Editable = false;
textView.ScrollEnabled = true;
textView.UserInteractionEnabled = true;
textView.ViewForBaselineLayout.Frame = new CGRect (0, 250, View.Frame.Size.Width, View.Frame.Size.Height * 3);
textView.Text = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. [shorten text for this post] "; // shorten text for this post
View.Add (textView);
}
}
}
基本上,当您使用 CGRect
和 new CGRect(x-coord, y-coord, width, height)
设置视图的框架时,您几乎已经完成了。由于所有视图均为 0,0,因此它们彼此重叠。 UITextView
也不会滚动,因为您已将其高度设置为屏幕高度的三倍。如果你想让它滚动,内容(文本)需要延伸到框架之外。
iOS9介绍UIStackView
观看来自 WWDC 2015 的视频:https://developer.apple.com/videos/wwdc/2015/?id=218 但如果您支持 iOS7/8,则有一些第三方实现。 Xamarin.Forms 有一个堆栈布局,所以这也可能是一个选项。
一个改进的解决方案是不设置视图的框架,而是像这样使用自动布局约束:
using System;
using System.Drawing;
using Foundation;
using UIKit;
using MediaPlayer;
using CoreGraphics;
namespace CHANGE_THIS_TO_YOUR_NAME_SPACE
{
public partial class VideoViewController : UIViewController
{
MPMoviePlayerController moviePlayer;
UILabel label;
UITextView textView;
public VideoViewController () : base ("VideoViewController", null)
{
}
public override void DidReceiveMemoryWarning ()
{
// Releases the view if it doesn't have a superview.
base.DidReceiveMemoryWarning ();
// Release any cached data, images, etc that aren't in use.
}
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
// Perform any additional setup after loading the view, typically from a nib.
moviePlayer = new MPMoviePlayerController (NSUrl.FromString ("http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4")); // Use FromString() to play video directly from web.
moviePlayer.View.TranslatesAutoresizingMaskIntoConstraints = false;
// moviePlayer.View.Frame = new CGRect (0, 20, View.Frame.Size.Width, 180); // size of the video frame
moviePlayer.ScalingMode = MPMovieScalingMode.AspectFit; // show the video relative to the video size dimensions
moviePlayer.PrepareToPlay ();
moviePlayer.Play ();
View.Add (moviePlayer.View); // add the view after video starts playing to display it
// UILabel
// label = new UILabel (new CGRect(0,200, View.Frame.Size.Width, 50));
label = new UILabel ();
label.TranslatesAutoresizingMaskIntoConstraints = false;
label.Text = "Tutorial";
label.Font.WithSize (36);
View.Add (label.ViewForBaselineLayout);
// UITextView
textView = new UITextView ();
textView.TranslatesAutoresizingMaskIntoConstraints = false;
textView.Editable = false;
textView.ScrollEnabled = true;
textView.UserInteractionEnabled = true;
// textView.ViewForBaselineLayout.Frame = new CGRect (0, 250, View.Frame.Size.Width, View.Frame.Size.Height * 3);
textView.Text = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. [shorten text for this post] "; // shorten text for this post
View.Add (textView);
SetUpAutoLayoutConstraints ();
}
private void SetUpAutoLayoutConstraints()
{
View.AddConstraints (new [] {
NSLayoutConstraint.Create(moviePlayer.View, NSLayoutAttribute.Width, NSLayoutRelation.Equal, View, NSLayoutAttribute.Width, 1, 0),
NSLayoutConstraint.Create(moviePlayer.View, NSLayoutAttribute.Height, NSLayoutRelation.Equal, View, NSLayoutAttribute.Width, 0.5625f, 0), // setting it to this to keep your aspect ratio
NSLayoutConstraint.Create(moviePlayer.View, NSLayoutAttribute.Top, NSLayoutRelation.Equal, View, NSLayoutAttribute.Top, 1, 20),
NSLayoutConstraint.Create(moviePlayer.View, NSLayoutAttribute.Left, NSLayoutRelation.Equal, View, NSLayoutAttribute.Left, 1, 0)
});
View.AddConstraints (new [] {
NSLayoutConstraint.Create(label, NSLayoutAttribute.Width, NSLayoutRelation.Equal, View, NSLayoutAttribute.Width, 1, 0),
NSLayoutConstraint.Create(label, NSLayoutAttribute.Height, NSLayoutRelation.Equal, null, NSLayoutAttribute.NoAttribute, 1, 50),
NSLayoutConstraint.Create(label, NSLayoutAttribute.Top, NSLayoutRelation.Equal, moviePlayer.View, NSLayoutAttribute.Bottom, 1, 0),
NSLayoutConstraint.Create(label, NSLayoutAttribute.Left, NSLayoutRelation.Equal, View, NSLayoutAttribute.Left, 1, 0)
});
View.AddConstraints (new [] {
NSLayoutConstraint.Create(textView, NSLayoutAttribute.Width, NSLayoutRelation.Equal, View, NSLayoutAttribute.Width, 1, 0),
NSLayoutConstraint.Create(textView, NSLayoutAttribute.Bottom, NSLayoutRelation.Equal, View, NSLayoutAttribute.Bottom, 1, 0),
NSLayoutConstraint.Create(textView, NSLayoutAttribute.Top, NSLayoutRelation.Equal, label, NSLayoutAttribute.Bottom, 1, 0),
NSLayoutConstraint.Create(textView, NSLayoutAttribute.Left, NSLayoutRelation.Equal, View, NSLayoutAttribute.Left, 1, 0)
});
}
}
}
这会让您的视图适应屏幕尺寸,例如在 iphone4,5,6,6+ iPad 上正确布局。如果它太大,你的 UITextView
会滚动。
关于自动布局的好教程here