LoginSignup
12

More than 1 year has passed since last update.

posted at

updated at

SwiftUIでListの上にButtonを置く場合List自体にイベントを奪われないようにする

SwiftUIでListの上にButtonを置くと、タップイベントがListのほうで実行されてしまう。そのため、ButtonのスタイルをBorderlessButtonStylePlainButtonStyleにする必要がある。

(この記事はXcode 12.4でのSwiftUIでの話です)

本題

解決方法

ButtonにBorderlessButtonStylePlainButtonStyleのスタイルを設定する

//: A UIKit based Playground for presenting user interface

import UIKit
import SwiftUI
import PlaygroundSupport

struct ContentView: View {
    var body: some View {
        List {
            HStack {
                Text("Cell 1")

                Spacer()

                Button(action: {
                    print("B_1押したね")
                }, label: {
                    Text("Border")
                })
                .buttonStyle(BorderlessButtonStyle())

                Button(action: {
                    print("P_1押したね")
                }, label: {
                    Text("Plain")
                })
                .buttonStyle(PlainButtonStyle())
            }
        }
    }
}

PlaygroundPage.current.liveView = UIHostingController(rootView: ContentView())

これで解決。タップイベントはListではなくボタンで反応するようになった。

デザイン的なものはButtonでなく内部のTextに適用していけばいい。

蛇足: なぜButtonのスタイルで判断するのかを考える

全てのスタイルを適用してみる

他にもDefaultButtonStyleというのがあるのでそれも適用してみる。結果はListがタップできるようになってしまう。つまりこれがデフォルトか。

//: A UIKit based Playground for presenting user interface

import UIKit
import SwiftUI
import PlaygroundSupport

struct ContentView: View {
    var body: some View {
        List {
            HStack {
                Text("Cell 1")

                Spacer()

                Button(action: {
                    print("B_1押したね")
                }, label: {
                    Text("Border")
                })
                .buttonStyle(BorderlessButtonStyle())

                Button(action: {
                    print("P_1押したね")
                }, label: {
                    Text("Plain")
                })
                .buttonStyle(PlainButtonStyle())

                Button(action: {
                    print("D_1押したね")
                }, label: {
                    Text("Default")
                })
                .buttonStyle(DefaultButtonStyle())
            }
        }
    }
}

PlaygroundPage.current.liveView = UIHostingController(rootView: ContentView())

なぜButtonのスタイルで判断するのか

  • Listには複数のSectionやView(Cell/Item)が必要なためListのスタイルで統一的に指定しづらい
    • 1行目とか指定する形にしてしまえばできるとは思うがそれも複雑でどうかと思う
      • 内部のViewの状態で判断しようとしている

具体的にはListが2行になっている場合、1行目はCellにはタップできないが、2行目はCellにもタップできる。

//: A UIKit based Playground for presenting user interface

import UIKit
import SwiftUI
import PlaygroundSupport

struct ContentView: View {
    var body: some View {
        List {
            HStack {
                Text("Cell 1")

                Spacer()

                Button(action: {
                    print("B_1押したね")
                }, label: {
                    Text("Border")
                })
                .buttonStyle(BorderlessButtonStyle())

                Button(action: {
                    print("P_1押したね")
                }, label: {
                    Text("Plain")
                })
                .buttonStyle(PlainButtonStyle())
            }

            HStack {
                Text("Cell 2")

                Spacer()

                Button(action: {
                    print("D_2押したね")
                }, label: {
                    Text("Default")
                })
                .buttonStyle(DefaultButtonStyle())
            }
        }
    }
}

PlaygroundPage.current.liveView = UIHostingController(rootView: ContentView())

スクリーンショット 2021-04-10 16.16.30.png

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
12