前のページで Canvas で描画した領域を消したり表示したりする場合にPorterDuff.Mode.CLEARを使いましたが、部分的に表示・非表示をしたい場合にはちょっと使いにくいかもしれません。
それぞれが重なっていると、重なった部分が黒抜きで消えたり色々面倒です。シンプルに全て再描画を使う方がいいかもしれません。
。
2021.2.1
Canvasに画像とテキストを描画
この例では、TextViewでのテキストとCanvas上のテキストが混在します。またCanvas領域に画像を表示していますが、これもImageViewで表示することもできます。このようにCanvasを使った表現の幅を種々広げることができるのが分かります。
Canvasに画像とテキストを描画
画像をdrawableに入れて、CanvasのためのViewを継承したクラスを作成します。
画像の描画
1 2 3 4 5 6 7 8 9 10 |
// 画像をresource drawableからBitmapとして呼び出し Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.image); ... @Override protected void onDraw(Canvas canvas) { ... // drawBitmapを使って描画 canvas.drawBitmap(bmp, x, y, paint); ... } |
文字列の表示
1 2 3 4 5 6 7 8 9 10 |
... @Override protected void onDraw(Canvas canvas) { ... // StyleをFILL_AND_STROKEに変更 Paint.Style.FILL_AND_STROKE // drawTextで文字列を表示 canvas.drawText("Text", x, y, paint) ... } |
サンプルコード
以前の方法 と同じように作っていきます。この例の package は 「com.example.testcanvasimagetext」で設定しました。
button によりCanvas領域での画像と文字を切り替えます。
画像 img.jpg など適宜drawableに入れておきます。
まずCanvasを作るためにTestCanvasViewクラスを新しく作成
TestCanvasView.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 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
//package com.example.testcanvasimagetext; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.util.AttributeSet; import android.view.View; public class TestCanvasView extends View { private final Paint paint; private Boolean viewflg; private final Bitmap bmp; public TestCanvasView(Context context, AttributeSet attrs) { super(context, attrs); paint = new Paint(); viewflg = true; bmp = BitmapFactory.decodeResource(getResources(), R.drawable.img); } public void showCanvas(boolean flg){ viewflg = flg; invalidate(); } @Override protected void onDraw(Canvas canvas) { // 背景、半透明 canvas.drawColor(Color.argb(125, 0, 0, 255)); // Bitmap 画像を表示 if(viewflg){ canvas.drawBitmap(bmp, 80, 200, paint); } // Textの表示 else{ paint.setStyle(Paint.Style.FILL_AND_STROKE); paint.setStrokeWidth(5); paint.setTextSize(100); paint.setColor(Color.argb(255, 255, 255, 0)); canvas.drawText("Yumiko Watanabe", 120, 600, paint); } // 円 paint.setColor(Color.argb(255, 255, 0, 255)); paint.setStrokeWidth(30); paint.setAntiAlias(true); paint.setStyle(Paint.Style.STROKE); // (x1,y1,r,paint) 中心x1座標, 中心y1座標, r半径 canvas.drawCircle(130, 150, 100, paint); paint.setStrokeWidth(30); paint.setAntiAlias(true); paint.setStyle(Paint.Style.STROKE); // (x1,y1,r,paint) 中心x1座標, 中心y1座標, r半径 canvas.drawCircle(130, 150, 50, paint); } } |
MainActivity.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 |
//package com.example.testcanvasimagetext; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.widget.Button; import android.widget.TextView; public class MainActivity extends AppCompatActivity { private boolean showCanvas; private TestCanvasView testCanvasView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView label = this.findViewById(R.id.label); label.setText(getString(R.string.text)); testCanvasView = this.findViewById(R.id.test_view); testCanvasView.showCanvas(true); showCanvas = true; Button button = findViewById(R.id.button); button.setOnClickListener(v -> { if (showCanvas) { testCanvasView.showCanvas(false); showCanvas = false; } else { testCanvasView.showCanvas(true); showCanvas = true; } }); } } |
レイアウトの中にカスタムで作成したCanvasを挿入する形にします。
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 |
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#000" tools:context=".MainActivity"> <!-- projectのpackagename+canvasにクラス --> <com.example.testcanvasimagetext.TestCanvasView android:id="@+id/test_view" android:layout_marginTop="70dp" android:layout_marginBottom="100dp" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:id="@+id/label" android:textSize="20sp" android:textColor="#ccc" android:layout_marginTop="20dp" android:layout_marginLeft="30dp" android:layout_marginRight="30dp" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <Button android:id="@+id/button" android:text="@string/button" android:layout_alignParentBottom="true" android:layout_marginBottom="20dp" android:layout_marginLeft="80dp" android:layout_marginRight="80dp" android:layout_width="match_parent" android:layout_height="wrap_content" /> </RelativeLayout> |
strings.xml
1 2 3 4 5 |
<resources> <string name="app_name">TestCanvasImageText</string> <string name="button">Button</string> <string name="text">"Test Canvas\nBitMap amp Text"</string> </resources> |
サンプル動画
描画を繰り返す場合のメモリには注意が必要です
Canvas のスクロール
ScrollViewにCanvasをaddすることでスクロールできるようです。
MainActivity.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
//package com.example.testcanvasimagetextscroll; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.widget.ScrollView; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TestCanvasView testCanvasView = new TestCanvasView(this); ScrollView scrollView = new ScrollView(this); // ScrollViewに追加 scrollView.addView(testCanvasView); // ScrollViewをセットする setContentView(scrollView); } } |
TestCanvasView.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 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 |
//package com.example.testcanvasimagetextscroll; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.view.View; public class TestCanvasView extends View { private final Paint paint; private final Bitmap bmp; public TestCanvasView(Context context) { super(context); paint = new Paint(); bmp = BitmapFactory.decodeResource(getResources(), R.drawable.img); } // heightがスクロール画面の高さ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width = MeasureSpec.getSize(widthMeasureSpec); int height = 10000; setMeasuredDimension(width, height); } @Override protected void onDraw(Canvas canvas) { // 背景、半透明 canvas.drawColor(Color.argb(125, 0, 0, 255)); // Bitmap 画像を表示 canvas.drawBitmap(bmp, 50, 300, paint); // Textの表示 paint.setStyle(Paint.Style.FILL_AND_STROKE); paint.setStrokeWidth(5); paint.setTextSize(100); paint.setColor(Color.argb(255, 255, 255, 0)); canvas.drawText("Yumiko Watanabe", 120, 2400, paint); // 円 paint.setColor(Color.argb(255, 255, 0, 255)); paint.setStrokeWidth(30); paint.setAntiAlias(true); paint.setStyle(Paint.Style.STROKE); // (x1,y1,r,paint) 中心x1座標, 中心y1座標, r半径 canvas.drawCircle(130, 550, 100, paint); paint.setStrokeWidth(30); paint.setAntiAlias(true); paint.setStyle(Paint.Style.STROKE); // (x1,y1,r,paint) 中心x1座標, 中心y1座標, r半径 canvas.drawCircle(130, 550, 50, paint); // 矩形 paint.setColor(Color.argb(255, 0, 0, 255)); paint.setStyle(Paint.Style.STROKE); // (x1,y1,x2,y2,paint) 左上の座標(x1,y1), 右下の座標(x2,y2) canvas.drawRect(100, 1600, 500, 1800, paint); // 線 paint.setStrokeWidth(10); paint.setColor(Color.argb(255, 0, 255, 0)); // (x1,y1,x2,y2,paint) 始点の座標(x1,y1), 終点の座標(x2,y2) canvas.drawLine(600, 1800, 1000, 1400, paint); canvas.drawLine(700, 1800, 1100, 1400, paint); canvas.drawLine(800, 1800, 1200, 1400, paint); } } |
これでCanvasもスクロールさせることができました。
関連ページ:
- Canvas と Paint で円や矩形を描く
- Custom Canvas をレイアウトに挿入する
- Canvas を Clear して再描画
- Canvas で画像とテキストを表示する
- Canvas Animation で円弧を動かす
References:
Canvas | Android Developers
Canvas and Drawables | Android Developers