easy-button 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +54 -0
- data/easy-button.gemspec +12 -0
- data/lib/easy-button.rb +9 -0
- data/lib/easy-button/easy-button.rb +205 -0
- data/spec/easy_button_spec.rb +47 -0
- metadata +50 -0
data/README.md
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
# Easy Button for RubyMotion
|
2
|
+
|
3
|
+
A nice looking button in RubyMotion that extends the UIButton class and adds a couple properties for easy styling.
|
4
|
+
|
5
|
+
Just pass a single hex value to `backgroundColor` and get a nice gradient button with a shadow.
|
6
|
+
|
7
|
+
You can also more easily set the `borderRadius`, `font`, `textColor`, and `title` for the button's label. Everything else works just like a UIButton!
|
8
|
+
|
9
|
+
# Install
|
10
|
+
|
11
|
+
I find it very easy to use Bundler to manage gems in RubyMotion.
|
12
|
+
|
13
|
+
Rakefile
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
$:.unshift("/Library/RubyMotion/lib")
|
17
|
+
require 'motion/project'
|
18
|
+
require 'bundler'
|
19
|
+
Bundler.require
|
20
|
+
|
21
|
+
Motion::Project::App.setup do |app|
|
22
|
+
# Use `rake config' to see complete project settings.
|
23
|
+
app.name = 'Testing'
|
24
|
+
end
|
25
|
+
```
|
26
|
+
|
27
|
+
Gemfile
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
source :rubygems
|
31
|
+
|
32
|
+
gem 'easy-button', :git => 'git://github.com/brianpattison/easy-button.git'
|
33
|
+
```
|
34
|
+
|
35
|
+
Run `bundle install`.
|
36
|
+
|
37
|
+
# Usage
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
@button = EasyButton.alloc.initWithFrame([[10, 160], [300, 80]])
|
41
|
+
@button.backgroundColor = '#ff0000'
|
42
|
+
@button.borderRadius = 14
|
43
|
+
@button.font = UIFont.boldSystemFontOfSize(26)
|
44
|
+
@button.textColor = '#fff'
|
45
|
+
@button.title = "That Was Easy!"
|
46
|
+
```
|
47
|
+
|
48
|
+
# Screenshot
|
49
|
+
|
50
|
+

|
51
|
+
|
52
|
+
# Thanks
|
53
|
+
|
54
|
+
Thanks to [@seanlilmateus](https://github.com/seanlilmateus) for the inspiration and a bunch of code from [CoolButton](https://github.com/seanlilmateus/CoolButton)!
|
data/easy-button.gemspec
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
Gem::Specification.new do |gem|
|
2
|
+
gem.authors = ["Brian Pattison"]
|
3
|
+
gem.email = ["brian@brianpattison.com"]
|
4
|
+
gem.description = "A nice looking button in RubyMotion"
|
5
|
+
gem.summary = "Extends to UIButton class and adds properties for easy styling."
|
6
|
+
gem.homepage = "https://github.com/brianpattison/easy-button"
|
7
|
+
|
8
|
+
gem.files = `git ls-files`.split($\)
|
9
|
+
gem.name = "easy-button"
|
10
|
+
gem.require_paths = ["lib"]
|
11
|
+
gem.version = '0.0.4'
|
12
|
+
end
|
data/lib/easy-button.rb
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
unless defined?(Motion::Project::Config)
|
2
|
+
raise "This file must be required within a RubyMotion project Rakefile."
|
3
|
+
end
|
4
|
+
|
5
|
+
Motion::Project::App.setup do |app|
|
6
|
+
Dir.glob(File.join(File.dirname(__FILE__), 'easy-button/*.rb')).each do |file|
|
7
|
+
app.files.unshift(file)
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,205 @@
|
|
1
|
+
class EasyButton < UIButton
|
2
|
+
attr_accessor :borderRadius, :font, :textColor, :title
|
3
|
+
|
4
|
+
def initWithFrame(frame)
|
5
|
+
if super
|
6
|
+
buttonSetup
|
7
|
+
end
|
8
|
+
self
|
9
|
+
end
|
10
|
+
|
11
|
+
def initWithCoder(a_decoder)
|
12
|
+
if super
|
13
|
+
buttonSetup
|
14
|
+
end
|
15
|
+
self
|
16
|
+
end
|
17
|
+
|
18
|
+
def buttonSetup
|
19
|
+
self.opaque = false
|
20
|
+
self.backgroundColor = UIColor.clearColor
|
21
|
+
self.backgroundColor = "#ff0000"
|
22
|
+
self.borderRadius = 10
|
23
|
+
self.font = UIFont.boldSystemFontOfSize(18)
|
24
|
+
self.textColor = '#fff'
|
25
|
+
titleLabel.shadowColor = UIColor.colorWithWhite(0, alpha:0.5);
|
26
|
+
titleLabel.shadowOffset = [0, -1]
|
27
|
+
end
|
28
|
+
|
29
|
+
def backgroundColor=(value)
|
30
|
+
if value.is_a? String
|
31
|
+
rgb = rgbFromHex(value)
|
32
|
+
@backGroundColorRed = rgb[0]
|
33
|
+
@backGroundColorGreen = rgb[1]
|
34
|
+
@backGroundColorBlue = rgb[2]
|
35
|
+
@backgroundColorTop = UIColor.colorWithRed(@backGroundColorRed * 1.2, green:@backGroundColorGreen * 1.2, blue:@backGroundColorBlue * 1.2, alpha:1)
|
36
|
+
@backgroundColorBottom = UIColor.colorWithRed(@backGroundColorRed * 0.7, green:@backGroundColorGreen * 0.7, blue:@backGroundColorBlue * 0.7, alpha:1)
|
37
|
+
elsif value = UIColor.clearColor
|
38
|
+
super
|
39
|
+
else
|
40
|
+
@backgroundColorStart = value
|
41
|
+
@backgroundColorBottom = value
|
42
|
+
end
|
43
|
+
self.setNeedsDisplay
|
44
|
+
end
|
45
|
+
|
46
|
+
def borderRadius=(value)
|
47
|
+
@borderRadius = value
|
48
|
+
self.setNeedsDisplay
|
49
|
+
end
|
50
|
+
|
51
|
+
def textColor=(value)
|
52
|
+
@textColor = value
|
53
|
+
if value.is_a? String
|
54
|
+
red, green, blue = rgbFromHex(value)
|
55
|
+
titleLabel.textColor = UIColor.colorWithRed(red, green:green, blue:blue, alpha:1)
|
56
|
+
else
|
57
|
+
titleLabel.textColor = value
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def font=(value)
|
62
|
+
@font = value
|
63
|
+
titleLabel.setFont(@font)
|
64
|
+
end
|
65
|
+
|
66
|
+
def title=(value)
|
67
|
+
@title = value
|
68
|
+
self.setTitle(@title, forState:UIControlStateNormal)
|
69
|
+
end
|
70
|
+
|
71
|
+
def drawRect(rect)
|
72
|
+
super
|
73
|
+
context = UIGraphicsGetCurrentContext()
|
74
|
+
|
75
|
+
if self.state == UIControlStateHighlighted && @backGroundColorRed && @backGroundColorGreen && @backGroundColorBlue
|
76
|
+
backgroundColorTop = UIColor.colorWithRed(@backGroundColorRed * 0.8, green:@backGroundColorGreen * 0.8, blue:@backGroundColorBlue * 0.8, alpha:1).CGColor
|
77
|
+
else
|
78
|
+
backgroundColorTop = @backgroundColorTop.CGColor
|
79
|
+
end
|
80
|
+
backgroundColorBottom = @backgroundColorBottom.CGColor
|
81
|
+
|
82
|
+
outerMargin = 5
|
83
|
+
outerRect = CGRectInset(self.bounds, outerMargin, outerMargin)
|
84
|
+
outerPath = createRoundedRectForRect(outerRect, @borderRadius)
|
85
|
+
|
86
|
+
highlightRect = CGRectInset(outerRect, 2, 3)
|
87
|
+
highlightPath = createRoundedRectForRect(highlightRect, @borderRadius - 1)
|
88
|
+
|
89
|
+
# Draw Shadow When Not Pressed
|
90
|
+
unless self.state == UIControlStateHighlighted
|
91
|
+
CGContextSaveGState(context)
|
92
|
+
CGContextSetFillColorWithColor(context, backgroundColorTop)
|
93
|
+
CGContextSetShadowWithColor(context, CGSizeMake(0, 2), 3, UIColor.colorWithWhite(0, alpha:0.5).CGColor)
|
94
|
+
CGContextAddPath(context, outerPath)
|
95
|
+
CGContextFillPath(context)
|
96
|
+
CGContextRestoreGState(context)
|
97
|
+
end
|
98
|
+
|
99
|
+
# Draw Button Gradient
|
100
|
+
CGContextSaveGState(context)
|
101
|
+
CGContextAddPath(context, outerPath)
|
102
|
+
CGContextClip(context)
|
103
|
+
drawLinearGradient(context, outerRect, backgroundColorTop, backgroundColorBottom)
|
104
|
+
CGContextRestoreGState(context)
|
105
|
+
|
106
|
+
# Draw Highlight or Inner Shadow
|
107
|
+
CGContextSaveGState(context)
|
108
|
+
if self.state == UIControlStateHighlighted
|
109
|
+
CGContextSetLineWidth(context, 4)
|
110
|
+
CGContextAddPath(context, outerPath)
|
111
|
+
CGContextAddPath(context, highlightPath)
|
112
|
+
CGContextEOClip(context)
|
113
|
+
drawLinearGradient(context, outerRect, UIColor.colorWithWhite(0, alpha:0.12).CGColor, UIColor.colorWithWhite(0, alpha:0.03).CGColor)
|
114
|
+
else
|
115
|
+
CGContextSetLineWidth(context, 4)
|
116
|
+
CGContextAddPath(context, outerPath)
|
117
|
+
CGContextAddPath(context, highlightPath)
|
118
|
+
CGContextEOClip(context)
|
119
|
+
drawLinearGradient(context, outerRect, UIColor.colorWithWhite(1, alpha:0.2).CGColor, UIColor.colorWithWhite(1, alpha:0.02).CGColor)
|
120
|
+
end
|
121
|
+
CGContextRestoreGState(context)
|
122
|
+
|
123
|
+
# Draw Button Border
|
124
|
+
CGContextSaveGState(context)
|
125
|
+
CGContextSetLineWidth(context, 1)
|
126
|
+
CGContextSetStrokeColorWithColor(context, UIColor.colorWithWhite(0, alpha:0.3).CGColor)
|
127
|
+
CGContextAddPath(context, outerPath)
|
128
|
+
CGContextStrokePath(context)
|
129
|
+
CGContextRestoreGState(context)
|
130
|
+
|
131
|
+
# Move Title Label Down When Pressed
|
132
|
+
if self.state == UIControlStateHighlighted
|
133
|
+
titleLabel.transform = CGAffineTransformIdentity
|
134
|
+
titleLabel.transform = CGAffineTransformMakeTranslation(0, 1)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def drawLinearGradient(context, rect, start_color, end_color)
|
139
|
+
color_space = CGColorSpaceCreateDeviceRGB()
|
140
|
+
locations = Pointer.new(:float, 2)
|
141
|
+
locations[1] = 1.0
|
142
|
+
|
143
|
+
colors = [start_color, end_color]
|
144
|
+
|
145
|
+
gradient = CGGradientCreateWithColors(color_space, colors, locations)
|
146
|
+
|
147
|
+
start_point = CGPointMake(CGRectGetMidX(rect), CGRectGetMinY(rect))
|
148
|
+
end_point = CGPointMake(CGRectGetMidX(rect), CGRectGetMaxY(rect))
|
149
|
+
|
150
|
+
CGContextSaveGState(context)
|
151
|
+
CGContextAddRect(context, rect)
|
152
|
+
CGContextClip(context)
|
153
|
+
CGContextDrawLinearGradient(context, gradient, start_point, end_point, 0)
|
154
|
+
CGContextRestoreGState(context)
|
155
|
+
end
|
156
|
+
|
157
|
+
def createRoundedRectForRect(rect, radius)
|
158
|
+
path = CGPathCreateMutable()
|
159
|
+
CGPathMoveToPoint(path, nil, CGRectGetMidX(rect), CGRectGetMinY(rect))
|
160
|
+
CGPathAddArcToPoint(path, nil, CGRectGetMaxX(rect), CGRectGetMinY(rect), CGRectGetMaxX(rect), CGRectGetMaxY(rect), radius)
|
161
|
+
CGPathAddArcToPoint(path, nil, CGRectGetMaxX(rect), CGRectGetMaxY(rect), CGRectGetMinX(rect), CGRectGetMaxY(rect), radius)
|
162
|
+
CGPathAddArcToPoint(path, nil, CGRectGetMinX(rect), CGRectGetMaxY(rect), CGRectGetMinX(rect), CGRectGetMinY(rect), radius)
|
163
|
+
CGPathAddArcToPoint(path, nil, CGRectGetMinX(rect), CGRectGetMinY(rect), CGRectGetMaxX(rect), CGRectGetMinY(rect), radius)
|
164
|
+
CGPathCloseSubpath(path)
|
165
|
+
path
|
166
|
+
end
|
167
|
+
|
168
|
+
def rgbFromHex(hex)
|
169
|
+
hex = hex.gsub(%r{[#;]}, '')
|
170
|
+
case hex.size
|
171
|
+
when 3
|
172
|
+
hex.scan(%r{[0-9A-Fa-f]}).map { |el| (1.0 * (el * 2).to_i(16)) / 255 }
|
173
|
+
when 6
|
174
|
+
hex.scan(%r<[0-9A-Fa-f]{2}>).map { |el| (1.0 * el.to_i(16)) / 255 }
|
175
|
+
else
|
176
|
+
raise ArgumentError, 'Argument is not a valid hex code.'
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
def hesitateUpdate
|
181
|
+
self.setNeedsDisplay
|
182
|
+
end
|
183
|
+
|
184
|
+
def touchesBegan(touches, withEvent:the_event)
|
185
|
+
super
|
186
|
+
self.setNeedsDisplay
|
187
|
+
end
|
188
|
+
|
189
|
+
def touchesMoved(touches, withEvent:the_event)
|
190
|
+
super
|
191
|
+
self.setNeedsDisplay
|
192
|
+
end
|
193
|
+
|
194
|
+
def touchesCancelled(touches, withEvent:the_event)
|
195
|
+
super
|
196
|
+
self.setNeedsDisplay
|
197
|
+
self.performSelector(:hesitateUpdate, withObject:nil, afterDelay:0.1)
|
198
|
+
end
|
199
|
+
|
200
|
+
def touchesEnded(touches, withEvent:the_event)
|
201
|
+
super
|
202
|
+
self.setNeedsDisplay
|
203
|
+
self.performSelector(:hesitateUpdate, withObject:nil, afterDelay:0.1)
|
204
|
+
end
|
205
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
describe EasyButton do
|
2
|
+
before do
|
3
|
+
@easyButton = EasyButton.alloc.initWithFrame([[0.0, 0.0], [10.0, 50.0]])
|
4
|
+
end
|
5
|
+
|
6
|
+
it "backgroundColor should be transparent" do
|
7
|
+
@easyButton.backgroundColor.should.equal UIColor.clearColor
|
8
|
+
end
|
9
|
+
|
10
|
+
it "borderRadius should have a default value" do
|
11
|
+
@easyButton.borderRadius.should.equal 10
|
12
|
+
end
|
13
|
+
|
14
|
+
it "font should have a default value" do
|
15
|
+
@easyButton.font.should.equal UIFont.boldSystemFontOfSize(18)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "titleLabel should have a default shadowColor" do
|
19
|
+
@easyButton.titleLabel.shadowColor.should.equal UIColor.colorWithWhite(0, alpha:0.5);
|
20
|
+
end
|
21
|
+
|
22
|
+
it "titleLabel should have a default shadowOffset" do
|
23
|
+
@easyButton.titleLabel.shadowOffset.should.equal CGSizeMake(0, -1)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "titleLabel should have a default textColor" do
|
27
|
+
@easyButton.titleLabel.textColor.should.equal UIColor.colorWithRed(1, green:1, blue:1, alpha:1)
|
28
|
+
end
|
29
|
+
|
30
|
+
it "titleLabel text should change with title" do
|
31
|
+
title = 'That Was Easy!'
|
32
|
+
@easyButton.title = title
|
33
|
+
@easyButton.titleLabel.text.should.equal title
|
34
|
+
end
|
35
|
+
|
36
|
+
it "titleLabel font should change with font" do
|
37
|
+
font = UIFont.boldSystemFontOfSize(10)
|
38
|
+
@easyButton.font = font
|
39
|
+
@easyButton.titleLabel.font.should.equal font
|
40
|
+
end
|
41
|
+
|
42
|
+
it "titleLabel textColor should change with textColor" do
|
43
|
+
textColor = '#000'
|
44
|
+
@easyButton.textColor = textColor
|
45
|
+
@easyButton.titleLabel.textColor.should.equal UIColor.colorWithRed(0, green:0, blue:0, alpha:1)
|
46
|
+
end
|
47
|
+
end
|
metadata
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: easy-button
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.4
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Brian Pattison
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-06-07 00:00:00.000000000Z
|
13
|
+
dependencies: []
|
14
|
+
description: A nice looking button in RubyMotion
|
15
|
+
email:
|
16
|
+
- brian@brianpattison.com
|
17
|
+
executables: []
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- README.md
|
22
|
+
- easy-button.gemspec
|
23
|
+
- lib/easy-button.rb
|
24
|
+
- lib/easy-button/easy-button.rb
|
25
|
+
- spec/easy_button_spec.rb
|
26
|
+
homepage: https://github.com/brianpattison/easy-button
|
27
|
+
licenses: []
|
28
|
+
post_install_message:
|
29
|
+
rdoc_options: []
|
30
|
+
require_paths:
|
31
|
+
- lib
|
32
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
requirements: []
|
45
|
+
rubyforge_project:
|
46
|
+
rubygems_version: 1.8.6
|
47
|
+
signing_key:
|
48
|
+
specification_version: 3
|
49
|
+
summary: Extends to UIButton class and adds properties for easy styling.
|
50
|
+
test_files: []
|