条件によってコントロールの色を変更する

コントロールの色を条件分けして色を変更したい場合は、ContentView の中で if 文で場合分けしてやればいいと考えがちですが、それをすると Type '()' cannot conform to 'View' といういつものコンパイルエラーが発生します。

なので、コントロールのモディファイア内で if 文で場合分けしてやります。

本記事では Text のモディファイア内で、条件を評価して背景色と前景色(文字色)を動的に変更するサンプルを示します。

実行例でボタンを押すと、上部に配置されている Text は、青→緑→青→緑、でループします。下に配置されている Text は、シアン→マゼンタ→イエロ→シアン→マゼンタ→イエロ、でループします。

25行目が、if の三項演算子を用いて、偶奇を判断して色を動的に決定しているところです。分岐条件が偶奇の2個だからこそ使える記法です。

33、34行目は、関数をつかって3個の条件分岐に対応しています。条件が2個までならば三項演算子で対応できますが、条件が3個では foregroundColor や background モディファイア内で一行で書くことができませんので動的に色を戻す関数を定義して対応しています。

import SwiftUI

struct ContentView: View {

    @State var GlobalCounter: Int  = 0

    let FONT_SIZE = 32.0
    let TXT_PADDING = 20.0

    let BTN_PADDING = 10.0
    let BTN_CORNER_R = 10.0
    let BTN_LINE_WIDTH = 1.0

    var body: some View {

        VStack {

            Spacer()

           // カウンタの値を表示しつつ、色を偶数と奇数で変更する.
            Text( String( format: "GlobalCounter is %d", GlobalCounter ) )
                .font( .system( size: FONT_SIZE ))
                .padding( TXT_PADDING )
                .foregroundColor( .white )
                .background( GlobalCounter % 2 == 0 ? Color.blue : Color.green )

            Spacer()

           // カウンタの値を表示しつつ、色を 0, 1, 2 でループして変更する.
            Text( String( format: "GlobalCounter is %d", GlobalCounter ) )
                .font( .system( size: FONT_SIZE ))
                .padding( TXT_PADDING )
                .foregroundColor( GetColorFg( GlobalCounter ) )
                .background( GetColorBg( GlobalCounter ) )

            Spacer()

            // カウンタをひとつインクリメントするボタン.
            Button( action: {
                GlobalCounter += 1
            }){
                Text( String( format: "Increment", GlobalCounter ) )
            }
            .padding( BTN_PADDING )
            .overlay(
                RoundedRectangle( cornerRadius: BTN_CORNER_R )
                    .stroke( Color.blue, lineWidth: BTN_LINE_WIDTH )
            )

            Spacer()

        }

    }

    private func GetColorBg( _ counter: Int ) -> Color {

        let tmp = counter % 3

        if ( tmp == 0 ){
            // Cyan.
            return Color( red: 0.0, green: 1.0, blue: 1.0, opacity: 1.0 )
        }
        else if ( tmp == 1 ){
            // Magenta.
            return Color( red: 1.0, green: 0.0, blue: 1.0, opacity: 1.0 )
        }
        else {
            // Yellow.
            return Color( red: 1.0, green: 1.0, blue: 0.0, opacity: 1.0 )
        }

    }

    private func GetColorFg( _ counter: Int ) -> Color {

        let tmp = counter % 3

        if ( tmp == 0 ){
            return Color( red: 0.0, green: 0.0, blue: 0.0, opacity: 1.0 )
        }
        else if ( tmp == 1 ){
            return Color( red: 1.0, green: 1.0, blue: 1.0, opacity: 1.0 )
        }
        else {
            return Color( red: 0.0, green: 0.0, blue: 0.0, opacity: 1.0 )
        }

    }

}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}