如何在特定上下文中将 hstack 的大小与其父视图相匹配?

问题描述 投票:0回答:1

我正在尝试在 SwiftUI 中重新创建 Whatsapp 的消息回复功能。

基本上我有一个表示消息的视图,消息的最大宽度为 300。因此,当消息链接有较旧的消息(已回复的消息)时,它将被放置在消息的顶部就像whatsapp一样。

问题是,我希望旧消息扩展到与消息相同的大小。 (检查我附加的图片看看出了什么问题)

当旧消息与回复大小相同/更长时

当旧消息比回复短时

正如您在第二张图片中看到的,我需要深蓝色背景一直延伸。

但是,我不想让宽度无限大,因为我不希望它一直延伸,除非回复这样做。如果这是有道理的话。我只是想让旧的消息背景与回复相匹配,而不会让回复右侧有很多空白。

这是我的代码:

struct DMMessageBubbleReceiver: View{
    
    let impactMed = UIImpactFeedbackGenerator(style: .medium)
    
    @State var message: Message
    
    @State private var showActionSheet = false
    
    @State var userUID: String
    
    @State var showEmojis = false
    
    @State private var scale: CGFloat = 0.5
    
    @State var emojis = ["😂", "❤️", "👍", "👎", "✈️", "☠️"]
    
    @Binding var blurEverything: String
    
    @ObservedObject var homeData = HomeViewModel.shared
    
    @State private var offsetX: CGFloat = 0
    @Binding var isReplying: Bool
    @Binding var replyToMessage: MsgReply
    
    var body: some View {
        
        VStack(alignment: .leading, spacing: 0) {
            
            if showEmojis {
                
                HStack(spacing: 17) {
                    
                    ForEach(emojis, id: \.self) { emoji in
                        Button(action: {
                            impactMed.impactOccurred()
                            withAnimation {
                                showEmojis.toggle()
                                blurEverything = ""
                            }
                            homeData.addRemoveEmoji(message: message, emoji: emoji, userUID: userUID)
                        }) {
                            Text(emoji)
                                .font(.custom("Poppins-Regular", fixedSize: 18))
                        }
                    }
                }
                .padding(.horizontal).padding(.vertical, 5)
                .background(Color(UIColor.systemGray5).cornerRadius(50))
                .padding(.bottom, 5)
                .scaleEffect(scale)
                .onAppear {
                    withAnimation(.easeInOut(duration: 0.3)) {
                        scale = 1.2
                        DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
                            impactMed.impactOccurred()
                            withAnimation(.easeInOut(duration: 0.3)) {
                                scale = 1.0
                            }
                        }
                    }
                }
            }
            
            HStack {
                
                HStack {
                    
                    if message.deleted != true {
                        
                        ZStack(alignment: .bottomTrailing) {
                            
                            VStack(alignment: .leading, spacing: 0){
                                
                                if let reply = message.reply{
                                    
                                    HStack{
                                        
                                        VStack(alignment: .leading, spacing: 5){
                                            
                                            Text("You")
                                                .font(.custom("Gilroy-Medium", fixedSize: 12))
                                                .foregroundColor(.blue)
                                                .lineSpacing(5)
                                            
                                            Text(reply.msg)
                                                .font(.custom("Gilroy-Medium", fixedSize: 13))
                                                .foregroundColor(.black)
                                                .lineSpacing(5)
                                                .lineLimit(3)
                                            
                                        }
                                        
                                    }.padding(10).background(Color.blue.opacity(0.07).cornerRadius(5)).padding(.horizontal, 5).padding(.top, 5)
                                    
                                }
                                
                                Text(filterLinksInText(message.text))
                                    .font(.custom("Gilroy-Medium", fixedSize: 15))
                                    .foregroundColor(.black)
                                    .lineSpacing(5)
                                    .padding(.vertical, 14).padding(.leading, 10).padding(.trailing, 15)
                                    
                                
                            }
                            .background(Color(UIColor.systemGray5).opacity(0.6))
                            .cornerRadius(12, corners: [.topLeft, .topRight, .bottomRight])
                            .offset(x: offsetX)
                            .gesture(
                                DragGesture()
                                    .onChanged { value in
                                        if message.deleted == false {
                                            if value.translation.width > 0 {
                                                offsetX = value.translation.width
                                            }
                                        }
                                    }
                                    .onEnded { value in
                                        if offsetX > 100 {
                                            
                                            impactMed.impactOccurred()
                                            
                                            withAnimation {
                                                isReplying = true
                                                replyToMessage = MsgReply(id: message.id, msg: message.text, name: "name")
                                                offsetX = 0
                                            }
                                        } else {
                                            withAnimation {
                                                offsetX = 0
                                            }
                                        }
                                    }
                            )
                            
                            if message.emoji != "" {
                                Text(message.emoji)
                                    .font(.system(size: 12))
                                    .foregroundColor(.red)
                                    .padding(3)
                                    .background(Color("messagebackground"))
                                    .cornerRadius(50)
                                    .offset(y: 8)
                                    .offset(x: 8)
                            }
                        }
                    } else {
                        Text("This message was deleted")
                            .font(Font.system(size: 13))
                            .italic()
                            .fontWeight(.medium)
                            .foregroundColor(.black.opacity(0.6))
                            .padding(.horizontal)
                            .padding(.vertical, 10)
                            .background(Color(UIColor.systemGray5))
                            .cornerRadius(12, corners: [.topLeft, .topRight, .bottomRight])
                    }
                }
                .frame(maxWidth: 300, alignment: .leading)

                Spacer()
                
                ZStack(alignment: .bottomTrailing) {
                    Text(" ")
                }.padding(.trailing)
                
            }
            
            Text("\(message.timestamp.formatted(.dateTime.hour().minute()))")
                .font(.custom("Gilroy-Medium", fixedSize: 11))
                .foregroundColor(.black.opacity(0.3))
                .padding(.leading, 5).padding(.top, 8).padding(.bottom, 10)
        }
        .frame(maxWidth: .infinity, alignment: .leading)
        .padding(.leading)
        .padding(.horizontal, 10)
        .blur(radius: (blurEverything != "" && blurEverything != message.id) ? 2 : 0)
        .onTapGesture(count: 2) {
            if message.deleted != true{
                self.likeMessage(message: message)
            }
        }
        .onTapGesture(count: 1) {
            if message.deleted == false {
                withAnimation {
                    showEmojis.toggle()
                    if blurEverything != "" {
                        blurEverything = ""
                    } else {
                        blurEverything = message.id
                    }
                }
            }
        }
        .onLongPressGesture {
            showActionSheet = true
        }
        .actionSheet(isPresented: $showActionSheet) {
            ActionSheet(title: Text("Message Options"), buttons: getButtons(message: message))
        }
    }
    
    func getButtons(message: Message) -> [ActionSheet.Button] {
        var buttons: [ActionSheet.Button] = []
        
        if message.deleted != true {
            buttons.append(.default(Text("Copy"), action: {
                self.copyText(message: message.text)
            }))
        }
        
        if message.deleted != true {
            if message.numLikes > 0 {
                buttons.append(.default(Text("Unlike"), action: { self.likeMessage(message: message) }))
            } else {
                buttons.append(.default(Text("Like"), action: { self.likeMessage(message: message) }))
            }
        }

        if message.deleted == false {
            buttons.append(.destructive(Text("Delete"), action: {
                self.deleteMessage()
            }))
        }

        buttons.append(.cancel(Text("Cancel")))

        return buttons
    }

    func copyText(message: String) {
        UIPasteboard.general.string = message
    }

    func likeMessage(message: Message) {
        impactMed.impactOccurred()
        homeData.likeDMMessage(message: message, userUID: userUID)
    }
    
    func deleteMessage() {
        impactMed.impactOccurred()
        homeData.deleteDMMessage(userUID: userUID, message: message)
    }
    
    func filterLinksInText(_ text: String) -> String {
        do {
            let regexPattern = try NSRegularExpression(pattern: "https?://([-\\w\\.]+)+(:\\d+)?(/([\\w/_\\.]*(\\?\\S+)?)?)?", options: .caseInsensitive)
            let modifiedText = regexPattern.stringByReplacingMatches(
                in: text,
                options: [],
                range: NSRange(location: 0, length: text.utf16.count),
                withTemplate: "****"
            )
            return modifiedText
        } catch {
            return text
        }
    }
}
ios swift xcode swiftui
1个回答
0
投票

您的

reply
视图没有宽度限制来填充其父级。因此,您需要添加
Spacer
或设置
frame(maxWidth: .infinity)
。由于其父级上有
.frame(maxWidth: 300)
,因此它不会被淹没。

VStack(alignment: .leading, spacing: 0) {
    if let reply = message.reply {
        HStack {
            ...
            
            Spacer() //<- here
        }
        //.frame(maxWidth: .infinity, alignment: .leading) //<- or here
    }
}

输出:

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.