You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI中Deal与Discard按钮不显示问题求助

解决按钮不显示及布局调整问题

问题原因

你的Toolbar无法显示是因为SwiftUI的toolbar修饰符需要配合NavigationStack(iOS 16+)或NavigationView(iOS 15及以下)使用,没有这些容器时,工具栏不会被渲染。

布局方案选择

如果你的需求是让按钮显示在屏幕中央,直接将按钮嵌入主布局的VStack中比用Toolbar更直接合理,不需要依赖导航容器。

修改后的完整代码

import SwiftUI

struct Card: Hashable {
    let rank: String
    let suit: String
}

struct ContentView: View {
    let ranks = ["2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"]
    let suits = ["clubs", "diamonds", "hearts", "spades"]
    let cardWidth: CGFloat = 100
    let cardHeight: CGFloat = 150
    
    @State private var playerHand: [Card] = []
    @State private var deck: [Card] = []
    @State private var discardPile: [Card] = []
    @State private var deckImages: [String] = []
    
    private func createDeck() -> [Card] {
        var deck = [Card]()
        for suit in suits {
            for rank in ranks {
                deck.append(Card(rank: rank, suit: suit))
            }
        }
        return deck
    }
    
    private func deal() {
        guard let card = deck.first else { return }
        playerHand.append(card)
        deck.removeFirst()
        deckImages.removeFirst()
    }
    
    private func discard() {
        guard let card = playerHand.first else { return }
        discardPile.append(card)
        playerHand.removeFirst()
    }
    
    var body: some View {
        VStack(spacing: 30) {
            // 玩家手牌区域
            HStack {
                ForEach(playerHand, id: \.self) { card in
                    Image(card.rank + "_of_" + card.suit)
                        .resizable()
                        .frame(width: cardWidth, height: cardHeight)
                }
            }
            
            // 中央操作按钮组
            HStack(spacing: 40) {
                Button("Deal") {
                    deal()
                }
                .buttonStyle(.borderedProminent)
                
                Button("Discard") {
                    discard()
                }
                .buttonStyle(.borderedProminent)
            }
            
            // 牌堆与弃牌堆区域
            HStack {
                VStack {
                    Image(deckImages.first ?? "card_back")
                        .resizable()
                        .frame(width: cardWidth, height: cardHeight)
                    
                    Text("Cards left: \(deck.count)")
                }
                
                Spacer()
                
                VStack {
                    ForEach(discardPile, id: \.self) { card in
                        Image(card.rank + "_of_" + card.suit)
                            .resizable()
                            .frame(width: cardWidth, height: cardHeight)
                    }
                    
                    Text("Cards discarded: \(discardPile.count)")
                }
            }
        }
        .padding()
        .onAppear {
            deck = createDeck().shuffled()
            deckImages = deck.map { $0.rank + "_of_" + $0.suit }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

关键修改点

  • 移除了原有的.toolbar修饰符,将Deal和Discard按钮放在主VStack的中间位置,用HStack横向排列并设置间距
  • 给按钮添加了.buttonStyle(.borderedProminent)让按钮更醒目(可选,可根据需求调整样式)
  • 调整了主VStack的spacing,让布局更均衡

如果坚持要用Toolbar实现底部工具栏,只需将整个VStack包裹在NavigationStack中即可:

NavigationStack {
    // 原VStack内容
}
.toolbar {
    ToolbarItem(placement: .bottomBar) {
        Button("Deal") { deal() }
    }
    ToolbarItem(placement: .bottomBar) {
        Button("Discard") { discard() }
    }
}

内容的提问来源于stack exchange,提问作者Justin Kachornvanich

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 20:09:25