Sliderで値を選択する・Sliderの色を変える
Published by @SoNiceInfo at 3/2/2021
指定した範囲をユーザに選択してもらうにはSlider
を使います。
Sliderの基本的な使い方から応用方法、色をデフォルトから変える方法を紹介します。
Slider
の基本的な使い方
デフォルトではSliderの範囲は0から1の範囲でFloatやDoubleが使えます。
- 範囲を変更するにはin
を使用します。
- step
を利用することで段階を変更することが可能です。(デフォルトでは少数点以下かなり細かいです。)
- onEditingChanged
もしくはクロージャを渡すことで、ユーザがスライダーを移動してる最中か否かを取得できます。
- accentColor
を使うことによりスライダーの色を変更できます。
//
// ContentView.swift
//
struct ContentView: View {
@State var littleValue: Float = 0.5
@State var bigValue: Float = 50
@State var isEditing: Bool = false
var body: some View {
VStack {
Slider(value: $littleValue)
Text("Float: \(littleValue)")
Slider(value: $bigValue, in: 0...100, step: 5) { editing in
isEditing = editing
}
.accentColor(.red)
Text("Int: \(bigValue)")
if isEditing {
Text("Editing!")
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
macOSでSlider
の色を変更する
iOSであればaccentColor
を使うことでスライダーの色を変更できました。
しかし、macOSではNSViewRepresentable
でNSSlider
をSwiftUIで使えるようにする必要があります。
独自のNSSliderCell
を使って色を変更したものを作成します。そのインスタンスをslider.cell
で指定します。
//
// ContentView.swift
//
import SwiftUI
struct ContentView: View {
@State var value: Float = 0.5
var body: some View {
VStack {
VStack {
MYSlider(value: $value)
Text("Float: \(value)")
}.padding()
}
}
}
struct MYSlider: NSViewRepresentable {
@Binding var value: Float
func makeNSView(context: Context) -> NSSlider {
let slider = NSSlider()
slider.cell = MYSliderCell()
slider.sliderType = .linear
slider.isEnabled = true
slider.isContinuous = true
slider.floatValue = value
slider.minValue = 0.0
slider.maxValue = 1.0
slider.target = context.coordinator
slider.action = #selector(context.coordinator.changed(_:))
return slider
}
func updateNSView(_ slider: NSSlider, context: NSViewRepresentableContext<MYSlider>) {
slider.floatValue = value
}
func makeCoordinator() -> Coordinator {
Coordinator(value: $value)
}
final class Coordinator: NSObject {
@Binding var value: Float
init(value: Binding<Float>) {
self._value = value
}
@objc func changed(_ sender: NSSlider) {
self.value = sender.floatValue
}
}
}
class MYSliderCell: NSSliderCell {
override func drawBar(inside rect: NSRect, flipped: Bool) {
var rect = rect
rect.size.height = CGFloat(4)
let value = CGFloat((self.doubleValue - self.minValue) / (self.maxValue - self.minValue))
let leftWidth = CGFloat(value * (self.controlView!.frame.size.width - 8))
var leftRect = rect
leftRect.size.width = leftWidth
let leftPath = NSBezierPath(roundedRect: leftRect, xRadius: CGFloat(2), yRadius: CGFloat(2))
NSColor.purple.setFill()
leftPath.fill()
let backgroundPath = NSBezierPath(roundedRect: rect, xRadius: CGFloat(2), yRadius: CGFloat(2))
NSColor.lightGray.withAlphaComponent(0.3).setFill()
backgroundPath.fill()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}