mirror of
https://github.com/nerdycat/Cupcake.git
synced 2024-08-16 08:20:37 +03:00
compatible with iOS 11
This commit is contained in:
parent
ec5c88e7b3
commit
5db392e14c
1
.swift-version
Normal file
1
.swift-version
Normal file
@ -0,0 +1 @@
|
||||
3.0
|
@ -12,10 +12,14 @@ import UIKit
|
||||
class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
|
||||
var window: UIWindow?
|
||||
|
||||
|
||||
|
||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
|
||||
// Override point for customization after application launch.
|
||||
|
||||
let sel = NSSelectorFromString("setContentInsetAdjustmentBehavior:")
|
||||
if UIScrollView().responds(to: sel) {
|
||||
UIScrollView.appearance().perform(sel, with: 2)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -92,6 +92,7 @@ class AppStoreViewController: UITableViewController {
|
||||
|
||||
self.tableView.estimatedRowHeight = 84
|
||||
self.tableView.register(AppStoreCell.self, forCellReuseIdentifier: "cell")
|
||||
self.tableView.contentInset = UIEdgeInsetsMake(0, 0, 34, 0)
|
||||
|
||||
let path = Bundle.main.path(forResource: "appList", ofType: "plist")
|
||||
appList = NSArray(contentsOfFile: path!) as? Array<Dictionary<String, Any>>
|
||||
|
@ -41,7 +41,7 @@ class SignupViewController: BaseViewController {
|
||||
self.view.bg("#184367")
|
||||
|
||||
let iphone5 = UIScreen.main.bounds.width == 320
|
||||
let card = View.bg("white").radius(4).embedIn(self.view, iphone5 ? 40 : 60, 30)
|
||||
let card = View.bg("white").radius(4).embedIn(self.view, iphone5 ? 40 : "60", 30)
|
||||
|
||||
let inputStyle = Styles.pin(40, .lowHugging).font(14)
|
||||
Styles("separator").bg("#C7C7CD").pin(1)
|
||||
@ -68,7 +68,7 @@ class SignupViewController: BaseViewController {
|
||||
|
||||
|
||||
Button.str("X").font(13).color("#D2E0E8").bg("#EDF2F5").radius(-1).pin(16, 16, .maxX(-10), .y(10)).addTo(card)
|
||||
Button.str("HELP").font(13).padding(10).pin(.centerX(0), .maxY(-5)).addTo(self.view)
|
||||
Button.str("HELP").font(13).padding(10).pin(.centerX(0), .maxY("-5")).addTo(self.view)
|
||||
}
|
||||
|
||||
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
|
||||
|
@ -47,7 +47,7 @@ class StackViewController: BaseViewController {
|
||||
self.stack.axis = self.stack.axis == .vertical ? .horizontal : .vertical
|
||||
})
|
||||
|
||||
HStack("<-->", addView, attachGap, gap, align, axis, "<-->").gap(8).embedIn(self.view, nil, 0, 0, 0)
|
||||
HStack("<-->", addView, attachGap, gap, align, axis, "<-->").gap(8).embedIn(self.view, nil, 0, "0", 0)
|
||||
}
|
||||
|
||||
override func setupUI() {
|
||||
|
@ -1,7 +1,7 @@
|
||||
Pod::Spec.new do |s|
|
||||
|
||||
s.name = "Cupcake"
|
||||
s.version = "1.1.0"
|
||||
s.version = "1.1.1"
|
||||
s.summary = "An easy way to create and layout UI components for iOS."
|
||||
|
||||
s.description = <<-DESC
|
||||
|
@ -90,6 +90,8 @@ public class CPKStackView: UIView {
|
||||
addAndActivateConstraintsForView(at: index)
|
||||
}
|
||||
|
||||
self.disableLayoutMarginsAdjustment(for: view)
|
||||
|
||||
} else if let array = sub as? [Any] {
|
||||
for i in 0..<array.count {
|
||||
insertArrangedSubview(item: array[i], at: min(index + i, self.arrangedSubviews.count))
|
||||
@ -122,6 +124,7 @@ public class CPKStackView: UIView {
|
||||
public override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
self.layoutMargins = UIEdgeInsets.zero
|
||||
self.disableLayoutMarginsAdjustment(for: self)
|
||||
}
|
||||
|
||||
public required init?(coder aDecoder: NSCoder) {
|
||||
@ -640,6 +643,17 @@ public class CPKStackView: UIView {
|
||||
removeAndDeactivateAllConstriants()
|
||||
addAndActivateConstraintsForAll()
|
||||
}
|
||||
|
||||
private func disableLayoutMarginsAdjustment(for view: UIView) {
|
||||
// if #available(iOS 11, *) {
|
||||
// view.insetsLayoutMarginsFromSafeArea = false
|
||||
// }
|
||||
|
||||
let sel = NSSelectorFromString("setInsetsLayoutMarginsFromSafeArea:")
|
||||
if view.responds(to: sel) {
|
||||
view.perform(sel, with: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -55,7 +55,7 @@ public extension UIView {
|
||||
.radius(-1) //passing negative number means using auto rounding
|
||||
*/
|
||||
@discardableResult public func radius(_ cornerRadius: CGFloat) -> Self {
|
||||
if cornerRadius >= 0 {
|
||||
if cornerRadius >= 0.1 && cornerRadius < 9999999 {
|
||||
self.layer.cornerRadius = cornerRadius
|
||||
self.cpkAutoRoundingRadius = false
|
||||
} else {
|
||||
@ -213,7 +213,9 @@ public extension UIView {
|
||||
|
||||
* Usages:
|
||||
.pin(.x(20)) //add left constraint
|
||||
.pin(.x("20")) //add left margin constraint
|
||||
.pin(.y(20)) //add top constraint
|
||||
.pin(.y("20")) //add top margin constraint
|
||||
.pin(.xy(20, 20)) //and left and top constraints
|
||||
|
||||
.pin(.w(100)) //add width constraint
|
||||
@ -223,7 +225,9 @@ public extension UIView {
|
||||
.pin(.xywh(20, 20, 100, 100)) //add left, top, width and height constraints
|
||||
|
||||
.pin(.maxX(-20)) //add right constraint
|
||||
.pin(.maxX(-20)) //add right margin constraint
|
||||
.pin(.maxY(-20)) //add bottom constraint
|
||||
.pin(.maxY(-20)) //add bottom margin constraint
|
||||
.pin(.maxXY(-20, -20)) //add right and bottom constraints
|
||||
|
||||
.pin(.centerX(0)) //add centerX constriant
|
||||
@ -296,6 +300,11 @@ public extension UIView {
|
||||
.embedIn(superview, 10, 20, 30) //top: 10, left: 20, right: 30
|
||||
.embedIn(superview, 10, 20, 30, 40) //top: 10, left: 20, bottom: 30, right: 40
|
||||
.embedIn(superview, 10, 20, nil) //top: 10, left: 20
|
||||
|
||||
* Passing string value instead of CGFloat will constraint to superview's margin.
|
||||
* This is useful when embed in controller's view whose margin may not be 0.
|
||||
* Usages:
|
||||
.embedIn(superview, "10", 20, "30", 40) //topMargin: 10, left: 20, bottomMargin: 30, right: 40
|
||||
*/
|
||||
@discardableResult public func embedIn(_ superview: UIView,
|
||||
_ p1: Any? = "", _ p2: Any? = "",
|
||||
@ -306,16 +315,32 @@ public extension UIView {
|
||||
|
||||
makeCons({
|
||||
if let top = edge.0 {
|
||||
$0.top.offset(top)
|
||||
if let topValue = top as? CGFloat {
|
||||
$0.top.offset(topValue)
|
||||
} else if let topMarginValue = CPKFloatOptional(top) {
|
||||
$0.top.equal(superview).topMargin.offset(topMarginValue)
|
||||
}
|
||||
}
|
||||
if let left = edge.1 {
|
||||
$0.left.offset(left)
|
||||
if let leftValue = left as? CGFloat {
|
||||
$0.left.offset(leftValue)
|
||||
} else if let leftMarginValue = CPKFloatOptional(left) {
|
||||
$0.left.equal(superview).leftMargin.offset(leftMarginValue)
|
||||
}
|
||||
}
|
||||
if let bottom = edge.2 {
|
||||
$0.bottom.offset(-bottom)
|
||||
if let bottomValue = bottom as? CGFloat {
|
||||
$0.bottom.offset(-bottomValue)
|
||||
} else if let bottomMarginValue = CPKFloatOptional(bottom) {
|
||||
$0.bottom.equal(superview).bottomMargin.offset(-bottomMarginValue)
|
||||
}
|
||||
}
|
||||
if let right = edge.3 {
|
||||
$0.right.offset(-right)
|
||||
if let rightValue = right as? CGFloat {
|
||||
$0.right.offset(-rightValue)
|
||||
} else if let rightMarginValue = CPKFloatOptional(right) {
|
||||
$0.right.equal(superview).rightMargin.offset(-rightMarginValue)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@ -325,9 +350,9 @@ public extension UIView {
|
||||
|
||||
|
||||
public enum CPKViewPinOptions {
|
||||
case x(CGFloat) //left constraint
|
||||
case y(CGFloat) //top constraint
|
||||
case xy(CGFloat, CGFloat) //left and top constraints
|
||||
case x(Any) //passing value for left constraint, passing string value for left margin constraint
|
||||
case y(Any) //passing value for top constraint, passing string value for top margin constraint
|
||||
case xy(Any, Any) //x + y
|
||||
|
||||
case w(CGFloat) //width constraint
|
||||
case h(CGFloat) //height constraint
|
||||
@ -336,9 +361,9 @@ public enum CPKViewPinOptions {
|
||||
case xywh(CGFloat, CGFloat, //left, top, width and height constraints
|
||||
CGFloat, CGFloat)
|
||||
|
||||
case maxX(CGFloat) //right constraint
|
||||
case maxY(CGFloat) //bottom constraint
|
||||
case maxXY(CGFloat, CGFloat) //right and bottom constraint
|
||||
case maxX(Any) //passing value for right constraint, passing string value for right margin constraint
|
||||
case maxY(Any) //passing value for bottom constraint, passing string value for bottom margin constraint
|
||||
case maxXY(Any, Any) //maxX + maxY
|
||||
|
||||
case centerX(CGFloat) //centerX constraint
|
||||
case centerY(CGFloat) //centerY constraint
|
||||
|
@ -76,6 +76,15 @@ func CPKFloatOptional(_ any: Any?) -> CGFloat? {
|
||||
}
|
||||
}
|
||||
|
||||
func CPKStringValueOptional(_ any: Any?) -> CGFloat? {
|
||||
if let str = any as? String {
|
||||
let f = Float(str)
|
||||
return f != nil ? CGFloat(f!) : nil
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func cpk_onePointImageWithColor(_ color: UIColor) -> UIImage {
|
||||
let rect = CGRect(x: 0, y: 0, width: 1, height: 1)
|
||||
let hasAlpha = cpk_colorHasAlphaChannel(color)
|
||||
@ -150,46 +159,46 @@ func cpk_edgeInsetsTupleFromParameters(_ p1: Any? = "",
|
||||
_ p3: Any? = "",
|
||||
_ p4: Any? = "")
|
||||
|
||||
-> (CGFloat?, CGFloat?, CGFloat?, CGFloat?) {
|
||||
-> (Any?, Any?, Any?, Any?) {
|
||||
|
||||
var leftOffset: CGFloat?
|
||||
var rightOffset: CGFloat?
|
||||
var topOffset: CGFloat?
|
||||
var bottomOffset: CGFloat?
|
||||
var leftOffset: Any?
|
||||
var rightOffset: Any?
|
||||
var topOffset: Any?
|
||||
var bottomOffset: Any?
|
||||
|
||||
let isValidP1 = !(p1 is String)
|
||||
let isValidP2 = !(p2 is String)
|
||||
let isValidP3 = !(p3 is String)
|
||||
let isValidP4 = !(p4 is String)
|
||||
let isValidP1 = !(p1 is String) || ((p1 as! String) != "")
|
||||
let isValidP2 = !(p2 is String) || ((p2 as! String) != "")
|
||||
let isValidP3 = !(p3 is String) || ((p3 as! String) != "")
|
||||
let isValidP4 = !(p4 is String) || ((p4 as! String) != "")
|
||||
|
||||
if isValidP1 && isValidP2 && isValidP3 && isValidP4 {
|
||||
topOffset = CPKFloatOptional(p1)
|
||||
leftOffset = CPKFloatOptional(p2)
|
||||
bottomOffset = CPKFloatOptional(p3)
|
||||
rightOffset = CPKFloatOptional(p4)
|
||||
topOffset = (p1 is String) ? p1 : CPKFloatOptional(p1)
|
||||
leftOffset = (p2 is String) ? p2 : CPKFloatOptional(p2)
|
||||
bottomOffset = (p3 is String) ? p3 : CPKFloatOptional(p3)
|
||||
rightOffset = (p4 is String) ? p4 : CPKFloatOptional(p4)
|
||||
|
||||
} else if isValidP1 && isValidP2 && isValidP3 {
|
||||
topOffset = CPKFloatOptional(p1)
|
||||
leftOffset = CPKFloatOptional(p2)
|
||||
rightOffset = CPKFloatOptional(p3)
|
||||
topOffset = (p1 is String) ? p1 : CPKFloatOptional(p1)
|
||||
leftOffset = (p2 is String) ? p2 : CPKFloatOptional(p2)
|
||||
rightOffset = (p3 is String) ? p3 : CPKFloatOptional(p3)
|
||||
|
||||
} else if isValidP1 && isValidP2 {
|
||||
topOffset = CPKFloatOptional(p1)
|
||||
leftOffset = CPKFloatOptional(p2)
|
||||
bottomOffset = CPKFloatOptional(p1)
|
||||
rightOffset = CPKFloatOptional(p2)
|
||||
topOffset = (p1 is String) ? p1 : CPKFloatOptional(p1)
|
||||
leftOffset = (p2 is String) ? p2 : CPKFloatOptional(p2)
|
||||
bottomOffset = topOffset
|
||||
rightOffset = leftOffset
|
||||
|
||||
} else if isValidP1 {
|
||||
topOffset = CPKFloatOptional(p1)
|
||||
leftOffset = CPKFloatOptional(p1)
|
||||
bottomOffset = CPKFloatOptional(p1)
|
||||
rightOffset = CPKFloatOptional(p1)
|
||||
topOffset = (p1 is String) ? p1 : CPKFloatOptional(p1)
|
||||
leftOffset = topOffset
|
||||
bottomOffset = topOffset
|
||||
rightOffset = topOffset
|
||||
|
||||
} else {
|
||||
topOffset = 0
|
||||
leftOffset = 0
|
||||
bottomOffset = 0
|
||||
rightOffset = 0
|
||||
topOffset = CGFloat(0)
|
||||
leftOffset = CGFloat(0)
|
||||
bottomOffset = CGFloat(0)
|
||||
rightOffset = CGFloat(0)
|
||||
}
|
||||
|
||||
return (topOffset, leftOffset, bottomOffset, rightOffset)
|
||||
@ -312,30 +321,94 @@ func cpk_updatePadding(_ padding: [CGFloat], forView view: UIView) {
|
||||
func cpk_pinOptions(_ options: [CPKViewPinOptions], forView view: UIView) {
|
||||
view.makeCons({
|
||||
var values = [CGFloat]()
|
||||
let priority: UILayoutPriority = 999
|
||||
|
||||
for option in options {
|
||||
switch option {
|
||||
case let .x(offset): $0.left.equal(offset)
|
||||
case let .y(offset): $0.top.equal(offset)
|
||||
case let .w(value): $0.width.equal(value)
|
||||
case let .h(value): $0.height.equal(value)
|
||||
case let .x(offset):
|
||||
if let value = CPKStringValueOptional(offset) {
|
||||
$0.left.equal("superview").leftMargin.offset(value).priority(priority)
|
||||
} else if let value = CPKFloatOptional(offset) {
|
||||
$0.left.equal(value).priority(priority)
|
||||
}
|
||||
|
||||
case let .xy(v1, v2): $0.left.top.equal(v1, v2); view.frame.origin = CGPoint(x: v1, y: v2)
|
||||
case let .wh(v1, v2): $0.width.height.equal(v1, v2); view.frame.size = CGSize(width: v1, height: v2)
|
||||
case let .xywh(v1, v2, v3, v4): $0.left.top.width.height.equal(v1, v2, v3, v4)
|
||||
case let .y(offset):
|
||||
if let value = CPKStringValueOptional(offset) {
|
||||
$0.top.equal("superview").topMargin.offset(value).priority(priority)
|
||||
} else if let value = CPKFloatOptional(offset) {
|
||||
$0.top.equal(value).priority(priority)
|
||||
}
|
||||
|
||||
case let .maxX(offset): $0.right.equal(offset)
|
||||
case let .maxY(offset): $0.bottom.equal(offset)
|
||||
case let .maxXY(v1, v2): $0.right.bottom.equal(v1, v2)
|
||||
case let .w(value):
|
||||
view.frame.size.width = value
|
||||
$0.width.equal(value).priority(priority)
|
||||
|
||||
case let .centerX(offset): $0.centerX.equal(offset)
|
||||
case let .centerY(offset): $0.centerY.equal(offset)
|
||||
case let .centerXY(v1, v2): $0.center.equal(v1, v2)
|
||||
case let .h(value):
|
||||
view.frame.size.height = value
|
||||
$0.height.equal(value).priority(priority)
|
||||
|
||||
case let .xy(v1, v2):
|
||||
if let value = CPKStringValueOptional(v1) {
|
||||
$0.left.equal("superview").leftMargin.offset(value).priority(priority)
|
||||
} else if let value = CPKFloatOptional(v1) {
|
||||
$0.left.equal(value).priority(priority)
|
||||
}
|
||||
if let value = CPKStringValueOptional(v2) {
|
||||
$0.top.equal("superview").topMargin.offset(value).priority(priority)
|
||||
} else if let value = CPKFloatOptional(v2) {
|
||||
$0.top.equal(value).priority(priority)
|
||||
}
|
||||
|
||||
case let .wh(v1, v2):
|
||||
view.frame.size = CGSize(width: v1, height: v2)
|
||||
$0.width.height.equal(v1, v2).priority(priority)
|
||||
|
||||
case let .xywh(v1, v2, v3, v4):
|
||||
view.frame = CGRect(x: v1, y: v2, width: v3, height: v4)
|
||||
$0.left.top.width.height.equal(v1, v2, v3, v4).priority(priority);
|
||||
|
||||
case let .maxX(offset):
|
||||
if let value = CPKStringValueOptional(offset) {
|
||||
$0.right.equal("superview").rightMargin.offset(value).priority(priority)
|
||||
} else if let value = CPKFloatOptional(offset) {
|
||||
$0.right.equal(value).priority(priority)
|
||||
}
|
||||
|
||||
case let .maxY(offset):
|
||||
if let value = CPKStringValueOptional(offset) {
|
||||
$0.bottom.equal("superview").bottomMargin.offset(value).priority(priority)
|
||||
} else if let value = CPKFloatOptional(offset) {
|
||||
$0.bottom.equal(value).priority(priority)
|
||||
}
|
||||
|
||||
case let .maxXY(v1, v2):
|
||||
if let value = CPKStringValueOptional(v1) {
|
||||
$0.right.equal("superview").rightMargin.offset(value).priority(priority)
|
||||
} else if let value = CPKFloatOptional(v1) {
|
||||
$0.right.equal(value).priority(priority)
|
||||
}
|
||||
if let value = CPKStringValueOptional(v2) {
|
||||
$0.bottom.equal("superview").bottomMargin.offset(value).priority(priority)
|
||||
} else if let value = CPKFloatOptional(v2) {
|
||||
$0.bottom.equal(value).priority(priority)
|
||||
}
|
||||
|
||||
case let .centerX(offset):
|
||||
$0.centerX.equal(offset)
|
||||
|
||||
case let .centerY(offset):
|
||||
$0.centerY.equal(offset)
|
||||
|
||||
case let .centerXY(v1, v2):
|
||||
$0.center.equal(v1, v2)
|
||||
|
||||
case let .whRatio(ratio): $0.width.equal(view).height.multiply(ratio)
|
||||
|
||||
case .center: $0.center.equal(0)
|
||||
case .ratio: $0.width.equal(view).height.multiply(view.frame.width / view.frame.height)
|
||||
case .center:
|
||||
$0.center.equal(0)
|
||||
|
||||
case .ratio:
|
||||
$0.width.equal(view).height.multiply(view.frame.width / view.frame.height)
|
||||
|
||||
case let .hhp(value): view.setContentHuggingPriority(value, for: .horizontal)
|
||||
case let .vhp(value): view.setContentHuggingPriority(value, for: .vertical)
|
||||
@ -350,16 +423,20 @@ func cpk_pinOptions(_ options: [CPKViewPinOptions], forView view: UIView) {
|
||||
view.setContentCompressionResistancePriority(kLowPriority, for: .horizontal)
|
||||
view.setContentCompressionResistancePriority(kLowPriority, for: .vertical)
|
||||
|
||||
case let .___value(value): values.append(value)
|
||||
case let .___value(value):
|
||||
values.append(value)
|
||||
}
|
||||
}
|
||||
|
||||
if values.count == 1 {
|
||||
$0.height.equal(values[0])
|
||||
view.frame.size.height = values[0]
|
||||
$0.height.equal(values[0]).priority(priority)
|
||||
} else if values.count == 2 {
|
||||
$0.size.equal(values[0], values[1])
|
||||
view.frame.size = CGSize(width: values[0], height: values[1])
|
||||
$0.size.equal(values[0], values[1]).priority(priority)
|
||||
} else if values.count == 4 {
|
||||
$0.origin.size.equal(values[0], values[1], values[2], values[3])
|
||||
view.frame = CGRect(x: values[0], y: values[1], width: values[2], height: values[3])
|
||||
$0.origin.size.equal(values[0], values[1], values[2], values[3]).priority(priority)
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -1029,6 +1106,7 @@ public class ConsAtts: NSObject {
|
||||
public class Cons: ConsAtts {
|
||||
private let firstItem: UIView
|
||||
private var secondItem: UIView?
|
||||
private var secondItemReferToSuperview = false
|
||||
|
||||
var relation = NSLayoutRelation.equal
|
||||
|
||||
@ -1050,7 +1128,7 @@ public class Cons: ConsAtts {
|
||||
@discardableResult
|
||||
override func addAttributes(_ attributes: NSLayoutAttribute...) -> Cons {
|
||||
for att in attributes {
|
||||
if secondItem == nil {
|
||||
if secondItem == nil && !secondItemReferToSuperview {
|
||||
firstItemAttributes.append(att)
|
||||
} else {
|
||||
secondItemAttributes.append(att)
|
||||
@ -1066,6 +1144,9 @@ public class Cons: ConsAtts {
|
||||
} else if let item2 = item2OrValues.first as? String {
|
||||
if item2 == "self" {
|
||||
self.secondItem = self.firstItem
|
||||
} else if item2 == "superview" {
|
||||
self.secondItem = nil
|
||||
self.secondItemReferToSuperview = true
|
||||
} else {
|
||||
assert(false, "invalid second item")
|
||||
}
|
||||
@ -1582,6 +1663,8 @@ public class StaticTableView: UITableView, UITableViewDelegate, UITableViewDataS
|
||||
public init(sectionsOrRows: [Any], style: UITableViewStyle) {
|
||||
super.init(frame: CGRect.zero, style: style)
|
||||
self.estimatedRowHeight = 44
|
||||
self.estimatedSectionHeaderHeight = 0
|
||||
self.estimatedSectionFooterHeight = 0
|
||||
self.delegate = self
|
||||
self.dataSource = self
|
||||
updateSections(sectionsOrRows: sectionsOrRows)
|
||||
|
Loading…
Reference in New Issue
Block a user