SwiftUI自定义滑块遮罩异常:滑块靠近右端时轨道两端均圆角
修复SwiftUI自定义滑块轨道圆角问题
我用SwiftUI开发自定义滑块,采用RoundedRectangle作为未选中轨道,通过遮罩Rectangle实现进度显示。滑块处于中间位置时效果正常,但拖动到靠近右侧边缘时,未选中轨道的两端都会显示圆角,需要修复为仅右端显示圆角。
解决方案
问题根源是原代码使用了全圆角的RoundedRectangle,再通过leading padding控制轨道位置,当轨道宽度缩小时,两端圆角都会暴露。正确做法是给未选中轨道仅设置右端圆角,并直接计算其位置和宽度,避免padding导致的形状收缩问题。
修改后的完整代码
struct Slider: View { @Binding var progress: CGFloat private let stroke: CGFloat = 5.0 private var thumbWidth: CGFloat { stroke * 2 } private var thumbHeight: CGFloat { thumbWidth * 3.5 } var body: some View { GeometryReader { geometry in ZStack { Color.black.ignoresSafeArea() VStack { let sliderWidth = geometry.size.width - thumbWidth let thumbLeftX = progress * sliderWidth let activeTrackWidth = thumbLeftX let inactiveTrackWidth = geometry.size.width - (thumbLeftX + thumbWidth) ZStack(alignment: .leading) { // 选中的进度轨道 Rectangle() .fill(Color.white.opacity(0.5)) .frame(width: activeTrackWidth, height: stroke) // 未选中的背景轨道(仅右端圆角) RoundedRectangle(cornerRadius: stroke, corners: [.topRight, .bottomRight]) .frame(width: max(0, inactiveTrackWidth), height: stroke) .offset(x: thumbLeftX + thumbWidth) // 滑块Thumb Capsule() .fill(.red) .frame(width: thumbWidth, height: thumbHeight) .offset(x: thumbLeftX) .gesture( DragGesture() .onChanged { gesture in let newProgress = min(max(gesture.location.x / sliderWidth, 0), 1) progress = newProgress } ) } .frame(height: thumbHeight) } } } } } struct SliderView: View { @State private var progress: CGFloat = 0.0 var body: some View { ZStack { Color.black.ignoresSafeArea() Slider(progress: $progress) } } }
关键修改点
- 将全圆角RoundedRectangle替换为仅右端圆角的形状,用
RoundedRectangle(cornerRadius:stroke, corners: [.topRight, .bottomRight])确保左端始终为直角。 - 去掉padding控制轨道位置的方式,直接通过
offset和计算后的宽度定位未选中轨道,避免宽度收缩时暴露左端圆角。 - 调整进度计算逻辑,基于可滑动区域(总宽度减去thumb宽度)计算位置,确保thumb拖动到两端时轨道显示准确。
内容的提问来源于stack exchange,提问作者batman
相关产品推荐
相关产品推荐

