Vẽ các đối tượng bitmap lên Canvas
Vẽ bitmap
Vẽ bitmap lên Canvas
có áp dụng ma trận:
drawBitmap(@NonNull Bitmap bitmap, @NonNull Matrix matrix, @Nullable Paint paint)
Vẽ bitmap lên Canvas
với các đối số:
drawBitmap(@NonNull Bitmap bitmap, @Nullable Rect src, @NonNull RectF dst, @Nullable Paint paint)
bitmap
: source bitmap dùng để vẽ lênCanvas
.src
: hình chữ nhật cắt bitmap để vẽ.- Ví dụ muốn bớt 1 phần của bitmap để vẽ thay vì vẽ toàn bộ hình ảnh.
- Trường hợp vẽ toàn hình ảnh sẽ truyền vào
null
.
dst
: hình chữ nhật mô tả tọa độ và khung hiển thị để vẽ lên Canvas.- Kiểu dữ liệu của các thuộc tính trong
dst
(left, top, right, bottom) là số thựcfloat
.
- Kiểu dữ liệu của các thuộc tính trong
Giống như phương thức trên nhưng kiểu dữ liệu của các thuộc tính dst
đều kiểu nguyên (left, top, right, bottom):
drawBitmap(@NonNull Bitmap bitmap, @Nullable Rect src, @NonNull Rect dst, @Nullable Paint paint)
Vẽ bitmap bắt đầu ở vị trí left
và top
xác định trên màn hình, điểm vẽ tính từ góc trái trên của bitmap:
drawBitmap(@NonNull Bitmap bitmap, float left, float top, @Nullable Paint paint)
Ví dụ vẽ bitmap lên Canvas
Chuẩn bị bitmap để vẽ:
mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.android);
Vẽ bitmap ở center-bottom màn hình
Trong phương thức onDraw()
hiện thực như sau:
float left = (getWidth() - mBitmap.getWidth()) / 2.0f;
float top = getHeight() - mBitmap.getHeight();
canvas.drawBitmap(mBitmap, left, top, mPaint);
Kết quả:
Vẽ 1/4 bitmap ở right-bottom tính từ tâm của bitmap
Trong phương thức onDraw()
hiện thực như sau:
Rect src = new Rect(0, 0, mBitmap.getWidth() / 2, mBitmap.getHeight() / 2);
int left = getWidth() - src.width();
int top = getHeight() - src.height();
Rect des = new Rect(left, top, left + src.width(), top + src.height());
canvas.drawBitmap(mBitmap, src, des, mPaint);
Vẽ bitmap tại vị trí center-middle màn hình
float left = (getWidth() - mBitmap.getWidth()) / 2.0f;
float top = (getHeight() - mBitmap.getHeight()) / 2.0f;
RectF dst = new RectF(left, top, left + mBitmap.getWidth(), top + mBitmap.getHeight());
canvas.drawBitmap(mBitmap, null, dst, mPaint);
Vẽ các đối tượng text lên Canvas
Vẽ text
Với bất kỳ ứng dụng nào trong Android cũng có văn bản hay những đoạn văn phức tạp. Android cung cấp lớp có tên là TextPaint
được kế thừa từ Paint
giúp vẽ text lên Canvas tốt hơn v àTextPaint
được khuyến khích sử dụng thay vì sử dụng Paint
.
Trong phương thức initPaint()
thêm vào phần khởi tạo TextPaint
sử dụng để vẽ text:
private void initPaint() {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.BLUE);
mPaint.setStrokeWidth(30);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
mTextPaint.setColor(Color.parseColor("#16a085"));
mTextPaint.setTextSize(50);
}
Vẽ text thông thường
Vẽ chuỗi ký tự với tọa độ bắt đầu vẽ x
, y
:
drawText(@NonNull String text, float x, float y, @NonNull Paint paint)
Vẽ chuỗi ký tự với start
, end
là vẽ từ ký tự bắt đầu tại vị trí start đến ký tự kết thúc ở vị trí end và x
, y
là tọa độ bắt đầu vẽ:
drawText(@NonNull String text, int start, int end, float x, float y, @NonNull Paint paint)
Vẽ 1 mảng char[]
, bắt đầu từ ký tự tại vị trí index
và số lượng phần tử cần vẽ count
, và vẽ ở tọa độ x
, y
.
drawText(@NonNull char[] text, int index, int count, float x, float y, @NonNull Paint paint)
Vẽ CharSequence
với start
, end
là vẽ từ ký tự bắt đầu tại vị trí start đến ký tự kết thúc ở vị trí end và x
, y
là tọa độ bắt đầu vẽ:
drawText(@NonNull CharSequence text, int start, int end, float x, float y, @NonNull Paint paint)
Ví dụ vẽ text lên Canvas
Ví dụ vẽ chuỗi "Eitguide Android"
ở vị trí x = 100, y = 400:
float x = 100;
float y = 400;
canvas.drawText("Eitguide Android", x, y, mTextPaint);
Sử dụng tiếp chuỗi "Eitguide Android"
nhưng chỉ vẽ “guide Androi"
:
float x = 100;
float y = 400;
String str = "Eitguide Android";
canvas.drawText(str, 3, str.length() - 1, x, y, mTextPaint);
Trường hợp chuỗi quá dài so với View
, ví dụ chuỗi "We can actually use any custom font that we'd like within our applications."
, chỉ hiển thị chuỗi "..."
khi chuỗi chạm mép của View
:
float x = 0;
float y = 400;
CharSequence str = TextUtils.ellipsize("We can actually use any custom font that we'd like within our applications.",
mTextPaint, getWidth(), TextUtils.TruncateAt.END);
canvas.drawText(str, 0, str.length(), x, y, mTextPaint);
Vẽ text với Spannable
Vẽ text đầy đủ các định dạng với Spannable
trong Android như sau:
- Đoạn chuỗi đầu tiên được in đậm.
- Đoạn chuỗi tiếp theo có màu nền đỏ.
- Đoạn chuỗi tiếp theo có chữ màu xanh.
- Đoạn chuỗi tiếp theo in nghiêng.
- Đoạn chuỗi cuối được gạch chân.
Với việc sử dụng Spannable để setSpan()
cho CharSequence
có thể đặt bất cứ kiểu nào cho chuỗi và sử dụng StaticLayout
để vẽ lên Canvas
:
float x = 0;
float y = 400;
CharSequence str = TextUtils.ellipsize("We can actually use any custom font that we'd like within our applications.", mTextPaint, getWidth(), TextUtils.TruncateAt.END);
SpannableString wordToSpan = new SpannableString(str);
wordToSpan.setSpan(new StyleSpan(Typeface.BOLD), 0, 10, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
wordToSpan.setSpan(new BackgroundColorSpan(Color.RED), 10, 15, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
wordToSpan.setSpan(new ForegroundColorSpan(Color.CYAN), 15, 20, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
wordToSpan.setSpan(new StyleSpan(Typeface.BOLD_ITALIC), 15, 25, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
wordToSpan.setSpan(new UnderlineSpan(), 25, wordToSpan.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
StaticLayout staticLayout = new StaticLayout(wordToSpan, mTextPaint, getWidth(), Layout.Alignment.ALIGN_NORMAL, 1, 0, false);
staticLayout.draw(canvas);
Các tính năng nâng cao của Canvas trong Android
Các phép biến đổi hình học
Canvas
có các phép biến đổi hình học như translate, scale, rotate để giúp vẽ các đối tượng 1 cách linh hoạt hơn.
Translate
Translate thực hiện tịnh tiến (dịch chuyển) gốc tọa độ Canvas
1 đoạn dx
và dy:
translate(float dx, float dy)
Mặc định gốc toạ độ nằm ở gốc trái-trên của View
, sau khi tịnh tiến 1 khoảng dx
, dy
thì gốc toạ độ sẽ nằm ở dx
và dy
.
Ví dụ khi chưa dịch chuyển và vẽ 1 điểm ở vị trí (x, y) = (200, 400)
sẽ có kết quả dx = 200, dy = 400 và sau đó vẽ 1 điểm tại vị trí (x, y) = (0, 0)
.
Scale
Scale là phép biến đổi tỷ lệ (thay đổi kích thước) của vật thể, nghĩa là thay đổi kích thước của các đối tượng vẽ trên Canvas
:
scale(float sx, float sy)
Mặc định tỷ lệ sx
, sy
có giá trị 1. Nếu đặt sx = 2
, sy = 4
thì đối tượng sẽ có kích thước theo chiều x
lớn hơn 2 lần và theo chiều y
lớn hơn 4 lần.
Rotate
Rotate là phép biển đổi xoay đối tượng theo 1 góc xác định:
void rotate(float degrees)
Ví dụ muốn xoay các đối tượng vẽ 45 độ:
canvas.rotate(45);
Save và Restore Canvas
Đặt trường hợp muốn vẽ 2 đối tượng:
- Vẽ đối tượng thứ 1 lớn hơn đối tượng đối tượng gốc của nó hơn 4 lần cả chiều x và chiều y.
- Vẽ đối tượng thứ 2 giống hình dạng của nó không có scale.
Các bước thực hiện như sau:
- Đặt
Canvas
với sx = 4, sy = 4:canvas.setScale(4, 4)
- Vẽ đối tượng thứ nhất.
- Về lại trạng thái ban đầu:
canvas.setScale(-4, -4)
- Vẽ đối tượng thứ hai.
Mỗi khi thay đổi trạng thái của Canvas
(translate, scale, rotate) muốn đưa về trạng thái cũ thì phải nhớ những thông số làm thay đổi trạng thái và đặt ngược lại giá trị đó để đưa Canvas về trạng thái cũ. Trường hợp tịnh tiến và phép quay thì sử dụng đổi dấu của các thông số, trường hợp phép tỷ lệ thì lấy nghịch đảo của thông số (1/scaleX, 1/scaleY).
Save Canvas
Trước khi thay đổi trạng thái của Canvas
gọi canvas.Save()
để lưu lại trạng thái hiện tại của Canvas. Khi đã lưu trạng thái thì có thể tự do sử dụng các phép biến đổi Canvas.
Restore Canvas
Gọi canvas.Restore()
để đưa Canvas về trạng thái được lưu trước đó.
canvas.Restore()
chỉ có thể gọi được nếu đã gọi canvas.Save()
, nếu vẫn gọi canvas.Restore()
mà chưa gọi canvas.Save()
ở trước thì Android sẽ ném ra ngoại lệ.