を使って描画した図形とButtonなどを同じレイアウトに入れたい。そんな時はRelativeLayout等のレイアウトとCanvasを重ねると可能です
2024.1.1
CustomとLayout
Canvasで描画していて困るのは、テキストやボタンなどと一緒にスクリーン上に表示したいというリクエストです。タッチリスナーや色々と手を尽くせば可能ですがコードが煩雑になりメンテしにくくなります。
そんな時は、Canvasで作成した描画領域、ViewをあたかもTextViewなどのようにレイアウトに張り付けることで解決できます。
ViewをLayoutに入れる
Buttonなどのように扱うために「パッケージ名+Viewのクラス名」で定義します。
例えば、com.example.testcanvasinsertion がパッケージ名で
MyViewがクラス名であれば
1 2 3 4 |
<com.example.testcanvasinsertion.MyView android:layout_width="wrap_content" android:layout_height="wrap_content" ... /> |
これで、下のようにButtonやTextViewと同じように扱えます。
1 2 3 4 5 6 7 8 |
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout ... <com.example.testcanvasinsertion.MyView ... /> ... </androidx.constraintlayout.widget.ConstraintLayout > |
サンプルコード
テキストとボタンのレイアウトに Canvas の描画領域を挿入して(重ねて)みたいと思います。
MyViewクラスを新たに作成します。
MyView.java
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 |
//package com.example.testcanvasinsertion; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.util.AttributeSet; import android.view.View; public class MyView extends View { Paint paint; public MyView(Context context, AttributeSet attrs) { super(context, attrs); paint = new Paint(); } @Override protected void onDraw(Canvas canvas) { // 背景、半透明 canvas.drawColor(Color.argb(127, 0, 127, 63)); // 円 paint.setColor(Color.argb(255, 68, 255, 255)); paint.setStrokeWidth(30); paint.setAntiAlias(true); paint.setStyle(Paint.Style.STROKE); // (x1,y1,r,paint) 中心x1座標, 中心y1座標, r半径 canvas.drawCircle(450, 450, 100, paint); // 矩形 paint.setColor(Color.argb(255, 255, 190, 0)); paint.setStrokeWidth(10); paint.setStyle(Paint.Style.STROKE); // (x1,y1,x2,y2,paint) 左上の座標(x1,y1), 右下の座標(x2,y2) canvas.drawRect(480, 480, 850, 880, paint); // 線 paint.setStrokeWidth(15); paint.setColor(Color.argb(255, 0, 255, 120)); // (x1,y1,x2,y2,paint) 始点の座標(x1,y1), 終点の座標(x2,y2) canvas.drawLine(350, 850, 750, 630, paint); } } |
次にMainActivityを作ります。
MainActivity.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
//package com.example.testcanvasinsertion; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.widget.TextView; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView label = this.findViewById(R.id.label); label.setText(R.string.text); } } |
activity_main.xmlのレイアウトファイルに
com.example.testcanvasinsertion.MyView
のタグで記述します
activity_main.xml
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 |
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#000" tools:context=".MainActivity"> <!-- ここは自分のプロジェクトに合わせる --> <com.example.testcanvasinsertion.MyView android:layout_width="340dp" android:layout_height="420dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" /> <TextView android:id="@+id/label" android:textSize="20sp" android:textColor="#cccccc" android:layout_marginStart="100dp" android:layout_marginEnd="60dp" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.2" /> <Button android:text="@string/button" android:layout_width="200dp" android:layout_height="wrap_content" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.88" /> </androidx.constraintlayout.widget.ConstraintLayout> |
stringのリソースです
strings.xml
1 2 3 4 5 6 7 |
<resources> <string name="app_name">TestCanvasInsertion</string> <string name="button">Button</string> <string name="text">"abcd123456789cdefg\n1234567893456978 \nhijklmnopq012698745rst4565848uvwxlmnopqffsjldalkdfasdfks \n\n\n\n\n\n012698745rst4565848asdf\nuvwx"</string> </resources> |
Canvasエリアは描画領域がわかりやすいように半透明の矩形を使いました。
- 関連ページ
- Canvas と Paint で円や矩形を描く
- Custom Canvas をレイアウトに挿入する
- Canvas を Clear して再描画
- Canvas で画像と文字を表示する
- Canvas Animation で円弧を動かす
References:
Canvas | Android Developers
Canvas and Drawables | Android Developers