Viewにグラデーションレイヤを適用する

androidではGUI部品に対して色のグラデーションを描画する場合、XMLでDrawableのインスタンスを記述するか、コードにより直接GradientDrawableクラスのインスタンスを生成するコードを書き、対象のViewに適用することで可能だった。

androidによるグラデーションの描画
  • XMLによるグラデーションシェイプ記述
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
  <gradient
      android:startColor="#ffff0000"
      android:endColor="#ff0000ff"
      android:angle="270" />
</shape>
  • コードによるGradientDrawableクラスの生成
GradientDrawable gradient = new GradientDrawable(Orientation.BOTTOM_TOP, new int[]{0xffff0000, 0x0000ff});
view.setBackgroundDrawable(gradient);
  • 表示結果

iOSによるグラデーションの描画(UIViewController)

一方iOSだがandroidのようにXMLで記述することはできないので、もっぱらコードで記述することになる。
iOSはViewにレイヤを追加することができるのだが、グラデーションのためにCAGradientLayerというクラスがQuartzCoreに用意されているので、これを使う。

  • UIViewController.viewDidLoad
#import <QuartzCore/QuartzCore.h>
- (void)viewDidLoad
{
    [super viewDidLoad];
    〜
    CAGradientLayer* gradient = [CAGradientLayer layer];
    gradient.frame = self.view.bounds;
    gradient.colors = [NSArray arrayWithObjects:
                       (id)[[UIColor redColor] CGColor], //開始色
                       (id)[[UIColor blueColor] CGColor], //終了色
                       nil];
    [gradient setStartPoint:CGPointMake(0.5, 0.0)];
    [gradient setEndPoint:CGPointMake(0.5, 1.0)]; // 0 degree
    [self.view.layer insertSublayer:gradient atIndex:0];
}

プロパティStartPointとEndPointはグラデーションの開始座標と終了座標を指定する。CALayerの場合、原座標はデフォルトでは左端上が(0, 0)、右端下が(1,1)に設定されており、その中の二点の座標を指定することでグラデーションの開始と終了点を指定する。

androidのDrawableで設定するAngle(角度)と対応させるとそれぞれ

StartPoint = (0.5, 0.0) EndPoint = (0.5, 1.0)

    • 45°

StartPoint = (1.0, 0.0) EndPoint = (0.0, 1.0)

    • 90°

StartPoint = (1.0, 0.5) EndPoint = (0.0, 0.5)
:
:
という対応になる。

  • 表示結果


このようにUIViewControllerで簡単にグラデーションレイヤを追加できるのは素晴らしいのだが、この方法には問題がある。


このようにビューがローテート等でリサイズした場合にレイヤが再描画されないのである。

やはりアドホックな対応というのは無理があるようだ。さて、どうしようか。

※本題とは違うが、赤から青へのグラデーションというのは美しいものだ。