View ja - Tai-Kimura/SwiftJsonUI GitHub Wiki

🇺🇸 English | 🇯🇵 日本語

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を動的に変更する必要がある場合は、以下の方法があります:

  1. ビューに直接アクセスしてプロパティを変更:
if let containerView = view.findViewWithId("container") as? SJUIView {
    containerView.touchDisabledState = .viewsWithoutInList
    containerView.touchEnabledViewIds = ["newAllowedButton"]
}
  1. 変更後にinvalidateメソッドを使ってレイアウトを更新:
// touchDisabledStateやtouchEnabledViewIdsを変更した後
containerView.setNeedsLayout()
containerView.layoutIfNeeded()
  1. カスタムハンドラーサポートの追加を検討:
# これは将来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ファイルでのカスタムハンドラー実装が必要です。