Skip to content

Instantly share code, notes, and snippets.

@Koshimizu-Takehito
Created July 17, 2023 09:52
Show Gist options
  • Save Koshimizu-Takehito/688f57c8f447f46bea7492f09c72d5be to your computer and use it in GitHub Desktop.
Save Koshimizu-Takehito/688f57c8f447f46bea7492f09c72d5be to your computer and use it in GitHub Desktop.
カスタムなセグメントコントロール
import SwiftUI
struct ContentView: View {
@State var selectedIndex = 0
let options = ["Apple", "Orange", "Muscat"]
let colors: [Color] = [.red, .orange, .green]
var body: some View {
VStack {
SegmentedControl(selectedIndex: $selectedIndex, options: options, colors: colors)
.frame(height: 60)
Text(options[selectedIndex])
.font(.largeTitle.bold())
.foregroundStyle(colors[selectedIndex])
}
.padding(.horizontal, 12)
}
}
/// カスタムのセグメントコントロール
struct SegmentedControl: View {
@Binding var selectedIndex: Int
var options: [String]
var colors: [Color]
var color: Color { colors[selectedIndex] }
@State var size = CGSize.zero
var body: some View {
ZStack(alignment: .leading) {
// 背景
color.opacity(0.2)
.background(Color.white)
// 現在の選択値
let width = size.width/CGFloat(max(options.count, 1))
Color.clear
.frame(width: width)
.overlay(alignment: .center) {
Rectangle()
.fill(color)
.cornerRadius(size.height/2)
.padding(size.height/10)
.offset(x: width * CGFloat(selectedIndex))
.shadow(radius: size.height/40, x: size.height/40, y: size.height/40)
}
// 現在の選択値のリスト
HStack(spacing: 0) {
ForEach(options.indices, id:\.self) { index in
Text(options[index])
.fontWeight(.bold)
.foregroundStyle((selectedIndex == index) ? .white : color)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.white.opacity(0.001))
.onTapGesture {
withAnimation(.spring(duration: 0.5, bounce: 0.3)) {
selectedIndex = index
}
}
}
}
}
.cornerRadius(size.height/2)
.background {
GeometryReader { geometry in
Color.clear.frame(maxWidth: .infinity, maxHeight: .infinity)
.onChange(of: geometry.size, initial: true) { _, new in
size = new
}
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment