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()
    }
}
sliderの基本的な使い方

macOSでSliderの色を変更する

iOSであればaccentColorを使うことでスライダーの色を変更できました。
しかし、macOSではNSViewRepresentableNSSliderを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()
    }
}
SwiftUIでmacOSのSliderの色を変更する方法

参考

cocoa - Change NSSlider bar color - Stack Overflow


    アプリをリリースしました!

    ToDoアプリ

    iCloudを利用したデバイス間データ共有、ダークモードに対応しています。

    リリースしたToDoアプリのスクリーンショット

    IPアドレス履歴保存アプリ

    取得したIPアドレスを確認、位置情報とともに保存できます。

    リリースしたIPアドレス保存アプリのスクリーンショット