Search code examples
xamarin.iosavplayerstackview

AvPlayer inside a StackView


I have a vertical StackView containing, in order, an UILabel and a set of UIButton (made possible thanks to a horizontal StackView. I need to insert a video between the UILabel and UIButtons, as second element, using AVPlayer.

Can you suggest me the best way to do that? I'm trying using generic UIView and passing to it frame and sublayer, but it doesn't work. I'm working with Xamarin iOS/tvOS (so in C#) but i can read examples in Swift

Thanks

UPDATE

At the end issue was about using wrongly uiview frame.

I set my layout structure by iOS designer, not programmatically as suggested, but thanks to @land user for these code lines:

contentView.Layer.AddSublayer(playerLayer);
//update its frame immediately
contentView.LayoutIfNeeded();
playerLayer.Frame = contentView.Bounds;

Lewix


Solution

  • You can try to create a UIView to display the AVPlayerLayer and set its position to layout your AVPlayer. We can either put this contentView in StackView or outside the StackView in the ViewController's View.

    I recommend to put this view directly in the ViewController's View so that we can use autolayout to layout it.

    Firstly, I create a UIView whose top constraint equal to your Vertical StackView's bottom constraint and bottom constraint equal to your horizontal StackView's top constraint like:

    UIView contentView = new UIView();
    contentView.TranslatesAutoresizingMaskIntoConstraints = false;
    View.AddSubview(contentView);
    
    NSLayoutConstraint topConstraint = NSLayoutConstraint.Create(contentView, NSLayoutAttribute.Top, NSLayoutRelation.Equal, VerticalStackView, NSLayoutAttribute.Bottom, 1, 0);
    NSLayoutConstraint leadConstraint = NSLayoutConstraint.Create(contentView, NSLayoutAttribute.Leading, NSLayoutRelation.Equal, View, NSLayoutAttribute.Leading, 1, 0);
    NSLayoutConstraint trailConstraint = NSLayoutConstraint.Create(contentView, NSLayoutAttribute.Trailing, NSLayoutRelation.Equal, View, NSLayoutAttribute.Trailing, 1, 0);
    NSLayoutConstraint heightConstraint = NSLayoutConstraint.Create(contentView, NSLayoutAttribute.Height, NSLayoutRelation.Equal, null, NSLayoutAttribute.NoAttribute, 0, 100);
    NSLayoutConstraint bottomConstraint = NSLayoutConstraint.Create(contentView, NSLayoutAttribute.Bottom, NSLayoutRelation.Equal, HorizontalStackView, NSLayoutAttribute.Top, 1, 0);
    
    View.AddConstraints(new NSLayoutConstraint[] { topConstraint, leadConstraint, trailConstraint, bottomConstraint });
    contentView.AddConstraint(heightConstraint);
    

    Then you can put your AVPlayerLayer in this view and let its frame equal to this view like:

    AVPlayerItem playerItem = new AVPlayerItem(new NSUrl(NSBundle.MainBundle.PathForResource("test.mp4", null), false));
    aVPlayer = new AVPlayer(playerItem);
    AVPlayerLayer playerLayer = AVPlayerLayer.FromPlayer(aVPlayer);
    
    contentView.Layer.AddSublayer(playerLayer);
    //update its frame immediately
    contentView.LayoutIfNeeded();
    playerLayer.Frame = contentView.Bounds;
    

    If you do want to achieve this in StackView. Just put the contentView in the StackView and set its height constraint to show the AVPlayer.