From acf8e83cbf106b4350536d54eb46379dd86a623c Mon Sep 17 00:00:00 2001 From: Runt <qingingrunt2010@qq.com> Date: Fri, 04 Jul 2025 17:05:00 +0000 Subject: [PATCH] 输入弹框 图标修改 相机调整 --- LiveProject/activity/stream/LiveActivity.swift | 208 +++++++++++++++++++++++++++++++++++++++++++++++----- 1 files changed, 188 insertions(+), 20 deletions(-) diff --git a/LiveProject/activity/stream/LiveActivity.swift b/LiveProject/activity/stream/LiveActivity.swift index d6faae2..57e7890 100644 --- a/LiveProject/activity/stream/LiveActivity.swift +++ b/LiveProject/activity/stream/LiveActivity.swift @@ -5,46 +5,213 @@ // Created by 倪路朋 on 6/25/25. // -import Foundation +import UIKit +import AVFoundation import SwiftUI +import MetalKit struct LiveActivity: View { + + @State private var showDeviceDialog = false + @State private var showInputDialog = false + + @State private var streamRate = Float(9/16.0); + @State private var fpsState = 30; + @State private var mainSize: CGSize = .init(width: 100, height: 100) + + @State private var displaySize : CGSize = .zero; + + @State private var devices = [DeviceInfo(name: "相机", type: .CAMERA, deviceId: UUID().uuidString,icon: Icons.CAMERA), + DeviceInfo(name: "话筒", type: .MICROPHONE,deviceId: UUID().uuidString,icon: Icons.MIC), + DeviceInfo(name: "系统", type: .SYSTEM,deviceId : UUID().uuidString,icon: Icons.PORTRAIT)] + + + @StateObject private var mViewModel = LiveViewModel() + var body: some View { - NavigationView{ - ZStack{ + ZStack{ + Color.clear + .ignoresSafeArea() // 填满全屏 + VStack{ + VideoRendererView(pixelBuffer: $mViewModel.pixelBuffer).background(Color.black).frame(width: mainSize.width,height:mainSize.height) + Spacer() + }.border(Color.blue) + VStack{ + Spacer() + BottomBtns().frame(alignment: .bottom).border(Color.green) + } + if showInputDialog{ + DialogInput() + } + }.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .topLeading) + .background( + GeometryReader { geometry in + Color.clear + .onAppear { + displaySize = geometry.size; + updateWindowSize() + print("displaySize:\(displaySize)") + } + .onChange(of: geometry.size) { newSize in + displaySize = newSize; + updateWindowSize() + print("displaySize:\(displaySize)") + } + }) + .border(Color.red) + .onDisappear { + print("onDisappear 视图消失了!") + }.onAppear { + print("onAppear 视图出现了!") + } + } + + func updateWindowSize(){ + var rate : Float = Float(displaySize.width)/Float(displaySize.height); + if(rate != streamRate) { + var mainWidth = 0.0; + var mainHeight = 0.0; + if(rate < streamRate){ + mainWidth = displaySize.width; + if(9.0/16 == streamRate){ + mainHeight = (mainWidth / 9.0 * 16); + }else{ + mainHeight = (mainWidth / 16.0 * 9); + } + }else{ + mainHeight = displaySize.height; + if(9.0 / 16 == streamRate){ + mainWidth = (mainHeight / 16.0 * 9); + }else{ + mainWidth = (mainHeight / 9.0 * 16); + } + } + if(mainSize.width != CGFloat(mainWidth) || mainSize.height != CGFloat(mainHeight)){ + mainSize = .init(width: mainWidth, height: mainHeight); + } + }else{ + if(mainSize.width != displaySize.width || mainSize.height != displaySize.height){ + mainSize = .init(width: displaySize.width, height: displaySize.height); } } + print("updateWindow:\(mainSize)") } -} - -struct Bottombtns:View { - var body: some View { + + func DialogInput(onCancel:() ->Void = {},onConfirm:() -> Void = {}) -> some View{ + ZStack{ + Color.black.opacity(0.4) + .edgesIgnoringSafeArea(.all) + .onTapGesture { + withAnimation { + showInputDialog = false + } + } + VStack { + VStack(alignment: .leading, spacing: 40) { + Text("请输入直播地址") + .font(Font.system(size: 20)) + LTextField().environmentObject(LText()) + HStack{ + Spacer() + Button(action:{ + showInputDialog.toggle(); + }){ + Text("取消") + .font(Font.system(size: 20)) + .foregroundColor(Color.gray) + } + + Spacer().frame(width: 30) + Button(action:{ + showInputDialog.toggle(); + }){ + Text("确认") + .font(Font.system(size: 20)) + .foregroundColor(Color.colorTextLink) + } + + } + } + .padding(30) + .background(Color.white) + .cornerRadius(20) + .transition(.move(edge: .bottom)) + } + .padding(60) + .zIndex(1) + .animation(.default, value: devices) + } + } + + func DialogDevices() -> some View{ VStack{ - + VStack(spacing: 20) { + Spacer().frame(height:20) + FlowLayout(){ + + ForEach(devices, id: \.self) { device in + MButton(icon: device.icon,text: device.name){ + mViewModel.newWindowAction(device: device){ status in + withAnimation{ + showDeviceDialog = false; + } + } + print("\(device.name) click") + } + } + } + } + .frame(maxWidth: .infinity,alignment:.leading) + .padding() + } + .frame(maxHeight: .infinity,alignment:.topLeading) + } + + func BottomBtns() -> some View{ + VStack{ + HStack(){ - MButton(icon: IconPortrait()){ - + //横竖屏控制 + MButton(icon:streamRate == (9/16.0) ? Icons.PORTRAIT : Icons.LANDSCAPE ){ + streamRate = streamRate == (9/16.0) ? (16/9.0) : (9/16.0) + updateWindowSize() } - MButton(text: "30帧"){ - + // fps 控制 + MButton(text: "\(fpsState)帧"){ + fpsState = fpsState == 30 ? 60 : 30; } + //添加推流地址 MButton(valid: .INVALID,text: "+"){ } } HStack{ LButton(text: "设备"){ - - } + print("Click 设备 button") + showDeviceDialog.toggle() + }.sheet(isPresented:$showDeviceDialog, content: { + VStack { + ScrollView { + DialogDevices() + } + } + .presentationDetents([.height(200),.medium]) + }) LButton(text: "RTMP"){ - + print("Click RTMP button") + withAnimation{ + showInputDialog.toggle() + } } - LButton(text: "文件"){ + /*flLButton(text: "文件"){ - } + }*/ LButton(text: "文本"){ - + print("Click 文本 button") + withAnimation{ + showInputDialog.toggle() + } } } HStack{ @@ -56,9 +223,10 @@ } } -struct LiveActivity_Previews: PreviewProvider{ + +struct LiveActivity_BottomBtns_Previews: PreviewProvider{ static var previews: some View { - Bottombtns(); + LiveActivity(); } } -- Gitblit v1.9.1