Swift UI Включение звука видео в центре просмотра прокруткиIOS

Программируем под IOS
Ответить
Anonymous
 Swift UI Включение звука видео в центре просмотра прокрутки

Сообщение Anonymous »

У меня есть режим прокрутки в Swift UI, в котором можно разместить различный контент, например текст или видео. Я хочу, чтобы видео воспроизводилось, когда они появляются, но включалось только тогда, когда они находятся в середине просмотра прокрутки, и одновременно можно включить только один видеопроигрыватель. В настоящее время я добиваюсь этого эффекта, но просмотр прокрутки становится очень медленным и глючным. Честно говоря, просмотр прокрутки немного тормозит, когда я прокручиваю видео, даже без этой функции. Как я могу сделать просмотр прокрутки очень плавным, одновременно имея возможность отображать несколько видеопроигрывателей и функцию включения звука?
Мой текущий подход заключается в размещении текущего «идентификатора» видео без звука внутри объекта среды, который можно получить доступ где угодно. В MainTabView я отслеживаю положение каждого сообщения, и как только сообщение оказывается посередине (если в нем есть видео), переменной currentAudio присваивается идентификатор этого сообщения. Внутри видеоплеера сообщений я слушаю изменения в этом опубликованном свойстве, и если новый идентификатор равен идентификатору видеоплеера, я включаю его. Если видео покидает середину представления прокрутки и currentAudio равен этому идентификатору, я устанавливаю для переменной среды пустую строку, чтобы указать этому подпредставлению отключить звук.
struct allVids: Identifiable, Hashable {
var id: String
var video: String?
}

class PopToRoot: ObservableObject {
@Published var currentAudio: String = ""
}

struct MainTabView: View {
@EnvironmentObject var popRoot: PopToRoot
@State var offset: CGFloat = 0.0
@State var someData: [allVids] = [
allVids(id: UUID().uuidString, video: "https://firebasestorage.googleapis.com: ... be9fbead84"),
allVids(id: UUID().uuidString, video: nil),
allVids(id: UUID().uuidString, video: "https://firebasestorage.googleapis.com: ... e485090fe1"),
allVids(id: UUID().uuidString, video: "https://firebasestorage.googleapis.com: ... 81739b243e"),
allVids(id: UUID().uuidString, video: nil),
allVids(id: UUID().uuidString, video: "https://firebasestorage.googleapis.com: ... be9fbead84"),
allVids(id: UUID().uuidString, video: nil)]

var body: some View {
GeometryReader { geometry in
ScrollViewReader { proxy in
ScrollView {
LazyVStack(spacing: 1){
ForEach(someData) { message in
MessageView(video: message)
.overlay(GeometryReader { proxy in
Color.clear
.onChange(of: offset, { _, _ in
if let vid_id = message.video {
let frame = proxy.frame(in: .global)
let bottomDistance = frame.minY - geometry.frame(in: .global).minY
let topDistance = geometry.frame(in: .global).maxY - frame.maxY
let diff = bottomDistance - topDistance
if bottomDistance < 0.0 && abs(bottomDistance) >= (frame.height / 2.0) {
if popRoot.currentAudio == vid_id + (message.id ?? "") {
popRoot.currentAudio = ""
}
} else if topDistance < 0.0 && abs(topDistance) >= (frame.height / 2.0) {
if popRoot.currentAudio == vid_id + (message.id ?? "") {
popRoot.currentAudio = ""
}
} else if abs(diff) < 140 && abs(diff) > -140 {
popRoot.currentAudio = vid_id + (message.id ?? "")
}
}
})
})
}
}
.background(GeometryReader {
Color.clear.preference(key: ViewOffsetKey.self,
value: -$0.frame(in: .named("scroll")).origin.y)
})
.onPreferenceChange(ViewOffsetKey.self) { value in
offset = value
}
}
}
}.ignoresSafeArea()
}
}

struct MessageView: View {
let video: allVids

var body: some View {
VStack {
if let url = URL(string: video.video ?? "") {
MessageVideoPlayer(url: url, viewID: video.id)
} else {
Text("This sub view does not contain a video")
}
}
}
}

struct MessageVideoPlayer: View {
@EnvironmentObject var popRoot: PopToRoot
@State var player: AVPlayer? = nil
let url: URL
@State var viewID: String

init(url: URL, viewID: String? = nil) {
self.url = url
_viewID = State(initialValue: viewID ?? UUID().uuidString)
}

var body: some View {
ZStack {
if let vid = player {
VidPlayer(player: vid)
}
}
.frame(width: 150, height: 200)
.onChange(of: popRoot.currentAudio) { _, _ in
if popRoot.currentAudio != (url.absoluteString + viewID) {
player?.isMuted = true
} else if appeared {
player?.isMuted = false
}
}
.onAppear {
if player == nil {
player = AVPlayer(url: url)
}

if popRoot.currentAudio.isEmpty || popRoot.currentAudio == (url.absoluteString + viewID) {
self.player?.isMuted = false
popRoot.currentAudio = url.absoluteString + viewID
} else {
self.player?.isMuted = true
}

self.player?.play()
}
.onDisappear {
if popRoot.currentAudio == (url.absoluteString + viewID) {
popRoot.currentAudio = ""
}
self.player?.pause()
}
}
}

//not important

struct VidPlayer : UIViewControllerRepresentable {
var player : AVPlayer

func makeUIViewController(context: UIViewControllerRepresentableContext) -> AVPlayerViewController {

let controller = AVPlayerViewController()
controller.player = player
controller.showsPlaybackControls = false
controller.allowsVideoFrameAnalysis = false
controller.videoGravity = .resizeAspectFill
return controller
}

func updateUIViewController(_ uiViewController: AVPlayerViewController, context: UIViewControllerRepresentableContext) { }
}

struct ViewOffsetKey: PreferenceKey {
typealias Value = CGFloat
static var defaultValue = CGFloat.zero
static func reduce(value: inout Value, nextValue: () -> Value) {
value += nextValue()
}
}


Подробнее здесь: https://stackoverflow.com/questions/784 ... iew-center
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «IOS»