View ja - Tai-Kimura/SwiftJsonUI GitHub Wiki
View
class: SJUIView inherits: UIView child classes: [GradientView](/Tai-Kimura/SwiftJsonUI/wiki/GradientView), [SJUISelectBox](/Tai-Kimura/SwiftJsonUI/wiki/SelectBox)
View の属性
| 属性名 | UIKit | SwiftUI | Compose | XML | jsonでの型 | 詳細 | 備考 |
|---|---|---|---|---|---|---|---|
| orientation | ✅ | ✅ | ✅ | ✅ | string | ビューの向き。この属性には「vertical」と「horizontal」の2つのタイプがあります。この属性が定義されると、Androidの「Linear Layout」のように動作します。 | XML: android:orientation |
| direction | ✅ | ✅ | ✅ | ❌ | string | ビューのレイアウト方向。この属性は「orientation」が定義されている場合にのみ有効です。この属性には5つのタイプがあります:vertical用 - 「topToBottom」、「bottomToTop」;horizontal用 - 「leftToRight」、「rightToLeft」;「none」はデフォルトで、方向なしを意味します。orientationが「vertical」の場合は「topToBottom」が、「horizontal」の場合は「leftToRight」がデフォルトに設定されます。 | |
| gravity | ✅ | ✅ | ✅ | ✅ | string | ビューの重力。この属性には6つのタイプがあります:vertical用 - 「top」、「bottom」、「centerVertical」;horizontal用 - 「left」、「right」、「centerHorizontal」。縦方向の重力はビューのorientationがhorizontalの場合にのみ機能し、横方向の重力はビューのorientationがverticalの場合に機能します。子要素の属性(alignTop、alignBottom、alignLeft、alignRight、centerVertical、centerHorizontal)で、このビューの子要素の重力をオーバーライドできます。 | XML: android:gravity |
| highlightBackground | ✅ | ✅ | ❌ | ❌ | string | ビューがハイライトされたときにbackgroundColorがこの色に変更されます。 | Dynamic mode only |
| highlighted | ✅ | ✅ | ❌ | ❌ | boolean | view.highlighted。 | Dynamic mode only |
| canTap | ✅ | ✅ | ✅ | ✅ | boolean | view.canTap。「onclick」属性が定義されている場合、ビューがタップされるとビューの背景色がtapBackground色に変更されます。この属性を「false」に設定して、ビューの背景色変更を防ぐことができます。 | XML: android:clickable |
| onclick | ✅ | ✅ | ✅ | ✅ | string | この属性でonclickイベントを定義できます。この属性で作成されたセレクターがUITapGestureRecognizerに設定され、UITapGestureRecognizerがビューに追加されます。 | XML: android:onClick |
| events | ✅ | ✅ | ❌ | ❌ | dictionary | この属性でイベントを定義できます。この属性で作成されたセレクターが各イベントのUIGestureRecognizerに設定され、UIGestureRecognizerがビューに追加されます。イベントのタイプには「eventType」キーを、Selectorには「selector」キーを使用します。eventTypeがswipeの場合、「directions」キーで方向を定義する必要があります。directionsキーには文字列の配列を提供します。利用可能な文字列:「up」、「down」、「left」、「right」eventTypeリスト:onclick: UITapGestureRecognizeronlongtap: UILongPressGestureRecognizerpan: UIPanGestureRecognizerswipe: UISwipeGestureRecognizerrotation: UIRotationGestureRecognizer | Dynamic mode only |
| touchDisabledState | ✅ | ✅ | ❌ | ❌ | string | このビューとその子ビューのタッチ処理動作を制御します。"none" (デフォルト): 通常のタッチ処理"onlyMe": このビューのみタッチを無効化、子ビューはタッチ可能のまま"viewsWithoutTouchEnabled": userInteractionEnabled=trueの子ビューのみタッチイベントを受信"viewsWithoutInList": touchEnabledViewIdsで指定された子ビューのみタッチイベントを受信 |
Dynamic mode only |
| touchEnabledViewIds | ✅ | ✅ | ❌ | ❌ | string array | touchDisabledStateが「viewsWithoutInList」の場合にタッチが有効のままにするビューIDのリスト。touchDisabledStateが「viewsWithoutInList」の場合のみ適用されます | Dynamic mode only |
| safeAreaInsetPositions | ✅ | ✅ | ✅ | ✅ | string array | SafeAreaViewタイプ専用。どの辺にセーフエリアインセットを適用するかを制御します。デフォルトは[「all」]です。 | SafeAreaView only; XML: KjuiSafeAreaView |
View のプロパティ
open class var viewClass: SJUIView.Type
このプロパティは、createFromJSONメソッドでどのクラスをインフレートするかを決定するために使用されます。 SJUIViewを継承するクラスを作成する際は、このプロパティでビューのクラスを定義する必要があります。
open class var canTap: Bool
説明は属性テーブルをご覧ください。
open class var highlighted: Bool
説明は属性テーブルをご覧ください。
open class var orientation: SJUIView.Orientation
説明は属性テーブルをご覧ください。 このプロパティを変更した後は、ビューの制約を適用するためにresetConstraintInfoメソッドを呼び出す必要があります。
open class var direction: SJUIView.Direction
説明は属性テーブルをご覧ください。 このプロパティを変更した後は、ビューの制約を適用するためにresetConstraintInfoメソッドを呼び出す必要があります。
open class var gravity: SJUIView.Gravity
説明は属性テーブルをご覧ください。 このプロパティを変更した後は、ビューの制約を適用するためにresetConstraintInfoメソッドを呼び出す必要があります。
View の関数
open override func didAddSubview(_ subview: UIView)
UIViewから継承。 このメソッドはサブビューが追加されたときに呼び出されます。 このメソッドが呼び出されると、resetConstraintInfoが呼び出されます。
public func addSubViewWith(json: JSON, target: Any, withCreatorClass creator: SJUIViewCreator.Type = SJUIViewCreator.self)
コードからJSONファイルで作成されたサブビューを追加したい場合は、このメソッドを使用します。
public class func createFromJSON(attr: JSON, target: Any, views: inout [String: UIView]) -> SJUIView
このメソッドは、JSONファイルから作成される際に呼び出されます。 SJUIViewクラスを継承するクラスを作成する際は、このメソッドをオーバーライドしてください。
TouchDisabledState 実装例
例1: 基本的なtouchDisabledStateの使用
{
"type": "View",
"id": "container",
"width": "matchParent",
"height": "matchParent",
"touchDisabledState": "onlyMe",
"background": "#CCCCCC",
"child": [
{
"type": "Button",
"id": "button1",
"width": 100,
"height": 50,
"text": "クリック可能",
"onclick": "buttonTapped"
}
]
}
この例では、コンテナビューはタップできませんが、内部のボタンはクリック可能のままです。
例2: touchEnabledViewIdsの使用
{
"type": "View",
"id": "parentView",
"width": "matchParent",
"height": "matchParent",
"touchDisabledState": "viewsWithoutInList",
"touchEnabledViewIds": ["allowedButton", "allowedLabel"],
"background": "#EEEEEE",
"child": [
{
"type": "Button",
"id": "allowedButton",
"width": 120,
"height": 50,
"text": "許可",
"onclick": "allowedButtonTapped"
},
{
"type": "Button",
"id": "blockedButton",
"width": 120,
"height": 50,
"text": "ブロック",
"onclick": "blockedButtonTapped"
},
{
"type": "Label",
"id": "allowedLabel",
"width": "wrapContent",
"height": "wrapContent",
"text": "クリック可能ラベル",
"onclick": "labelTapped"
}
]
}
「allowedButton」と「allowedLabel」のみがタッチイベントを受信します。「blockedButton」はタッチに反応しません。
例3: データバインディングでの条件付きタッチ有効化
{
"type": "View",
"id": "conditionalView",
"width": "matchParent",
"height": 200,
"data": [
{
"name": "isInteractionEnabled",
"class": "Bool",
"defaultValue": true
},
{
"name": "enabledViewIds",
"class": "[String]",
"defaultValue": []
}
],
"touchDisabledState": "@{isInteractionEnabled ? 'none' : 'viewsWithoutInList'}",
"touchEnabledViewIds": "@{enabledViewIds}",
"background": "#F0F0F0",
"child": [
{
"type": "Button",
"id": "controlButton",
"width": 150,
"height": 50,
"text": "インタラクション切替",
"onclick": "toggleInteraction"
},
{
"type": "Button",
"id": "actionButton",
"width": 120,
"height": 50,
"text": "アクション",
"onclick": "performAction"
}
]
}
この例では、データバインディングを使用してタッチ動作を動的に制御する方法を示しています。
Swift実装例
class ViewController: UIViewController {
@IBOutlet weak var containerView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
setupTouchControlledView()
}
func setupTouchControlledView() {
let jsonString = """
{
"type": "View",
"id": "touchControlledContainer",
"width": "matchParent",
"height": 300,
"touchDisabledState": "viewsWithoutInList",
"touchEnabledViewIds": ["enabledButton"],
"background": "#E8E8E8",
"child": [
{
"type": "Button",
"id": "enabledButton",
"width": 140,
"height": 50,
"text": "有効",
"onclick": "enabledButtonTapped"
},
{
"type": "Button",
"id": "disabledButton",
"width": 140,
"height": 50,
"text": "無効",
"onclick": "disabledButtonTapped"
}
]
}
"""
if let jsonData = jsonString.data(using: .utf8),
let json = try? JSON(data: jsonData) {
let createdView = SJUIViewCreator.viewFromJSON(json, target: self)
containerView.addSubview(createdView)
createdView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
createdView.topAnchor.constraint(equalTo: containerView.topAnchor),
createdView.leadingAnchor.constraint(equalTo: containerView.leadingAnchor),
createdView.trailingAnchor.constraint(equalTo: containerView.trailingAnchor),
createdView.heightAnchor.constraint(equalToConstant: 300)
])
}
}
@objc func enabledButtonTapped() {
print("有効ボタンがタップされました")
}
@objc func disabledButtonTapped() {
print("touchDisabledStateにより、これは呼び出されません")
}
}
動的なtouchDisabledState制御
現在、touchDisabledStateはデータバインディング構文@{}を使って動的に制御できますが、binding_builderにはこの属性に対する専用のハンドラー実装はありません。SwiftコードからtouchDisabledStateを動的に変更する必要がある場合は、以下の方法があります:
- ビューに直接アクセスしてプロパティを変更:
if let containerView = view.findViewWithId("container") as? SJUIView {
containerView.touchDisabledState = .viewsWithoutInList
containerView.touchEnabledViewIds = ["newAllowedButton"]
}
- 変更後にinvalidateメソッドを使ってレイアウトを更新:
// touchDisabledStateやtouchEnabledViewIdsを変更した後
containerView.setNeedsLayout()
containerView.layoutIfNeeded()
- カスタムハンドラーサポートの追加を検討:
# これは将来view_binding_handler.rbに追加できるかもしれません:
when "touchDisabledState"
@binding_content << " #{view_name}?.touchDisabledState = TouchDisabledState(rawValue: #{value}) ?? .none\n"
true
when "touchEnabledViewIds"
@binding_content << " #{view_name}?.touchEnabledViewIds = #{value}\n"
true
注意: binding_builderを通じた完全な動的制御には、view_binding_handler.rbファイルでのカスタムハンドラー実装が必要です。