У меня есть режим прокрутки в 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
Swift UI Включение звука видео в центре просмотра прокрутки ⇐ IOS
Программируем под IOS
-
Anonymous
1714974858
Anonymous
У меня есть режим прокрутки в Swift UI, в котором можно разместить различный контент, например текст или видео. Я хочу, чтобы видео воспроизводилось, когда они появляются, но включалось только тогда, когда они находятся в середине просмотра прокрутки, и одновременно можно включить только один видеопроигрыватель. В настоящее время я добиваюсь этого эффекта, но просмотр прокрутки становится очень медленным и глючным. Честно говоря, просмотр прокрутки немного тормозит, когда я прокручиваю видео, даже без этой функции. Как я могу сделать просмотр прокрутки очень плавным, одновременно имея возможность отображать несколько видеопроигрывателей и функцию включения звука?
Мой текущий подход заключается в размещении текущего «идентификатора» видео без звука внутри объекта среды, который можно получить доступ где угодно. В [b]MainTabView[/b] я отслеживаю положение каждого сообщения, и как только сообщение оказывается посередине (если в нем есть видео), переменной [b]currentAudio[/b] присваивается идентификатор этого сообщения. Внутри видеоплеера сообщений я слушаю изменения в этом опубликованном свойстве, и если новый идентификатор равен идентификатору видеоплеера, я включаю его. Если видео покидает середину представления прокрутки и [b]currentAudio[/b] равен этому идентификатору, я устанавливаю для переменной среды пустую строку, чтобы указать этому подпредставлению отключить звук.
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:443/v0/b/hustle-85b6c.appspot.com/o/stories%2F0FCE66A1-06F7-47CC-A38A-9A95192A2728.mp4?alt=media&token=57921e5a-e5e6-4b54-919b-39be9fbead84"),
allVids(id: UUID().uuidString, video: nil),
allVids(id: UUID().uuidString, video: "https://firebasestorage.googleapis.com:443/v0/b/hustle-85b6c.appspot.com/o/stories%2F0A514500-F1A0-4093-98A2-2847FE46484A.mp4?alt=media&token=69afd165-1ab6-4686-9ad2-2ce485090fe1"),
allVids(id: UUID().uuidString, video: "https://firebasestorage.googleapis.com:443/v0/b/hustle-85b6c.appspot.com/o/stories%2FE8937043-873E-4178-A90D-C6C03684C700.mp4?alt=media&token=ddc1f616-5427-4722-a96f-ab81739b243e"),
allVids(id: UUID().uuidString, video: nil),
allVids(id: UUID().uuidString, video: "https://firebasestorage.googleapis.com:443/v0/b/hustle-85b6c.appspot.com/o/stories%2F0FCE66A1-06F7-47CC-A38A-9A95192A2728.mp4?alt=media&token=57921e5a-e5e6-4b54-919b-39be9fbead84"),
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()
}
}
Подробнее здесь: [url]https://stackoverflow.com/questions/78434747/swift-ui-unmute-video-when-in-scroll-view-center[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия