AndroidのCanvas: その概要、Canvasクラス、drawメソッド

著者: IT Sectr 公開日: 2026-07-21 読了時間: 7 分

AndroidのCanvas — android.graphicsパッケージのクラスで、View上での2DレンダリングのためのAPIを提供します。Canvasはキャンバスとして機能し、開発者はさまざまなdraw*メソッドを使用して幾何学的図形、テキスト、画像、パスを描画します。Androidデベロッパーズドキュメンテーション(2025)によると、CanvasはAndroidでのカスタムレンダリングの主要ツールであり、スタイルと色を定義するためにPaintクラスと一緒に使用されます。各onDraw()呼び出しは、ビューのビットマップバッファに関連付けられた準備済みのCanvasインスタンスを受け取ります。

重要なポイント

  • Canvas — Androidでの2Dレンダリング用クラス。drawRect、drawCircle、drawText、drawBitmapなどのメソッドを提供
  • Paint — レンダリングスタイル(色、太さ、塗りつぶし、影、グラデーションなどの効果)を定義するクラス
  • onDraw(Canvas) — 受け取ったCanvasを介してすべてのレンダリングが行われるViewのメソッド
  • Canvas.save()とrestore() — ネストされた座標系変換のための変換スタックの管理
  • Path — 任意の輪郭や曲線を構築するためのクラス。drawPath(Path, Paint)に渡される

AndroidのCanvasとは

Canvas — Androidの中心的な2Dグラフィックスクラスであり、平面上に描画するためのメソッドを提供します。各CanvasはBitmapに関連付けられています — 描画操作の結果が記録されるメモリ領域です。Viewが再描画されると、システムはonDraw()にそのViewのバッファにすでに関連付けられたCanvasを渡します。

Canvasは、(0,0)が左上隅、X軸が右、Y軸が下の座標系で動作します。すべての描画操作は、変換行列、クリッピング領域、Paintスタイルを含むCanvasの現在の状態を使用します。Androidドキュメンテーション(2025)によると、Canvas APIにはさまざまな種類のグラフィックプリミティブのための30以上のdraw*メソッドが含まれています。

Canvasとハードウェアアクセラレーション

Android 3.0(API 11)以降、CanvasはDisplayListを介したハードウェアアクセラレーションをサポートしています。アクセラレーションモードでは、Canvas操作はDisplayListに記録され、GPUで実行されます。これにより大幅なパフォーマンス向上が得られますが、制限もあります。一部のCanvas操作(非PathクリップでのclipPath)はアクセラレーションモードでサポートされていません。

Canvasの基本的なレンダリングメソッド

Canvasは基本的なプリミティブを描画するための一連のメソッドを提供します。各メソッドは幾何学的パラメータと、視覚スタイルを定義するPaintオブジェクトを受け入れます。

メソッド目的
drawRect()長方形を描画canvas.drawRect(10f, 10f, 100f, 100f, paint)
drawCircle()円を描画canvas.drawCircle(50f, 50f, 30f, paint)
drawLine()線を描画canvas.drawLine(0f, 0f, 100f, 100f, paint)
drawText()テキストを描画canvas.drawText(“Hello”, 10f, 20f, paint)
drawBitmap()画像を描画canvas.drawBitmap(bitmap, 0f, 0f, paint)
drawPath()任意のパスを描画canvas.drawPath(path, paint)
drawOval()楕円を描画canvas.drawOval(rectF, paint)
drawArc()円弧または扇形を描画canvas.drawArc(rectF, 0f, 90f, true, paint)

各メソッドは任意の順序で呼び出すことができます — Canvasは呼び出し順に描画し、新しい要素を前の要素の上に重ねます。複雑な構成では、Canvas状態の保存と復元を使用したマルチレイヤーレンダリング手法が使用されます。

Paintクラス: スタイルと効果の設定

Paint — Canvasがどのように描画するかを定義するクラスです。PaintなしではCanvasメソッドは無意味です — 色、線の太さ、塗りつぶしスタイル、テキストサイズ、効果(影、グラデーション、ぼかし)およびブレンドモードを設定します。

Paintには主要なプロパティがあります: color(色)、style(FILL、STROKE、またはFILL_AND_STROKE)、strokeWidth(線の太さ)、textSize(テキストサイズ)、isAntiAlias(アンチエイリアシング)、shader(グラデーションまたは画像)。Paintオブジェクトの作成はコストのかかる操作であるため、一度作成して再利用する必要があります。

kotlin
private val fillPaint = Paint().apply {
    color = Color.parseColor("#FF6200EE")
    style = Paint.Style.FILL
    isAntiAlias = true
}

private val strokePaint = Paint().apply {
    color = Color.WHITE
    style = Paint.Style.STROKE
    strokeWidth = 4f
    isAntiAlias = true
}

override fun onDraw(canvas: Canvas) {
    super.onDraw(canvas)
    canvas.drawCircle(100f, 100f, 80f, fillPaint)
    canvas.drawCircle(100f, 100f, 80f, strokePaint)
}

この例では、2つのPaintオブジェクトが使用されています。1つは円を紫色で塗りつぶすため、もう1つは白いストロークのためです。塗りつぶしとストロークを分離することは、オブジェクトを再作成せずに外観を柔軟に制御できる標準的なプラクティスです。

Shaderとグラデーション

グラデーションの塗りつぶしのために、PaintはShaderを受け入れます — サブクラスLinearGradient、RadialGradient、SweepGradient。ShaderはsetShader()メソッドを介してPaintにバインドされ、描画領域全体で色がどのように変化するかを定義します。

Canvasの変換: translate、rotate、scale

Canvasは座標系の行列変換をサポートしています: translate()(移動)、rotate()(回転)、scale()(拡大縮小)、skew()(傾斜)。変換は累積されます。後続の各呼び出しは前の呼び出しの上に適用されます。

変換スタックの管理はsave()restore()を介して行われます。save()は現在のCanvas状態(行列、クリップ)をスタックに保存し、restore()は最後に保存された状態を復元します。save()とrestore()の間では、ネストされた変換を適用できます。

kotlin
override fun onDraw(canvas: Canvas) {
    super.onDraw(canvas)

    canvas.save() // Save initial state
    canvas.translate(100f, 100f) // Translate origin

    // First square
    canvas.drawRect(0f, 0f, 50f, 50f, fillPaint)

    canvas.save() // Save after translate
    canvas.rotate(45f, 25f, 25f) // Rotate around square center

    // Rotated square
    canvas.drawRect(0f, 0f, 50f, 50f, strokePaint)
    canvas.restore() // Restore after rotate

    canvas.restore() // Restore initial state
}

変換を開始する前には必ずsave()を、変換を完了した後にはrestore()を使用してください。不均衡なsave/restoreは行列の累積と後続要素の不正確なレンダリングを引き起こします。

複雑なグラフィックのためのBitmapとPathを使用したCanvas

複雑なグラフィックのために、CanvasはBitmapおよびPathと組み合わせて使用されます。Bitmapは画像の読み込みとレンダリングされたフレームのキャッシュに使用されます。Pathは任意のベジェ曲線、多角形、複雑な輪郭を構築するために使用されます。

オフスクリーンBitmapバッファ

オフスクリーンレンダリング手法: Bitmapを作成し、別のCanvasを介して複雑なシーンをその上に描画し、完成したBitmapをdrawBitmap()を介してonDraw()で出力します。これにより、毎フレームの完全な再描画なしで複雑なグラフィックを更新できます。

kotlin
private var offscreenBitmap: Bitmap? = null
private var offscreenCanvas: Canvas? = null

fun buildOffscreenScene(width: Int, height: Int) {
    offscreenBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
    offscreenCanvas = Canvas(offscreenBitmap)

    // Render scene once
    offscreenCanvas!!.drawColor(Color.WHITE)
    drawGrid(offscreenCanvas!!)
    drawComplexShape(offscreenCanvas!!)
}

override fun onDraw(canvas: Canvas) {
    super.onDraw(canvas)
    offscreenBitmap?.let { canvas.drawBitmap(it, 0f, 0f, null) }
}

Pathは複雑な輪郭の構築に使用されます: ベジェ曲線(quadTo、cubicTo)、円弧(arcTo)、線(lineTo)。Pathは塗りつぶし形状の場合は閉じる(close())ことも、線の場合は開いたままにすることもできます。主要なdrawPath()メソッドはPathとPaintを組み合わせて最終的なレンダリングを行います。

Canvasレンダリングの最適化

CanvasレンダリングのパフォーマンスはアプリケーションのFPSに直接影響します。主な問題: onDraw()での過剰なメモリ割り当て、頻繁なinvalidate()呼び出し、ハードウェアアクセラレーションの最適でない使用。

onDraw()の外部でオブジェクトを作成する

Paint、Path、Rect、RectFなどのオブジェクトは、初期化子またはsetup()メソッドで一度だけ作成する必要があります。onDraw()での各メモリ割り当てはガベージコレクタに負荷をかけ、マイクロラグを引き起こします。例外は、不変オブジェクトのためのstaticまたはcompanion objectです。

領域を制限するためにclipRect()を使用する

Viewの大部分が可視領域の外に隠れている場合(たとえばScrollView内)、レンダリングを制限するためにcanvas.clipRect()を使用します。この場合、ハードウェアアクセラレーションは非表示ピクセルのクリッピングをさらに最適化します。

kotlin
override fun onDraw(canvas: Canvas) {
    super.onDraw(canvas)

    // Clip to visible area
    canvas.save()
    canvas.clipRect(scrollX, scrollY, scrollX + width, scrollY + height)

    // Render large scene
    renderScene(canvas)
    canvas.restore()
}

更新が稀な複雑なCanvasグラフィックを持つViewには、LAYER_TYPE_HARDWAREを指定したView.setLayerType()を使用します。頻繁に更新されるアニメーションの場合は、逆にLAYER_TYPE_NONEを使用して高コストなハードウェアレイヤーの更新を避けます。GPU Profile RenderingAndroid Studio Profilerを使用してプロファイリングします。

よくある質問

ViewなしでCanvasを作成できますか?

はい、Canvas(Bitmap)を作成できます — Bitmapを受け取るコンストラクタです。これはオフスクリーンレンダリングに使用されます。Bitmapに描画し、drawBitmap()を介して出力します。CanvasはSurface(SurfaceView用)またはPictureからも作成できます。

CanvasとSurfaceViewの違いは何ですか?

Canvas — UIスレッドでViewに描画するためのAPIです。SurfaceView — 独自のCanvas(lockCanvas() / unlockCanvasAndPost())を介してバックグラウンドスレッドから更新できる別個のSurfaceです。SurfaceViewはゲームやビデオに適しています。

変換後にCanvasが描画しないのはなぜですか?

最も一般的な原因は、save()restore()の不均衡です。変換(translate、rotate)後にrestore()が呼び出されないと、Canvasは変更された座標系のままになり、後続の要素がオフセットして描画されます。save()/restore()のペアを確認してください。

Canvasの中央にテキストを描画するには?

水平方向の中央揃えにはPaint.setTextAlign(Paint.Align.CENTER)、垂直方向にはPaint.getTextBounds()またはPaint.descent() / ascent()を使用します。中央揃え: canvas.drawText(テキスト, centerX, centerY - (ascent + descent) / 2, paint)。

Canvasはアニメーションをサポートしていますか?

Canvas自体はアニメーションしません — 現在の状態を描画するだけです。アニメーションはinvalidate()(またはpostInvalidateOnAnimation())の連続呼び出しによって実現され、毎回onDraw()で新しいフレームを描画します。スムーズなアニメーションのためには、Vsyncと同期するためにValueAnimatorまたはChoreographerを使用します。

まとめ

  • Canvas — Androidの中心的な2Dレンダリングクラス。プリミティブ、テキスト、画像を描画するdraw*メソッドを提供
  • Paint — 視覚スタイル(色、太さ、塗りつぶし、シェーダー)を定義。一度作成して再利用
  • save() / restore() — 変換スタックの管理。各変換はsave/restoreのペアで行う必要がある
  • Path — 複雑なベクターグラフィックのための任意の輪郭とベジェ曲線の構築
  • Offscreen Bitmap — onDraw()の負荷を減らすためにCanvas(Bitmap)を介して複雑なシーンをキャッシュする手法
  • ハードウェアアクセラレーション — Android 3.0以降のCanvasのGPUアクセラレーション。一部の操作(clipPath)に制限あり
  • プロファイリング — onDraw()のボトルネックを見つけるにはGPU Profile RenderingとAndroid Studio Profilerが必須

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

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

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

こちらもお読みください