モバイル開発におけるカスタムビューと描画:本質、API、そして仕組み

著者: IT Sectr 公開日: 2026-08-01 読了時間: 11 分

カスタムビューは、あらゆるモバイルアプリのユニークなインターフェースの基盤です。モバイルアプリのカスタムビューを使用すると、標準コンポーネントでは利用できない独自のグラフィック、アニメーション、要素を作成できます。Apple Developer、2025によると、drawRectはiOSモバイル開発におけるカスタム描画の主要メソッドであり続けています。AndroidではCanvasを伴うonDrawが同じ役割を果たし、FlutterではCustomPainterがその役割を担います。

重要なポイント

  • カスタムビュー — モバイルアプリにおいて、独自の描画、サイズ、動作ロジックを持つユーザー定義コンポーネント。
  • drawRect — iOSでCore GraphicsとCGContextを使用したカスタム描画のためのUIViewメソッド。
  • onDraw — AndroidでCanvasとPaintを使用し、onMeasure測定システムを伴う描画のためのViewメソッド。
  • CustomPainter — paintメソッドとshouldRepaintメソッドを使用してCanvasに描画するFlutterクラス。
  • 測定 — iOSのsizeThatFits、AndroidのonMeasure、FlutterのcomputeDryLayoutを介してビューの寸法を決定するプロセス。

カスタムビューとは何か、モバイルアプリでなぜ必要か

カスタムビューは、独自のグラフィックを作成するために標準の描画および測定メソッドをオーバーライドするユーザー定義のインターフェースコンポーネントです。グラフ、アニメーション、図表、カスタムチャット要素、ARマスク — これらはモバイルアプリにおけるカスタムビューの典型的な使用例です。標準のUIコンポーネント(Button、TextView、Label)は80%のタスクをカバーしますが、残りの20%はモバイル開発における描画の完全な制御を必要とします。モバイル開発における描画は、ジュニア開発者とシニア開発者を区別するスキルです。

カスタムビューが正当化される場合

モバイルアプリのカスタムビューは、ユニークな2Dグラフィック、複雑なアニメーション、チャート、データ可視化のために必要です。標準のUIKitが必要な要素を提供しない場合 — カスタムビューが作成されます。モバイルアプリでは、カスタムビューはプログレスバー、カスタムボタン、グラデーション塗りつぶし、アニメーションアイコン、指での描画キャンバスに使用されます。過度に使用しないことが重要です — シンプルなスタイルには、Appearance APIを介して標準コンポーネントを設定するだけで十分です。

iOSのカスタムビュー:drawRectとCore Graphics

iOSでは、UIViewを継承してdrawRectメソッドをオーバーライドすることでカスタムビューを作成します。drawRectは最初のレンダリング時と、setNeedsDisplay()の呼び出しごとに呼び出されます。drawRect内で、開発者はUIGraphicsGetCurrentContext()を介してCGContextを取得します — 線、図形、グラデーション、テキストのためのキャンバスです。Core Graphics(Quartz 2D)は、すべてのピクセルを完全に制御できる低レベルのCPUベースのレンダリングエンジンです。UIBezierPathは、簡潔な構文でパスを作成するための便利なラッパーです。

swift
class CircleView: UIView {
    private var fillColor: UIColor = .systemBlue

    override func drawRect(_ rect: CGRect) {
        guard let ctx = UIGraphicsGetCurrentContext() else { return }
        ctx.setFillColor(fillColor.cgColor)
        ctx.addEllipse(in: bounds.insetBy(dx: 4, dy: 4))
        ctx.drawPath(using: .fill)
    }

    func updateColor(_ newColor: UIColor) {
        fillColor = newColor
        setNeedsDisplay()
    }
}

Core Graphics:CGContext、CGGradient、変換

Core Graphicsは、すべての描画操作のためのキャンバスであるCGContextを提供します。CGGradientは、CGColorSpace(sRGB、Display P3)をサポートして線形および放射状のグラデーションを作成します。変換はCGAffineTransformを介して実行されます — 回転、スケーリング、移動のための3x3マトリックスです。CGContextTranslateCTM、CGContextRotateCTM、CGContextScaleCTMは座標系を変更します。Core GraphicsはCPUで動作するため、複雑なグラフィックはプロセッサに負荷をかける可能性があります — GPUアクセラレーションにはMetalを使用してください。

図形作成のためのUIBezierPath

UIBezierPathはCGPath上のオブジェクト指向ラッパーです。addArc(withCenter:radius:startAngle:endAngle:clockwise:)メソッドは円弧と円を作成し、addCurveはベジェ曲線を作成します。パスはaddClipを介して結合、交差、減算操作をサポートします。UIBezierPathは、カスタムマスク(maskView)、クリッピングパス、複雑な図形 — 星、ハート、カスタムアイコンに便利です。

Androidのカスタムビュー:onDrawとCanvas

Androidでは、カスタムビューはonDraw(Canvas)をオーバーライドしてViewを拡張します。Canvasにはモバイル開発におけるすべての描画メソッドが含まれています:drawCircle、drawRect、drawLine、drawText、drawBitmap、drawPath、drawRoundRect。Paintはパラメータを設定します — 色、線の太さ、スタイル(FILL、STROKE、FILL_AND_STROKE)、アンチエイリアス(isAntiAlias)、テキストサイズ。onDrawはinvalidate()のたびに呼び出され、重い操作を含めてはいけません — すべての計算はキャッシュされます。

kotlin
class CustomCircleView(context: Context, attrs: AttributeSet?)
    : View(context, attrs) {

    private val paint = Paint().apply {
        style = Paint.Style.FILL
        color = Color.BLUE
        isAntiAlias = true
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        val cx = width / 2f
        val cy = height / 2f
        val radius = minOf(cx, cy) - 4f
        canvas.drawCircle(cx, cy, radius, paint)
    }
}

AndroidのPathとアニメーション

AndroidのPathはUIBezierPathに相当します:addCircle、addRect、addOval、lineTo、cubicTo、quadTo。PathMeasureはパスの長さと任意のポイントの座標を計算します — パスに沿ったオブジェクトの動きをアニメーション化するのに便利です。アニメーションには、コールバックでinvalidate()を使用するValueAnimatorを使用します。アニメーターは色、半径、位置を変更できます — 描画に影響を与える任意のプロパティです。Androidのカスタムビューは、XMLを介したアニメーションのためのStateListDrawableとanimated-vectorもサポートしています。

CanvasのShaderとグラデーション

AndroidのグラデーションはShaderを介して設定されます — LinearGradient、RadialGradient、SweepGradient。Shaderはpaint.setShader(shader)を介してPaintに割り当てられます。LinearGradientは、2点間のオプションの色位置を持つ線形グラデーションを生成します。RadialGradient — 中心から端への放射状。SweepGradient — 中心点の周りの円錐状。Shader.TileMode(CLAMP、REPEAT、MIRROR)は領域の境界を超えた動作を定義します。

FlutterのCustomPainter:Canvasへの描画

FlutterはCustomPainterを使用します — paint(Canvas canvas, Size size)メソッドとshouldRepaintメソッドを持つクラスです。FlutterのCanvasはAndroidと同じメソッドを提供します:drawCircle、drawRect、drawLine、drawPath、drawParagraph、drawImage。FlutterのPaintは色、太さ、スタイル、アンチエイリアスを設定します。FlutterはdrawRectやonDrawを使用しません — すべての描画はCustomPaintウィジェットに組み込まれたCustomPainterを介して行われます。

dart
class CirclePainter extends CustomPainter {
  final Color color;

  CirclePainter({required this.color});

  @override
  void paint(Canvas canvas, Size size) {
    final paint = Paint()
      ..color = color
      ..style = PaintingStyle.fill
      ..isAntiAlias = true;
    final radius = size.shortestSide / 2 - 4;
    canvas.drawCircle(size.center(Offset.zero), radius, paint);
  }

  @override
  bool shouldRepaint(CirclePainter oldDelegate) =>
    oldDelegate.color != color;
}

shouldRepaintとRepaintBoundary

shouldRepaintは、CustomPainterを再描画する必要があるかどうかを決定します。レンダリングに影響を与えるデータが変更された場合のみtrueを返します — 色、サイズ、チャートデータ。RepaintBoundaryは再描画を個別のレイヤーに分離します — めったに変更されないウィジェットに使用します。FlutterにはsetNeedsDisplayやinvalidateはありません — 再描画はsetStateまたは変更をリッスンするValueNotifierを介してトリガーされます。

Flutterのグラデーションと変換

FlutterはLinearGradient、RadialGradient、SweepGradientをサポートしています — Androidと同じタイプです。GradientはcreateShader(Rect bounds)を介してPaintのShaderを作成します。変換はcanvas.rotate、canvas.scale、canvas.translate、canvas.skewを介して実行されます。FlutterはTransformウィジェットに4x4変換マトリックス(Matrix4)を使用します。Flutterの描画アニメーションは、CustomPainterを再描画するためにsetStateと組み合わせてAnimationControllerを使用して行われます。

カスタムビューの測定:sizeThatFits、onMeasure、computeDryLayoutメソッド

カスタムビューの正確な測定は、予測可能なインターフェース動作の基盤です。iOSでは、ビューのサイズはsizeThatFitsとintrinsicContentSizeを介して決定されます。sizeThatFitsは、指定された制約に対する最適なサイズを返します。intrinsicContentSize — 外部制約のないコンテンツの自然なサイズ。Androidでは、測定はMeasureSpecパラメータ(UNSPECIFIED、EXACTLY、AT_MOST)を使用してonMeasureで実装されます。Flutterでは、サイズはpaint(Canvas, Size)に渡され、computeDryLayoutまたはLayoutBuilderを介して計算できます。

iOSのsizeThatFitsとintrinsicContentSize

intrinsicContentSizeはCGSizeを返します — そのコンテンツに基づくビューの自然なサイズです。setContentHuggingPriorityとsetContentCompressionResistancePriorityは、伸長と圧縮時の動作を制御します。sizeThatFitsは、Auto Layoutでサイズを計算するためにシステムによって呼び出されます。カスタムビューの場合、コンポーネントに自然なサイズがある場合はintrinsicContentSizeをオーバーライドします — たとえば、円は常に100x100である必要があります。

AndroidのonMeasureとMeasureSpec

onMeasureはwidthMeasureSpecとheightMeasureSpecを受け入れます。MeasureSpecにはモードとサイズが含まれています:UNSPECIFIED(制約なし、ビューが自身のサイズを選択)、EXACTLY(親からの正確なサイズ)、AT_MOST(最大サイズ)。setMeasuredDimension(width, height)は測定結果を保存します。データが変更されたら、再測定のためにrequestLayout()を呼び出します。ネストされたViewGroupは、子要素を配置するためにonLayoutのオーバーライドが必要です。

プラットフォーム測定メソッド変更時の呼び出し戻り値
iOSsizeThatFits / intrinsicContentSizesetNeedsLayout / invalidateIntrinsicContentSizeCGSize
AndroidonMeasure / setMeasuredDimensionrequestLayout / invalidatevoid(サイズを保存)
FluttercomputeDryLayoutsetState / LayoutBuilderSize

FlutterのcomputeDryLayout

computeDryLayoutは、完全なレイアウトサイクルなしでサイズを計算するためのRenderObjectメソッドです。LayoutBuilder.getSize — buildメソッドで利用可能なスペースを取得するための代替手段です。Flutterでは、キャンバスのサイズはSizeとしてpaintに渡され、個別の測定は必要ありません — CustomPainterは渡された境界内で描画します。ただし、カスタムRenderObjectの場合は、performLayoutとcomputeDryLayoutをオーバーライドする必要があります。

よくある質問

iOSのdrawRectとは何ですか?いつ呼び出されますか?

drawRectは、Core Graphicsを介したカスタム描画のためのUIViewメソッドです。ビューの最初のレンダリング時と、setNeedsDisplay()の呼び出しごとに呼び出されます。線、図形、テキストについてはdrawRect内でCGContextを使用します。

Canvasを使用してAndroidで描画するには?

Viewを拡張するクラスを作成し、onDraw(Canvas canvas)をオーバーライドしてCanvas APIを使用します:drawCircle、drawRect、drawPath。Paintは色、太さ、スタイルを設定します。更新するにはinvalidate()を呼び出します。

FlutterのCustomPainterとは何ですか?

CustomPainterは、Canvasへのカスタム描画のためのFlutterクラスです。paint(Canvas, Size)メソッドとshouldRepaintメソッドを実装します。CustomPaintウィジェットを介して配置されます。FlutterにはdrawRectはありません — すべての描画はCustomPainterを介して行われます。

カスタムビューのサイズを測定するには?

iOSではsizeThatFitsとintrinsicContentSizeを使用します。Androidでは — MeasureSpecを伴うonMeasure。Flutterでは、サイズはpaint(Canvas, Size)に渡されるか、computeDryLayoutを介して計算されます。各プラットフォームは独自の測定メソッドを使用します。

標準コンポーネントの代わりにカスタムビューを使用するのはいつですか?

カスタムビューは、標準のUIKitやViewでは実装できないユニークなグラフィック、アニメーション、チャート、要素に必要です。シンプルなスタイルの場合は、標準コンポーネントを設定するだけで十分です — 不必要にアーキテクチャを複雑にしないでください。

まとめ

  • カスタムビュー — モバイルアプリのグラフ、アニメーション、非標準要素のためのユニークなインターフェースの基盤。
  • drawRect — CGContextとUIBezierPathを使用したCore Graphicsによる描画のためのiOSメソッド。
  • onDraw — PathとShaderのサポートを備えたCanvasとPaintによる描画のためのAndroidメソッド。
  • CustomPainter — shouldRepaintとRepaintBoundaryを使用してCanvasに描画するためのFlutterクラス。
  • 測定 — sizeThatFits(iOS)、onMeasure(Android)、computeDryLayout(Flutter)によるサイズ検証。
  • モバイル開発における描画は、すべてのプラットフォームで統一されたパターンに従います:コンテキストを取得し、スタイルを設定し、プリミティブを描画します。
  • 描画オブジェクト(Paint、Path)をキャッシュします — 安定したパフォーマンスのために、drawRect、onDraw、またはpaint内で作成しないでください。

ターンキー方式のモバイルアプリケーションを開発します

IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。

プロジェクトについて相談