Skip to content

Instantly share code, notes, and snippets.

@brianpattison
Last active October 13, 2015 00:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save brianpattison/4113832 to your computer and use it in GitHub Desktop.
Save brianpattison/4113832 to your computer and use it in GitHub Desktop.
Rubymotion Layout Wrapper

Rubymotion Layout Wrapper

There's a lot of wrappers for Rubymotion already. I've been collecting my personal wrappers in the Loco namespace. I'm really starting to like this layout wrapper, so I thought I'd share it.

Usage

Include the loco.rb file in your Rubymotion project and include the Loco::UIView module in any of your custom UIViews.

class SampleView < UIView
  include Loco::UIView
end

When you initialize your view, just pass it a combination of parameters for the position and size.

  • bottom
  • height
  • left
  • right
  • top
  • width

Examples

# This view will be 300 x 200 and centered 
# horizontally and vertically in its superview.
@centeredView = SampleView.alloc.initWithFrame({
  height: 300,
  width: 200
})
@centeredView.backgroundColor = UIColor.greenColor

# This view will have the height of 100, left margin of 20, 
# right margin of 30, a flexible width, and will be 
# centered vertically in its superview.
@fixedMarginsView = SampleView.alloc.initWithFrame({
  height: 100,
  left: 20,
  right: 30
})
@fixedMarginsView.backgroundColor = UIColor.yellowColor
@centeredView.addSubview(@fixedMarginsView)

view.addSubview(@centeredView)

Screenshot

Missing Parameters

The console will yell at you if you don't include enough parameters to determine how to size and position the view. Example:

{height: 100, left: 20, top: 20} - The width can't be determined.

The console will also yell at you if you include parameters that may conflict with each other. Example:

{left: 20, right: 20, width: 200} - The width may conflict with the margins depending on the size of the superview.

Enjoy

I hope you can use it or at least learn something from it!

@brianpattison

module Loco
module UIView
# The position of the bottom edge,
# relative to the superview's bottom edge.
# @return [Integer]
attr_accessor :bottom
def bottom=(bottom)
@bottom = bottom
refresh_layout
end
# The height of the view.
# @return [Integer]
attr_accessor :height
def height=(height)
@height = height
refresh_layout
end
# The position of the left edge,
# relative to the superview's left edge.
# @return [Integer]
attr_accessor :left
def left=(left)
@left = left
refresh_layout
end
# The position of the right edge,
# relative to the superview's right edge.
# @return [Integer]
attr_accessor :right
def right=(right)
@right = right
refresh_layout
end
# The position of the top edge,
# relative to the superview's top edge.
# @return [Integer]
attr_accessor :top
def top=(top)
@top = top
refresh_layout
end
# The width of the view.
# @return [Integer]
attr_accessor :width
def width=(width)
@width = width
refresh_layout
end
# Create new instance from a hash of properties with values.
# @param [Object] frame The CGRect or a Hash of properties for layout.
def initWithFrame(frame)
if frame.is_a? Hash
# Set the initial property values from the given hash
super(CGRect.new)
frame.each do |key, value|
self.send("#{key}=", value) if %w(bottom height left right top width).include?(key.to_s)
end
else
super(frame)
end
self
end
# Refresh the layout based on bottom, left, right, top, and superview.
# @param [UIView] superview
def refresh_layout(superview=nil)
# The view can't be positioned without being added to the superview first.
superview ||= self.superview
return if superview.nil?
# Determine the original size, position, and autoresizing mask that should be used.
if self.top && self.bottom
if self.left && self.right
# FW, FH
@origin_x = self.left
@origin_y = self.top
@size_height = superview.bounds.size.height - self.top - self.bottom
@size_width = superview.bounds.size.width - self.left - self.right
@autoresizing = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight
elsif self.left && self.width
# FH, FRM
@origin_x = self.left
@origin_y = self.top
@size_height = superview.bounds.size.height - self.top - self.bottom
@size_width = self.width
@autoresizing = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleRightMargin
elsif self.right && self.width
# FH, FLM
@origin_x = superview.bounds.size.width - self.width - self.right
@origin_y = self.top
@size_height = superview.bounds.size.height - self.top - self.bottom
@size_width = self.width
@autoresizing = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleLeftMargin
elsif self.width
# FH, FLM, FRM
@origin_x = (superview.bounds.size.width - self.width) / 2
@origin_y = self.top
@size_height = superview.bounds.size.height - self.top - self.bottom
@size_width = self.width
@autoresizing = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin
else
# Needs More Params
NSLog('%@<Loco::UIView> Not enough params to position and size the view.', self.class)
end
elsif self.top
if self.left && self.right && self.height
# FW, FBM
@origin_x = self.left
@origin_y = self.top
@size_height = self.height
@size_width = superview.bounds.size.width - self.left - self.right
@autoresizing = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleBottomMargin
elsif self.left && self.height && self.width
# FBM, FRM
@origin_x = self.left
@origin_y = self.top
@size_height = self.height
@size_width = self.width
@autoresizing = UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleRightMargin
elsif self.right && self.height && self.width
# FBM, FLM
@origin_x = superview.bounds.size.width - self.width - self.right
@origin_y = self.top
@size_height = self.height
@size_width = self.width
@autoresizing = UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleLeftMargin
elsif self.height && self.width
# FLM, FRM, FBM
@origin_x = (superview.bounds.size.width - self.width) / 2
@origin_y = self.top
@size_height = self.height
@size_width = self.width
@autoresizing = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin |UIViewAutoresizingFlexibleBottomMargin
else
# Needs More Params
NSLog('%@<Loco::UIView> Not enough params to position and size the view.', self.class)
end
elsif self.bottom
if self.left && self.right && self.height
# FW, FTM
@origin_x = self.left
@origin_y = superview.bounds.size.height - self.height - self.bottom
@size_height = self.height
@size_width = superview.bounds.size.width - self.left - self.right
@autoresizing = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin
elsif self.left && self.height && self.width
# FTM, FRM
@origin_x = self.left
@origin_y = superview.bounds.size.height - self.height - self.bottom
@size_height = self.height
@size_width = self.width
@autoresizing = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleRightMargin
elsif self.right && self.height && self.width
# FTM, FLM
@origin_x = superview.bounds.size.width - self.width - self.right
@origin_y = superview.bounds.size.height - self.height - self.bottom
@size_height = self.height
@size_width = self.width
@autoresizing = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin
elsif self.height && self.width
# FLM, FRM, FTM
@origin_x = (superview.bounds.size.width - self.width) / 2
@origin_y = superview.bounds.size.height - self.height - self.bottom
@size_height = self.height
@size_width = self.width
@autoresizing = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin |UIViewAutoresizingFlexibleTopMargin
else
# Needs More Params
NSLog('%@<Loco::UIView> Not enough params to position and size the view.', self.class)
end
elsif self.left && self.right && self.height
# FW, FTM, FBM
@origin_x = self.left
@origin_y = (superview.bounds.size.height - self.height) / 2
@size_height = self.height
@size_width = superview.bounds.size.width - self.left - self.right
@autoresizing = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin
elsif self.width && self.height
if self.left
# FTM, FBM, FRM
@origin_x = self.left
@origin_y = (superview.bounds.size.height - self.height) / 2
@size_height = self.height
@size_width = self.width
@autoresizing = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleRightMargin
elsif self.right
# FTM, FBM, FLM
@origin_x = superview.bounds.size.width - self.width - self.right
@origin_y = (superview.bounds.size.height - self.height) / 2
@size_height = self.height
@size_width = self.width
@autoresizing = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleLeftMargin
else
# FTM, FBM, FLM, FRM
@origin_x = (superview.bounds.size.width - self.width) / 2
@origin_y = (superview.bounds.size.height - self.height) / 2
@size_height = self.height
@size_width = self.width
@autoresizing = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin
end
else
# Needs More Params
NSLog('%@<Loco::UIView> Not enough params to position and size the view.', self.class)
end
# Warn of any possible conflicts
if self.top && self.bottom && self.height
NSLog('%@<Loco::UIView> `top`, `bottom`, and `height` may conflict with each other. Only two of the three should be set.', self.class)
NSLog('%@<Loco::UIView> top: %@, bottom: %@, height: %@', self.class, self.top, self.bottom, self.height)
end
if self.left && self.right && self.width
NSLog('%@<Loco::UIView> `left`, `right`, and `width` may conflict with each other. Only two of the three should be set.', self.class)
NSLog('%@<Loco::UIView> left: %@, right: %@, width: %@', self.class, self.left, self.right, self.width)
end
if @origin_x && @origin_y && @size_width && @size_height && @autoresizing
self.frame = [[@origin_x, @origin_y], [@size_width, @size_height]]
self.autoresizingMask = @autoresizing
end
# Update the subviews
self.subviews.each do |view|
view.refresh_layout(self) if view.is_a? Loco::UIView
end
end
# Fires when the superview changes.
def willMoveToSuperview(superview)
refresh_layout(superview)
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment