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

如何让SwiftUI矩形固定在基准线上绘制?

问题

我想要创建一个音频平衡控件,用两个矩形分别表示左右声道的声像(pan)值,目前通过滑块输入数值。但无论调整Geometry、基线和对齐方式,矩形始终悬浮无法固定在底部,希望调整高度时从底部向上变化而非从中部扩展。

相关代码如下:

import Foundation
import SwiftUI

struct PanView: View {
  @Binding var value: Double
    
    var body: some View {
        HStack(spacing: 10) {
          leftBar
          rightBar
        }
    }
    
    private var leftBar: some View {
      Rectangle()
        .fill(Color(.green))
        .frame(width: barWidth,
               height: abs(value - 50),
               alignment: .bottom)
    }
    
    private var rightBar: some View {
      Rectangle()
        .fill(Color(.red))
        .frame(width: barWidth,
               height: abs(value + 50),
               alignment: .bottom)
    }
    
    private var barWidth: CGFloat {
      return 50 // Adjust the width as per your preference
    }
  }

struct PanView_Used: View {
  @State private var barValue:Double = 0.0
  
  var body: some View {
    VStack {
      Text("Bar Graph at \(Int(barValue))")
        .font(.title)
      
      PanView(value: $barValue)
      
      Slider(value: $barValue, in: -50...50, step:Double.Stride(1), onEditingChanged: {e in})
    }
  }
}

struct  PV_Previews: PreviewProvider {
  static var previews: some View {
    PanView_Used()
  }
}

当前效果不佳:
效果截图1 效果截图2 效果截图3

解决方案

核心问题是未给PanView设置固定高度基准,且单个条形未锚定到底部容器。修改后的实现如下:

import Foundation
import SwiftUI

struct PanView: View {
    @Binding var value: Double
    // 定义条形最大高度,可按需调整
    private let maxBarHeight: CGFloat = 200
    
    var body: some View {
        HStack(spacing: 10) {
            leftBar
            rightBar
        }
        // 给整个控件设置固定高度,作为布局基准
        .frame(height: maxBarHeight)
    }
    
    private var leftBar: some View {
        Rectangle()
            .fill(Color(.green))
            .frame(width: barWidth)
            // 计算高度:value=-50时左条满高,value=50时左条高度为0
            .frame(height: CGFloat((50 - value) / 100 * maxBarHeight))
            // 锚定底部,高度变化时向上扩展
            .frame(maxHeight: .infinity, alignment: .bottom)
    }
    
    private var rightBar: some View {
        Rectangle()
            .fill(Color(.red))
            .frame(width: barWidth)
            // 计算高度:value=50时右条满高,value=-50时右条高度为0
            .frame(height: CGFloat((50 + value) / 100 * maxBarHeight))
            // 锚定底部,高度变化时向上扩展
            .frame(maxHeight: .infinity, alignment: .bottom)
    }
    
    private var barWidth: CGFloat {
        return 50 // 按需调整宽度
    }
}

struct PanView_Used: View {
    @State private var barValue: Double = 0.0
    
    var body: some View {
        VStack(spacing: 20) {
            Text("Bar Graph at \(Int(barValue))")
                .font(.title)
            
            PanView(value: $barValue)
            
            Slider(value: $barValue, in: -50...50, step: 1)
        }
        .padding()
    }
}

struct PV_Previews: PreviewProvider {
    static var previews: some View {
        PanView_Used()
    }
}

关键改动说明:

  • 新增maxBarHeight常量,统一控制条形高度上限,明确布局基准;
  • 给PanView的HStack设置固定高度,确保控件有稳定的布局范围;
  • 调整高度计算逻辑,通过线性映射实现滑块值与条形高度的对应关系;
  • 给每个条形添加.frame(maxHeight: .infinity, alignment: .bottom),让条形锚定底部,高度变化时从底部向上扩展。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 17:17:16