Created
July 17, 2023 09:52
-
-
Save Koshimizu-Takehito/688f57c8f447f46bea7492f09c72d5be to your computer and use it in GitHub Desktop.
カスタムなセグメントコントロール
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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