LoginSignup
2
2

More than 5 years have passed since last update.

RubyMotion でグラデーション

Posted at

RubyMotion で CGGradient を使ってグラデーションを作る際に 2 点ほどポイントがありそうです。

1. Pointer クラスを使用する

CGGradient オブジェクトを作成する際に使用する関数 CGGradientCreateWithColorComponentsCGFloat 型の配列を受け取ります(変数 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 では kCGGradientDrawsBeforeStartLocationkCGGradientDrawsAfterEndLocation という定数が用意されています。どちらも小文字から始まる定数です。

RubyMotion では英小文字から始まる定数は、一文字目を大文字に書き換えて利用してあげる必要があります。

kCGGradientDrawsAfterEndLocationKCGGradientDrawsAfterEndLocation になります。

いざ動かしてみる

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
2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2