Put This View Over There
usage:
override func viewDidLoad() {
super.viewDidLoad()
let middleView = UIView(width: 100, height: 100)
middleView.backgroundColor = UIColor.blueColor()
view.put(middleView,
inside: view,
onThe: .BottomLeft,
withPadding: 10)
let someOtherView = UIView(width: 50, height: 50)
someOtherView.backgroundColor = UIColor.greenColor()
view.put(someOtherView,
atThe: .TopRight,
of: middleView,
withSpacing: 20)
}
result:
implementation:
import UIKit
let screenWidth = UIScreen.mainScreen().bounds.width
let screenHeight = UIScreen.mainScreen().bounds.height
let statusBarHeight = UIApplication.sharedApplication().statusBarFrame.size.height
extension UIViewController {
func addChildVC(vc: UIViewController) {
addChildViewController(vc)
view.addSubview(vc.view)
vc.didMoveToParentViewController(vc)
}
func name() -> String {
return NSStringFromClass(self.dynamicType).componentsSeparatedByString(".").last!
}
func navigationBarHeight() -> CGFloat {
if let navController = navigationController {
return navController.navigationBar.height
} else {
return 0
}
}
func put(aSubview:UIView, inside thisView:UIView, onThe position:Position, withPadding padding:CGFloat) {
view.put(aSubview, inside: thisView, onThe: position, withPadding: padding)
}
func put(aView:UIView, atThe position:Position, of relativeView:UIView, withSpacing spacing:CGFloat) {
view.put(aView, atThe: position, of: relativeView, withSpacing: spacing)
}
}
enum Position {
case Left
case Right
case Top
case Bottom
case TopLeft
case TopRight
case BottomLeft
case BottomRight
}
protocol PutAware {
func wasPut()
}
extension UIView { //put
convenience init(width theWidth:CGFloat, height theHeight: CGFloat) {
self.init()
self.frame = CGRectMake(0, 0, theWidth, theHeight)
}
func put(aSubview:UIView, inside thisView:UIView, onThe position:Position, withPadding padding:CGFloat) {
assert(aSubview.width <= thisView.width &&
aSubview.height <= thisView.height,
"The subview is too large to fit inside this view!")
if position == .Left || position == .Right {
assert(aSubview.width + 2 * padding < thisView.width,
"The padding is too wide!")
}
if position == .Top || position == .Bottom {
assert(aSubview.height + 2 * padding < thisView.height,
"The padding is too high!")
}
if let aLabel = aSubview as? UILabel { aLabel.sizeToFit() }
var subRect: CGRect = CGRectZero
switch position {
case .Left:
subRect = CGRectMake(
padding,
thisView.midHeight - aSubview.midHeight,
aSubview.width,
aSubview.height)
case .Right:
subRect = CGRectMake(
thisView.width - padding - aSubview.width,
thisView.midHeight - aSubview.midHeight,
aSubview.width,
aSubview.height)
case .Top:
subRect = CGRectMake(
thisView.midWidth - aSubview.midWidth,
padding,
aSubview.width,
aSubview.height)
case .Bottom:
subRect = CGRectMake(
thisView.midWidth - aSubview.midWidth,
thisView.height - padding - aSubview.height,
aSubview.width,
aSubview.height)
case .TopLeft:
subRect = CGRectMake(
padding,
padding,
aSubview.width,
aSubview.height)
case .TopRight:
subRect = CGRectMake(
thisView.width - padding - aSubview.width,
padding,
aSubview.width,
aSubview.height)
case .BottomLeft:
subRect = CGRectMake(
padding,
thisView.height - padding - aSubview.height,
aSubview.width,
aSubview.height)
case .BottomRight:
subRect = CGRectMake(
thisView.width - padding - aSubview.width,
thisView.height - padding - aSubview.height,
aSubview.width,
aSubview.height)
}
aSubview.frame = subRect
if aSubview.superview != thisView{
thisView.addSubview(aSubview)
}
(aSubview as? PutAware)?.wasPut()
}
func put(aView:UIView, atThe position:Position, of relativeView:UIView, withSpacing spacing:CGFloat) {
let diagonalSpacing:CGFloat = spacing / sqrt(2.0)
switch position {
case .Left:
aView.center = CGPointMake(
relativeView.minX - aView.width/2 - spacing,
relativeView.midY)
case .Right:
aView.center = CGPointMake(
relativeView.maxX + aView.width/2 + spacing,
relativeView.midY)
case .Top:
aView.center = CGPointMake(
relativeView.midX,
relativeView.minY - aView.height/2 - spacing)
case .Bottom:
aView.center = CGPointMake(
relativeView.midX,
relativeView.maxY + aView.height/2 + spacing)
case .TopLeft:
aView.center = CGPointMake(
relativeView.minX - aView.width/2 - diagonalSpacing,
relativeView.minY - aView.height/2 - diagonalSpacing)
case .TopRight:
aView.center = CGPointMake(
relativeView.maxX + aView.width/2 + diagonalSpacing,
relativeView.minY - aView.height/2 - diagonalSpacing)
case .BottomLeft:
aView.center = CGPointMake(
relativeView.minX - aView.width/2 - diagonalSpacing,
relativeView.maxY + aView.height/2 + diagonalSpacing)
case .BottomRight:
aView.center = CGPointMake(
relativeView.maxX + aView.width/2 + diagonalSpacing,
relativeView.maxY + aView.height/2 + diagonalSpacing)
}
if let relativeSuperview = relativeView.superview {
relativeSuperview.addSubview(aView)
}
(aView as? PutAware)?.wasPut()
}
func resize(toWidth width:CGFloat, toHeight height:CGFloat) {
frame = CGRectMake(minX, minY, width, height)
(self as? PutAware)?.wasPut()
}
func reposition(toX newX:CGFloat, toY newY:CGFloat) {
frame = CGRectMake(newX, newY, width, height)
(self as? PutAware)?.wasPut()
}
func shift(toRight deltaX:CGFloat, toBottom deltaY:CGFloat) {
frame = CGRectMake(minX + deltaX, minY + deltaY, width, height)
(self as? PutAware)?.wasPut()
}
var width: CGFloat { return CGRectGetWidth(frame) }
var height: CGFloat { return CGRectGetHeight(frame) }
var minX: CGFloat { return CGRectGetMinX(frame) }
var minY: CGFloat { return CGRectGetMinY(frame) }
var midX: CGFloat { return CGRectGetMidX(frame) }
var midY: CGFloat { return CGRectGetMidY(frame) }
var midWidth: CGFloat { return CGRectGetWidth(frame)/2 }
var midHeight: CGFloat { return CGRectGetHeight(frame)/2 }
var maxX: CGFloat { return CGRectGetMaxX(frame) }
var maxY: CGFloat { return CGRectGetMaxY(frame) }
}