59

ビデオを表示するためのUIViewを含むがあります。AVPlayer向きを変えるときは、ビデオのサイズと場所を変える必要があります。

レイヤーのサイズ変更の経験があまりないため、ビデオのサイズ変更に問題があります。

まず、を作成し、AVPlayerそのプレーヤーをvideoHolderViewのレイヤーに追加します。

NSURL *videoURL = [NSURL fileURLWithPath:videoPath];
self.avPlayer = [AVPlayer playerWithURL:videoURL];

AVPlayerLayer* playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.avPlayer];
playerLayer.frame = videoHolderView.bounds;
playerLayer.videoGravity = AVLayerVideoGravityResizeAspect;
playerLayer.needsDisplayOnBoundsChange = YES;

[videoHolderView.layer addSublayer:playerLayer];
videoHolderView.layer.needsDisplayOnBoundsChange = YES;

次に、後で、videoHolderViewのフレームのサイズと場所を変更します。

[videoHolderView setFrame:CGRectMake(0, 0, 768, 502)];

この時点で、avPlayerをこれらの同じサイズにサイズ変更する必要があります。これは自動的には発生しません。avPlayerはvideoHolderView内で小さいサイズのままです。

誰かが助けてくれるなら、私は本当にアドバイスをいただければ幸いです。

みんなありがとう。

4

13 に答える 13

66
  playerLayer.videoGravity = AVLayerVideoGravityResizeAspectFit;
于 2015-04-13T22:33:18.920 に答える
37

@SuranのソリューションをSwiftに変換する:

まず、UIViewを継承するクラスを作成します。このクラスでは、1つの変数のみをオーバーライドします。

import UIKit
import AVFoundation

class AVPlayerView: UIView {
    override class var layerClass: AnyClass {
        return AVPlayerLayer.self
    }
}

次に、Interface Builderを使用して単純なUIViewを追加し、そのクラスを作成したばかりのAVPlayerViewに変更します。

通常のUIViewのクラスをAVPlayerViewに変更します

次に、そのビューのアウトレットを作成します。それをavPlayerViewと呼びます

@IBOutlet weak var avPlayerView: AVPlayerView!

これで、ビューコントローラ内でそのビューを使用して、次のようにそのavlayerにアクセスできます。

let avPlayer = AVPlayer(url: video)
let castLayer = avPlayerView.layer as! AVPlayerLayer
castLayer.player = avPlayer
avPlayer.play()

レイヤーは、通常のレイヤーと同じように制約に従います。境界やサイズを手動で変更する必要はありません。

于 2017-01-16T18:03:22.200 に答える
21

実際には、AVPlayerのレイヤーをサブレイヤーとして追加しないでください。その代わりに、AVPlayerを表示するビューのサブクラスで次のメソッドを使用する必要があります。

+ (Class)layerClass
{
     return [AVPlayerLayer class];
}

そして、次の行を使用して、プレーヤーレイヤーを追加(設定)します。

[(AVPlayerLayer *)self.layer setPlayer:self.avPlayer];

それが役に立てば幸い;-)

于 2015-01-26T14:01:51.073 に答える
16

結局、私はAVPlayerLayerをUIViewに再度追加することでこれを解決しました。フレームを変更するとレイヤーが削除された理由はわかりませんが、削除されました。最終的な解決策は次のとおりです。

//amend the frame of the view
[videoHolderView setFrame:CGRectMake(0, 0, 768, 502)];

//reset the layer's frame, and re-add it to the view
AVPlayerLayer* playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.avPlayer];
playerLayer.frame = videoHolderView.bounds;
[videoHolderView.layer addSublayer:playerLayer];
于 2012-04-17T17:21:24.190 に答える
14

修正への複数のアプローチを示すMarcoSantarossaによる素晴らしい記事を見つけました。https://marcosantadev.com/calayer-auto-layout-swift/

私は彼の最初の提案を使用して、viewDidLayoutSubViews()イベント中にレイヤーフレームをリセットしました。

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    playerLayer.frame = view.layer.bounds
}
于 2017-08-02T12:06:35.703 に答える
8

-layoutSubviewsメソッドをオーバーライドすることで、レイヤーのフレームを変更できます。

- (void)layoutSubviews
{
    [super layoutSubviews];
    self.playerLayer.frame = self.bounds;
}
于 2015-10-10T22:11:47.807 に答える
7

Swift4では

    playerLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill

AVLayerVideoGravityまたはあなたの望むプロパティ。

于 2019-09-19T09:26:39.417 に答える
3

theDuncの答えは私にはうまくいきませんでした。より簡単な解決策を見つけました。UIViewで変更した後、AVPlayerLayerのフレームを調整する必要がありました。

avPlayerLayer.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);

このブログでは、ビューのフレームがその中のレイヤーのフレームにも影響を与えると述べられています。

ビューのフレームを変更すると、レイヤーのフレームが変更されるだけです。

この場合、それは真実ではありません。

于 2015-01-22T15:43:29.447 に答える
2

Swift 2.3でこの問題が発生し、適切なPlayerViewクラスを記述して、それをサブビューとして設定することを解決しました。

import UIKit
import AVKit
import AVFoundation

class PlayerPreviewView: UIView {

    override class func layerClass() -> AnyClass {
        return AVPlayerLayer.self
    }

    var player: AVPlayer? {
        get {
            return playerLayer.player
        }

        set {
            playerLayer.player = newValue
        }
    }

    var playerLayer: AVPlayerLayer {
        return layer as! AVPlayerLayer
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
        playerLayer.videoGravity = AVLayerVideoGravityResize
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        playerLayer.videoGravity = AVLayerVideoGravityResize
    }

}

提示するViewControllerでは:

private func play(asset asset: AVURLAsset){
    let playerItem = AVPlayerItem(asset: asset)

    player = AVPlayer(playerItem: playerItem)
    player?.actionAtItemEnd = .None
    player?.muted = true

    playerPreviewView = PlayerPreviewView(frame: CGRectZero)
    view.addSubview(playerPreviewView)
    playerPreviewView.player = player


    playerPreviewView.translatesAutoresizingMaskIntoConstraints = false
    view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-0-[subview]-0-|", options: .DirectionLeadingToTrailing, metrics: nil, views: ["subview": playerPreviewView]))
    view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-0-[subview]-0-|", options: .DirectionLeadingToTrailing, metrics: nil, views: ["subview": playerPreviewView]))


    player?.play()

    NSNotificationCenter.defaultCenter().addObserver(self,
                                                     selector: #selector(SplashScreenViewController.videoDidFinish),
                                                     name: AVPlayerItemDidPlayToEndTimeNotification,
                                                     object: nil)
}
于 2016-09-13T14:37:08.333 に答える
1

最初のステップ:UIVIew.hでUIViewの自動サイズ変更プロパティを確認します

@property(nonatomic)UIViewAutoresizing autoresizingMask; //単純なサイズ変更。デフォルトはUIViewAutoresizingNoneです

このプロパティは、IBの「スプリングとストラット」コントロールに対応していますが、必要な結果を得るにはある程度の実験が必要です。

于 2012-04-12T15:14:41.177 に答える
1

に到達するにplayerLayerは、ループしてそれぞれを変更する必要がありますvideoHolderView.layer.sublayers

これは私がSwift2.2で行ったことです

if let sublayers = videoHolderView.layer.sublayers{
    for layer in sublayers where layer is AVPlayerLayer{
        layer.frame.size = ... // change size of the layer here
    }
}
于 2016-07-20T22:32:14.640 に答える
1

デバイスの回転中にAVPlayerのサイズ変更のみを行う場合は、以下に示すように、viewWillTransition(サイズ:CGSize、コーディネーター:UIViewControllerTransitionCoordinatorを使用)メソッドでレイヤーフレームを変更できます。

//Swift 4
//Method in UIViewController
//Variable definitions are:
//self.layer is the AVPlayerLayer
//self.videoPlayerView is the view that the AVPlayerLayer is the sublayer of
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    super.viewWillTransition(to: size, with: coordinator)
    coordinator.animate(alongsideTransition: { context in
        self.layer.layoutIfNeeded()
        UIView.animate(
            withDuration: context.transitionDuration,
            animations: {
                self.layer.frame = self.videoPlayerView.bounds
            }
        )
    }, completion: nil)
}

これにより、回転中に他のすべてのビューとともにレイヤーフレームがアニメーション化されます。

于 2018-05-21T01:54:59.933 に答える
0

私が検索していたときにXamarinバージョンを検索している人

AVPlayerLayerをサブレイヤーとして追加せずに、レイヤーをAvplayerレイヤーに設定します

[Export("layerClass")]
public static Class LayerClass()
{
    return new Class(typeof(AVPlayerLayer));
}

次の行はレイヤーを設定します

(this.Layer as AVPlayerLayer).Player = _player;   // Acplayer
于 2016-08-13T18:01:44.943 に答える