RubyMotion で CGGradient を使ってグラデーションを作る際に 2 点ほどポイントがありそうです。
1. Pointer クラスを使用する
CGGradient オブジェクトを作成する際に使用する関数 CGGradientCreateWithColorComponents
は CGFloat
型の配列を受け取ります(変数 components
, locations
に注目してください)。
CGGradientRef CGGradientCreateWithColorComponents(
CGColorSpaceRef space,
const CGFloat components[],
const CGFloat locations[],
size_t count
);
Ruby の Array クラスを使った配列は簡単に用意できますが、ここでは CGFloat
型の配列なので、RubyMotion で用意されている Pointer クラスを使い CGFloat
型の配列と同等のものを作ります。以下のようなコードになります。
float_array = Pointer.new(:float, size)
2. kCGGradientDrawsXXXX 定数
CGGradient では kCGGradientDrawsBeforeStartLocation
と kCGGradientDrawsAfterEndLocation
という定数が用意されています。どちらも小文字から始まる定数です。
RubyMotion では英小文字から始まる定数は、一文字目を大文字に書き換えて利用してあげる必要があります。
kCGGradientDrawsAfterEndLocation
は KCGGradientDrawsAfterEndLocation
になります。
いざ動かしてみる
app_delegate.rb
class Array
def to_pointer(type)
# Ruby の Array オブジェクトを Pointer クラスを使ったものに変換
pointer = Pointer.new(type, self.size)
self.each_with_index do |v, i|
pointer[i] = v
end
pointer
end
end
class GradientView < UIView
def drawRect(rect)
super
context = UIGraphicsGetCurrentContext()
CGContextSaveGState(context)
CGContextAddRect(context, self.frame)
space = CGColorSpaceCreateDeviceRGB()
comp = [
0.0, 0.0, 1.0, 1.0, # Blue
1.0, 0.0, 0.0, 1.0, # Red
0.0, 1.0, 0.0, 1.0 # Green
]
components = comp.to_pointer(:float)
loc = [0.0, 0.5, 1.0]
locations = loc.to_pointer(:float)
count = loc.size
frame = self.bounds
start_point = frame.origin
end_point = CGPointMake(frame.origin.x + frame.size.width, frame.origin.y)
gradient = CGGradientCreateWithColorComponents(space, components, locations, count)
CGContextDrawLinearGradient(context,
gradient,
start_point,
end_point,
KCGGradientDrawsAfterEndLocation) # 定数を英大文字で始める
CGContextRestoreGState(context)
end
end
class AppDelegate
def application(application, didFinishLaunchingWithOptions:launchOptions)
@window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds)
@window.rootViewController = UIViewController.alloc.initWithNibName(nil, bundle: nil)
@view = GradientView.alloc.initWithFrame(CGRectMake(10, 10, 100, 100))
@window.rootViewController.view.addSubview(@view)
@window.makeKeyAndVisible
true
end
end