一般的にcompact/regularで判断付けていた気がするけれど。
前提
widthをw、heightをhと表す。
compactをC、regularをRと表す。
compact/regularのまとめ
iPhoneが縦向きの場合、全てwChRである。
iPhoneの横向きの場合、全てhCである。
iPadはフルスクリーン時において、縦向き、横向き、全てwRhRである。
iPadが縦向きでsplit viewを使う場合、全てwChRである。
iPadは2/3 split viewの場合、横向きは全てwRhRである。
それ以外のsplit viewは全てwChRである。
したがって、iPadの場合「縦か横か」を判定するためにSizeClassが使えない(レイアウトの振り分けには使えるけれど)
Notificationを使う
単純な縦横を知りたいだけならば次のモディファイアを足す。
.onReceive(NotificationCenter.default.publisher(for: UIDevice.orientationDidChangeNotification)) { output in
guard let device = output.object as? UIDevice else { return }
// device.orientation.isPortrait のtrue / falseで判断つく
}
検証用ソース
struct ContentView: View {
var iPhoneLandscape : some View {
Text("iPhone Landscape")
}
var iPhonePortrait : some View {
Text("iPhone Portrait")
}
var iPadLandscape : some View {
Text("iPad Landscape")
}
var iPadPortrait : some View {
Text("iPad Portrait")
}
var main: some View {
VStack {
switch deviceSize {
case .wChR:
Text("wChR")
case .wRhR:
Text("wRhR")
case .wChC:
Text("wChC")
case .wRhC:
Text("wRhC")
}
switch device {
case .pad:
if isPortrait {
iPadPortrait
} else {
iPadLandscape
}
case .phone:
if isPortrait {
iPhonePortrait
} else {
iPhoneLandscape
}
// 他の端末は何もしない
case .unspecified, .tv, .carPlay, .mac:
EmptyView()
@unknown default:
EmptyView()
}
}
}
enum DeviceSize {
case wRhR
case wRhC
case wChR
case wChC
}
// iPadかiPhoneか
let device = UIDevice.current.userInterfaceIdiom
// 横向きか縦向きか
@State private var isPortrait: Bool = UIDevice.current.orientation.isPortrait
// compact/regular
@Environment(\.horizontalSizeClass) private var horizontalSizeClass
@Environment(\.verticalSizeClass) private var verticalSizeClass
var deviceSize: DeviceSize {
guard let horizontalSizeClass , let verticalSizeClass else {
return .wRhR
}
switch (horizontalSizeClass, verticalSizeClass) {
case (.regular, .regular):
return .wRhR
case (.regular, .compact):
return .wRhC
case (.compact, .regular):
return .wChR
case (.compact, .compact):
return .wChC
default:
return .wRhR
}
}
var body: some View {
main
.onReceive(NotificationCenter.default.publisher(for: UIDevice.orientationDidChangeNotification)) { output in
guard let device = output.object as? UIDevice else { return }
self.isPortrait = device.orientation.isPortrait
}
}
}