Skip to content

Commit

Permalink
Add startOffset / endOffset support
Browse files Browse the repository at this point in the history
  • Loading branch information
psharanda committed Jan 11, 2024
1 parent abb837a commit 7441c79
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 19 deletions.
11 changes: 8 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@
- Simple API with 2 functions and 4 specifiers, covering 99% of layout use cases
- Lightweight, implementation is only 300 lines of code
- Compatible with any other Auto Layout code
- Basically generates a bunch of `NSLayoutConstraint` and `UILayoutGuide`
- Basically generates a bunch of activated `NSLayoutConstraint` and `UILayoutGuide`
- Super straightforward mental model
- Typesafe alternative to VFL
- Dynamic Type and Right-To-Left friendly
- Automatically sets `translatesAutoresizingMaskIntoConstraints` to false
- Supports iOS 12.0+ / Mac OS X 10.13+ / tvOS 12.0+

Expand Down Expand Up @@ -92,14 +93,16 @@ That's it! The best part is how easy it is to modify FixFlex layout code, insert

`FixFlex` provides two functions for laying out views horizontally (`hput`) and vertically (`vput`), accessible through the `view.fx.*` namespace.

You can specify `startAnchor`/`endAnchor` to layout items between arbitrary anchors instead of the view's edges.
You can specify `startAnchor`/`endAnchor` to layout items between arbitrary anchors instead of the view's edges. `startOffset`/`endOffset` are used to add spacing or offsets from the `startAnchor` and `endAnchor` respectively.

By default, `hput` works in natural positioning mode and operates using `leadingAnchor`/`trailingAnchor`. This setup ensures that the layout is mirrored for Right-to-Left (RTL) languages. However, this behavior can be overridden by enabling the `useAbsolutePositioning` flag. When this flag is set to true, `hput` shifts to using `leftAnchor`/`rightAnchor` for layout positioning.
By default, `hput` works in natural positioning mode and operates using `leadingAnchor`/`trailingAnchor`. This setup ensures that the layout is mirrored for Right-to-Left languages. However, this behavior can be overridden by enabling the `useAbsolutePositioning` flag. When this flag is set to true, `hput` shifts to using `leftAnchor`/`rightAnchor` for layout positioning.

```swift
func hput(
startAnchor: NSLayoutXAxisAnchor? = nil, // if nil, we use leadingAnchor or leftAnchor
startOffset: CGFloat = 0,
endAnchor: NSLayoutXAxisAnchor? = nil, // if nil, we use trailingAnchor or rightAnchor
endOffset: CGFloat = 0,
useAbsolutePositioning: Bool = false, // if true, we use leftAnchor/rightAnchor based positioning (force Left-To-Right)
_ intents: PutIntent...
) -> PutResult
Expand All @@ -108,7 +111,9 @@ func hput(
```swift
func vput(
startAnchor: NSLayoutYAxisAnchor? = nil, // if nil, we use topAnchor
startOffset: CGFloat = 0,
endAnchor: NSLayoutYAxisAnchor? = nil, // if nil, we use bottomAnchor
endOffset: CGFloat = 0,
_ intents: PutIntent...
) -> PutResult
```
Expand Down
11 changes: 8 additions & 3 deletions Readme/src/templates/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@
- Simple API with 2 functions and 4 specifiers, covering 99% of layout use cases
- Lightweight, implementation is only 300 lines of code
- Compatible with any other Auto Layout code
- Basically generates a bunch of `NSLayoutConstraint` and `UILayoutGuide`
- Basically generates a bunch of activated `NSLayoutConstraint` and `UILayoutGuide`
- Super straightforward mental model
- Typesafe alternative to VFL
- Dynamic Type and Right-To-Left friendly
- Automatically sets `translatesAutoresizingMaskIntoConstraints` to false
- Supports iOS 12.0+ / Mac OS X 10.13+ / tvOS 12.0+

Expand Down Expand Up @@ -92,14 +93,16 @@ That's it! The best part is how easy it is to modify FixFlex layout code, insert

`FixFlex` provides two functions for laying out views horizontally (`hput`) and vertically (`vput`), accessible through the `view.fx.*` namespace.

You can specify `startAnchor`/`endAnchor` to layout items between arbitrary anchors instead of the view's edges.
You can specify `startAnchor`/`endAnchor` to layout items between arbitrary anchors instead of the view's edges. `startOffset`/`endOffset` are used to add spacing or offsets from the `startAnchor` and `endAnchor` respectively.

By default, `hput` works in natural positioning mode and operates using `leadingAnchor`/`trailingAnchor`. This setup ensures that the layout is mirrored for Right-to-Left (RTL) languages. However, this behavior can be overridden by enabling the `useAbsolutePositioning` flag. When this flag is set to true, `hput` shifts to using `leftAnchor`/`rightAnchor` for layout positioning.
By default, `hput` works in natural positioning mode and operates using `leadingAnchor`/`trailingAnchor`. This setup ensures that the layout is mirrored for Right-to-Left languages. However, this behavior can be overridden by enabling the `useAbsolutePositioning` flag. When this flag is set to true, `hput` shifts to using `leftAnchor`/`rightAnchor` for layout positioning.

```swift
func hput(
startAnchor: NSLayoutXAxisAnchor? = nil, // if nil, we use leadingAnchor or leftAnchor
startOffset: CGFloat = 0,
endAnchor: NSLayoutXAxisAnchor? = nil, // if nil, we use trailingAnchor or rightAnchor
endOffset: CGFloat = 0,
useAbsolutePositioning: Bool = false, // if true, we use leftAnchor/rightAnchor based positioning (force Left-To-Right)
_ intents: PutIntent...
) -> PutResult
Expand All @@ -108,7 +111,9 @@ func hput(
```swift
func vput(
startAnchor: NSLayoutYAxisAnchor? = nil, // if nil, we use topAnchor
startOffset: CGFloat = 0,
endAnchor: NSLayoutYAxisAnchor? = nil, // if nil, we use bottomAnchor
endOffset: CGFloat = 0,
_ intents: PutIntent...
) -> PutResult
```
Expand Down
50 changes: 37 additions & 13 deletions Sources/FixFlex.swift
Original file line number Diff line number Diff line change
Expand Up @@ -176,10 +176,12 @@ public struct PutResult {

public extension FixFlexing {
private func _put<AnchorType: AnyObject, AxisAnchorsBuilderType: AxisAnchorsBuilder>(
_ intents: [PutIntent],
builder: AxisAnchorsBuilderType,
startAnchor: NSLayoutAnchor<AnchorType>,
endAnchor: NSLayoutAnchor<AnchorType>
startOffset: CGFloat,
endAnchor: NSLayoutAnchor<AnchorType>,
endOffset: CGFloat,
builder: AxisAnchorsBuilderType,
intents: [PutIntent]
) -> PutResult where AxisAnchorsBuilderType.AnchorType == AnchorType {
var lastAnchors = [startAnchor]
var weightsInfo: (dimensionAnchor: NSLayoutDimension, weight: CGFloat)?
Expand All @@ -206,7 +208,8 @@ public extension FixFlexing {

for aa in aas {
for lastAnchor in lastAnchors {
constraints.append(aa.startAnchor.constraint(equalTo: lastAnchor))
constraints.append(aa.startAnchor.constraint(equalTo: lastAnchor,
constant: lastAnchor === startAnchor ? startOffset : 0))
}

func handleSizingConstraint(_ constraint: NSLayoutConstraint) {
Expand Down Expand Up @@ -252,7 +255,7 @@ public extension FixFlexing {
}

lastAnchors.forEach {
constraints.append($0.constraint(equalTo: endAnchor))
constraints.append($0.constraint(equalTo: endAnchor, constant: endOffset))
}

NSLayoutConstraint.activate(constraints)
Expand All @@ -263,44 +266,65 @@ public extension FixFlexing {
@discardableResult
func hput(
startAnchor: NSLayoutXAxisAnchor? = nil,
startOffset: CGFloat = 0,
endAnchor: NSLayoutXAxisAnchor? = nil,
endOffset: CGFloat = 0,
useAbsolutePositioning: Bool = false,
_ intents: [PutIntent]
) -> PutResult {
return _put(intents,
return _put(startAnchor: startAnchor ?? (useAbsolutePositioning ? base.leftAnchor : base.leadingAnchor),
startOffset: startOffset,
endAnchor: endAnchor ?? (useAbsolutePositioning ? base.rightAnchor : base.trailingAnchor),
endOffset: endOffset,
builder: XAxisAnchorsBuilder(useAbsolutePositioning: useAbsolutePositioning),
startAnchor: startAnchor ?? (useAbsolutePositioning ? base.leftAnchor : base.leadingAnchor),
endAnchor: endAnchor ?? (useAbsolutePositioning ? base.rightAnchor : base.trailingAnchor))
intents: intents)
}

@discardableResult
func hput(
startAnchor: NSLayoutXAxisAnchor? = nil,
startOffset: CGFloat = 0,
endAnchor: NSLayoutXAxisAnchor? = nil,
endOffset: CGFloat = 0,
useAbsolutePositioning: Bool = false,
_ intents: PutIntent...
) -> PutResult {
return hput(startAnchor: startAnchor, endAnchor: endAnchor, useAbsolutePositioning: useAbsolutePositioning, intents)
return hput(startAnchor: startAnchor,
startOffset: startOffset,
endAnchor: endAnchor,
endOffset: endOffset,
useAbsolutePositioning: useAbsolutePositioning,
intents)
}

@discardableResult
func vput(
startAnchor: NSLayoutYAxisAnchor? = nil,
startOffset: CGFloat = 0,
endAnchor: NSLayoutYAxisAnchor? = nil,
endOffset: CGFloat = 0,
_ intents: [PutIntent]
) -> PutResult {
return _put(intents,
return _put(startAnchor: startAnchor ?? base.topAnchor,
startOffset: startOffset,
endAnchor: endAnchor ?? base.bottomAnchor,
endOffset: endOffset,
builder: YAxisAnchorsBuilder(),
startAnchor: startAnchor ?? base.topAnchor,
endAnchor: endAnchor ?? base.bottomAnchor)
intents: intents)
}

@discardableResult
func vput(
startAnchor: NSLayoutYAxisAnchor? = nil,
startOffset: CGFloat = 0,
endAnchor: NSLayoutYAxisAnchor? = nil,
endOffset: CGFloat = 0,
_ intents: PutIntent...
) -> PutResult {
return vput(startAnchor: startAnchor, endAnchor: endAnchor, intents)
return vput(startAnchor: startAnchor,
startOffset: startOffset,
endAnchor: endAnchor,
endOffset: endOffset,
intents)
}
}

0 comments on commit 7441c79

Please sign in to comment.