TextViewやImageViewなどはConstraintLayoutなどのレイアウトを使ってViewを表示させますが、もっと自由に直線や図形を描画するためには Canvas を使います。
 
![[Android & Kotlin] 円や矩形を描画するCanvas 1x1.trans - [Android & Kotlin] 円や矩形を描画するCanvas](https://akira-watson.com/wp-content/themes/simplicity2/images/1x1.trans.gif)
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)         }     } }  | 
					
 
![[Android & Kotlin] 円や矩形を描画するCanvas 1x1.trans - [Android & Kotlin] 円や矩形を描画するCanvas](https://akira-watson.com/wp-content/themes/simplicity2/images/1x1.trans.gif)
矩形が描画されました。
矩形の描画では
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)はピクセルになりますので端末依存です。スクリーン縦横のサイズを取得して計算する必要があります。
 
![[Android & Kotlin] 円や矩形を描画するCanvas 1x1.trans - [Android & Kotlin] 円や矩形を描画するCanvas](https://akira-watson.com/wp-content/themes/simplicity2/images/1x1.trans.gif)
JavaでのCanvas:
 
 
References:
Canvas | Android Developers
Canvas and Drawables | Android Developers