TextViewやImageViewなどはConstraintLayoutなどのレイアウトを使ってViewを表示させますが、もっと自由に直線や図形を描画するためには Canvas を使います。
2024.1.1
Canvas
GoogleはAndroidフレームワークとしてグラフィックスにおいては2つの方法を提供しています。
- Drawables
- 画像などをViewを使って表示。静的で表示させるだけの用途であり、アニメーションでも決まりきった動きのものに適している
パフォーマンスを必要とするようなゲームにはあまり向かない - 代表的な例は、画像をresourceのdrawableにおいてImageViewを使って表示するような例。
- 画像などをViewを使って表示。静的で表示させるだけの用途であり、アニメーションでも決まりきった動きのものに適している
- Canvas
- onDrawメソッドを使ってCanvas上で描画。ゲームなどの動きがありグラフィックスのredrawが頻繁に起きる場合や、カスタマイズされたアニメーションに向いている
Ref: Canvas and Drawables
drawLine
始点座標を(startX, startY) 終点座標を(stopX, stopY) としてラインを引く
1 2 3 4 5 |
public void drawLine (float startX, float startY, float stopX, float stopY, Paint paint) |
drawCircle
中心点を (cx, cy) 、半径 radius とした円を描く
1 2 3 4 |
public void drawCircle (float cx, float cy, float radius, Paint paint) |
drawRect
左上座標を (left, top)、右下座標を (right, bottom) とした矩形を描く
1 2 3 4 5 |
public void drawRect (float left, float top, float right, float bottom, Paint paint) |
ゲームのようなものでなければDrawablesを使えばそこそこできますが、どうしてもカスタム化して動きを入れたいというような場合ではCavasを使います。
Canvasの基本的な形
Canvasでprimitiveな矩形を描画する基本的な例です。
Activity から View を継承したクラスを作りsetContentViewに入れてonDraw() で描画します。setContentView(MyView)
レイアウトファイルは使いません。
MainActivity.kt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
//package com.example.kotlincanvas import android.os.Bundle import androidx.activity.enableEdgeToEdge import androidx.appcompat.app.AppCompatActivity import android.content.Context import android.graphics.Canvas import android.graphics.Color import android.graphics.Paint import android.view.View class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() // setContentView(R.layout.activity_main) // ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets -> // val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()) // v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom) // insets // } val myView = MyView(this) setContentView(myView) } // Viewを継承したクラス internal inner class MyView(context: Context) : View(context) { private var paint: Paint = Paint() // 描画するラインの太さ private val lineStrokeWidth = 20f init { } override fun onDraw(canvas: Canvas){ // ペイントする色の設定 paint.color = Color.argb(255, 255, 0, 255) // ペイントストロークの太さを設定 paint.strokeWidth = lineStrokeWidth // Styleのストロークを設定する paint.style = Paint.Style.STROKE // drawRectを使って矩形を描画する、引数に座標を設定 // (x1,y1,x2,y2,paint) 左上の座標(x1,y1), 右下の座標(x2,y2) canvas.drawRect(300f, 300f, 600f, 600f, paint) } } } |
矩形が描画されました。
矩形の描画では
Paint クラスの
color で線の色を指定
strokeWidth にて線の太さ
Canvas クラスの
drawRect を使って4つの頂点を引数に入れます。
サンプルコード
矩形以外にも円、楕円のような基本的なprimitiveな図形を描画するメソッドもあります。またラインを組み合わせて三角形を作ることもできます。
MainActivity.kt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
//package your.package.name import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.content.Context import android.graphics.Canvas import android.graphics.Color import android.graphics.Paint import android.graphics.Path import android.view.View class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val myView = MyView(this) setContentView(myView) } internal inner class MyView(context: Context) : View(context) { private val paint = Paint() private val path = Path() private val strokeW1 = 20f private val strokeW2 = 40f private val dp: Float = resources.displayMetrics.density override fun onDraw(canvas: Canvas) { // Canvas Background Color canvas.drawColor(Color.argb(255, 0, 0, 125)) // Canvas center point val xc = (width / 2).toFloat() val yc = (height / 2).toFloat() // Circle paint.color = Color.argb(255, 125, 125, 255) paint.strokeWidth = strokeW1 paint.isAntiAlias = true paint.style = Paint.Style.STROKE // (x1,y1,r,paint) 中心x1座標, 中心y1座標, r半径 canvas.drawCircle(xc - 15 * dp, yc - 55 * dp, xc / 2, paint) // Rectangle paint.color = Color.argb(255, 255, 0, 255) paint.style = Paint.Style.STROKE // (x1,y1,x2,y2,paint) 左上の座標(x1,y1), 右下の座標(x2,y2) canvas.drawRect(xc - 30 * dp, yc - 50 * dp, xc + 120 * dp, yc + 100 * dp, paint) // Lines paint.strokeWidth = strokeW1 paint.color = Color.argb(255, 0, 255, 0) // (x1,y1,x2,y2,paint) 始点の座標(x1,y1), 終点の座標(x2,y2) canvas.drawLine(xc + 20 * dp, yc - 30 * dp, xc - 70 * dp, yc + 70 * dp, paint) // Triangle val tx1 = 230 * dp val ty1 = 370 * dp val tx2 = 100 * dp val ty2 = 500 * dp val tx3 = 350 * dp val ty3 = 500 * dp paint.strokeWidth = 10f paint.color = Color.WHITE path.moveTo(tx1, ty1) path.lineTo(tx2, ty2) path.lineTo(tx3, ty3) path.lineTo(tx1, ty1) canvas.drawPath(path, paint) // Circle paint.color = Color.YELLOW paint.strokeWidth = strokeW2 paint.isAntiAlias = true paint.style = Paint.Style.STROKE // (x,y,r,paint) x座標, y座標, r半径 canvas.drawCircle(220 * dp, 130 * dp, 40 * dp, paint) } } } |
ここで指定している(x,y)はピクセルになりますので端末依存です。スクリーン縦横のサイズを取得して計算する必要があります。
JavaでのCanvas:
References:
Canvas | Android Developers
Canvas and Drawables | Android Developers