Search…

Canvas trong Android - Phần 1

12/11/20208 min read
Giới thiệu về Canvas trên Android và hướng dẫn lập trình đồ họa trên Android với Canvas.

Các đối tượng trên Android như TextView, EditText, ImageView đều được vẽ trên Canvas của hệ thống Android, vậy vẽ các đối tượng này như thế nào?

Canvas là gì ?

Canvas được xem là 1 bề mặt (giấy, bảng) có thể vẽ lên, ví dụ như vẽ điểm, đường thằng, hình chữ nhật, đường tròn, elip, văn bản, 1 hình ảnh và các hình học phức tạp khác.

Canvas có thể làm những gì ?

Trong Android, nếu muốn tạo 1 View và tự vẽ lại tất cả các thành phần của View đó, có thể sử dụng canvas.

Canvas trong Android cung cấp các phương thức để vẽ tất cả các đối tượng như sau:

  • Các đối tượng hình học cơ bản (point, line, oval, rectangle, ...).
  • Vẽ hình ảnh (bitmap, drawable).
  • Vẽ đường - Path (tập hợp các điểm).
  • Vẽ văn bản - Text.

Những thành phần vẽ đều được xử lý trong phương thức onDraw(Canvas canvas) của class View. Để vẽ những đối tượng thành phần lên Canvas phải sử dụng 1 đối tượng Paint để định dạng style, color, size cho nét vẽ.

Khởi tạo project làm việc với Canvas

Canvas trong Android

Chọn nền tảng và target API (có thể chọn API mới nhất).

Canvas trong Android

Sau đó nhấn Next để Android Studio tiến hành tạo project.

Canvas trong Android

Tiến hành tạo class GraphicView kế thừa từ class View để vẽ các thành phần.

package comcanvasdemo.example.nguyennghia.canvasdemo;
import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.View;
/**
 * Created by nguyennghia on 7/22/16.
 */
public class GraphicView extends View  {
    public GraphicView(Context context) {
        this(context, null);
    }

    public GraphicView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }
    public GraphicView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // Draw component in here
    }
}

Trong file activity_main.xml, thêm GraphicView với độ rộng và độ cao match_parent để có không gian rộng hiển thị các hình học:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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"
    tools:context="comcanvasdemo.example.nguyennghia.canvasdemo.MainActivity">
    <comcanvasdemo.example.nguyennghia.canvasdemo.GraphicView
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</FrameLayout>

Đối tượng Paint

Đối tượng Paint trong Android dùng để định nghĩa size, color, kiểu nét vẽ sẽ sử dụng để vẽ bởi Canvas, truyền vào phương thức canvas.draw... trong phương thức onDraw() của View.

Các phương thức của class Paint

Có 2 cách khởi tạo Paint:

  • Contructor không có đối số Paint mPaint = new Paint();
  • Contructor có 2 đối số Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

Cờ Paint.ANTI_ALIAS_FLAG truyền vào ở trên chỉ định cho Paint rằng vẽ mượt cho các biên của các đối tượng (khử răng cưa). Ví dụ như vẽ hình tròn sẽ loại bỏ những răng cưa bao quanh hình tròn, từ đó có cảm giác hình vẽ lên mượt mà hơn.

Các phương thức được sử dụng phổ biến

  • setColor(int color): đặt màu cho nét vẽ.
  • setAlpha(int a) đặt giá trị alpha (từ 0 đến 255) cho nét vẽ, thường áp dụng để tạo hiệu ứng làm mờ.
  • setStrokeWidth(float width): đặt giá trị độ rộng của nét vẽ.
  • setStyle(Style style) đặt kiểu cho nét vẽ, có 3 giá trị như sau:
    • Paint.Style.FILL: dùng để tô đối tượng, ví dụ như tô hình tròn, elip, oval.
    • Paint.Style.STROKE: dùng để vẽ đường (viền), ví dụ như vẽ đường tròn mà không có tô.
    • Paint.Style.FILL_AND_STROKE: vừa vẽ vừa tô.
  • setStrokeCap(Cap cap): đặt kiểu vẽ ở những điểm kết thúc của hai đường thẳng và có những giá trị sau:
    • Cap.ROUND: bo tròn nét vẽ ở hai đầu mút của đoạn thẳng.
    • Cap.SQUARE: vẽ nét vẽ bình thường, nét vẽ sẽ sắc cạnh ở 2 đầu mút của đoạn thẳng.
  • setTypeface(Typeface typeface): tùy chỉnh phông chữ vẽ text.
  • setTextSize(float textSize): đặt kích thước phông chữ.

Vẽ các đối tượng cơ bản bằng Canvas

Canvas cung cấp rất nhiều các phương thức để vẽ các đối tượng hình học bắt đầu bởi phương thức cavas.draw…:

  • DrawPoint
  • DrawLine
  • DrawRect
  • DrawCircle
  • DrawOvals
  • DrawArc
  • ...

Tạo 1 đối tượng Paint và đặt các thuộc tính phục vụ cho mục đích vẽ:

private void initPaint() {
    mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    mPaint.setColor(Color.BLUE);
    mPaint.setStrokeWidth(30);
}

Màu sử dụng để vẽ là màu xanh BLUE, độ rộng nét vẽ là 30 và đặt vào trong constructor thứ ba của GraphicView.

public GraphicView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    initPaint();
}

DrawPoint

Vẽ điểm tại toạ độ x, y sử dụng đối tượng paint để vẽ:

drawPoint(float x, float y, @NonNull Paint paint)

Vẽ danh sách các điểm trong mảng pts 2 vị trí kề này là x và y, sử dụng đối tượng paint để vẽ:

drawPoints(@NonNull float[] pts, @NonNull Paint paint)

Vẽ danh sách các điểm trong mảng pts và có giới hạn vẽ từ khoảng nào và độ dài là bao nhiêu?

drawPoints(float[] pts, int offset, int count, @NonNull Paint paint)

Ví dụ muốn vẽ 1 điểm ở vị trí x = 100, y = 100:

// Draw Point
int x = 100;
int y = 200;
canvas.drawPoint(x, y, mPaint);

DrawLine

Vẽ đoạn thẳng với 4 tham số là điểm startX, startY và kết thúc là điểm stopX, stopY:

drawLine(float startX, float startY, float stopX, float stopY, Paint paint)

Vẽ đoạn thẳng trong mảng pts với 4 phần tử liên tiếp sẽ là startX, startY, stopX, stopY với độ dời offset trong mảng và số phần tử để vẽ:

drawLines(float[] pts, int offset, int count, Paint paint)

Vẽ đoạn thẳng trong mảng pts, sử dụng paint để vẽ:

drawLines(float[] pts, Paint paint)

Ví dụ vẽ đường chéo từ góc trái màn hình qua góc phải màn hình sẽ làm như sau:

// Draw Line
float startX = 0;
float startY = 0;
float stopX = getWidth();
float stopY = getHeight();
canvas.drawLine(startX, startY, stopX, stopY, mPaint);

DrawRect

Vẽ hình chữ nhật với dữ liệu rect là cấu trúc kiểu số thực:

drawRect(@NonNull RectF rect, @NonNull Paint paint)

Vẽ hình chữ nhật với rect là cấu trúc kiểu số nguyên:

drawRect(@NonNull Rect rect, @NonNull Paint paint)

Với các thông số cơ bản left, top, right, bottom:

drawRect(float left, float top, float right, float bottom, @NonNull Paint paint)

Ví dụ muốn vẽ hình chữ nhật có độ rộng 100, độ cao 200 và nằm chính giữa màn hình như sau:

// Draw Rect
float width = 100;
float height = 200;
float left = (getWidth() - width) / 2.0f;
float top = (getHeight() - height) / 2.0f;
canvas.drawRect(left, top, left + width, top + height, mPaint);
mPaint.setStyle(Paint.Style.STROKE);

DrawCircle

Với 4 tham số lần lượt là tọa độ tâm cx, cy, bán kính radius và cuối cùng là paint để vẽ:

drawCircle(float cx, float cy, float radius, @NonNull Paint paint)

Ví dụ vẽ hình tròn có bán kính là 50 ở góc trái trên:

// Draw Circle
float radius = 50.0f;
float cx = radius;
float cy = radius;
canvas.drawCircle(cx, cy, radius, mPaint);

DrawOval

Vẽ hình oval có các yếu tố là left, top, right, bottom, sử dụng paint để vẽ:

drawOval(float left, float top, float right, float bottom, @NonNull Paint paint)

Vẽ hình oval trong giới hạn của cấu trúc rect là số thực, sử dụng paint để vẽ;

drawOval(@NonNull RectF rect, @NonNull Paint paint)

* Phương thức này chỉ gọi được trên Android API 21

Ví dụ vẽ hình oval chính giữa màn hình:

// Draw Oval
float width = 300;
float height = 100;
float left = (getWidth() - width) / 2.0f;
float top = (getHeight() - height) / 2.0f;
canvas.drawOval(new RectF(left, top, left + width, top + height), mPaint);

DrawArc

Đây là hình học cuối cùng có các phương thức đễ vẽ cung tròn Arc lên Canvas.

Vẽ cung tròn với hình chữ nhật bao quanh rect, góc bắt đầu vẽ startAngle, cung vẽ sweepAngle, sử dụng tâm vẽ useCenterpaint để có thể vẽ lên Canvas:

drawArc(@NonNull RectF rect, float startAngle, float sweepAngle, boolean useCenter, @NonNull Paint paint)

Vẽ cung tròn với các đối số left, top, right, bottom đại diện cho hình chữ nhật bao quanh, góc bắt đầu vẽ startAngle, cung vẽ sweepAngle, sử dụng tâm vẽ useCenterpaint để có thể vẽ lên Canvas:

drawArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean useCenter, @NonNull Paint paint)

Ví dụ vẽ cung tròn ở giữa màn hình thiết bị với các thông số là góc bắt đầu vẽ có giá trị 45 và chiều dài cung vẽ là 270:

// Draw Arc
float width = 400;
float height = 400;
float left = (getWidth() - width) / 2.0f;
float top = (getHeight() - height) / 2.0f;
canvas.drawArc(new RectF(left, top, left + width, top + height),45, 270, false, mPaint);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeCap(Paint.Cap.ROUND);

Có 2 đầu mút được bo tròn là tác dụng của Paint.Cap.Round.

Hình ảnh cuối bài viết này là tiếp tục chỉnh lại phương thức drawArc() đổi false thành true và xem kết quả.

// Draw Arc
float width = 400;
float height = 400;
float left = (getWidth() - width) / 2.0f;
float top = (getHeight() - height) / 2.0f;
canvas.drawArc(new RectF(left, top, left + width, top + height),45, 270, true, mPaint);

Bài chung series

IO Stream

IO Stream Co., Ltd

30 Trinh Dinh Thao, Hoa Thanh ward, Tan Phu district, Ho Chi Minh city, Vietnam
+84 28 22 00 11 12
developer@iostream.co

383/1 Quang Trung, ward 10, Go Vap district, Ho Chi Minh city
Business license number: 0311563559 issued by the Department of Planning and Investment of Ho Chi Minh City on February 23, 2012

©IO Stream, 2013 - 2024