Post by Admin on May 21, 2017 12:02:49 GMT 7
Custom View, Canvas, Paint
Nếu như bạn nghĩ rằng việc sử dụng những view có sẵn không mấy gì màu mè, đẹp đẽ, bạn có ý nghĩ sử dụng đến một thứ mà nơi đó bạn có thể tạo hình tất cả những đối tượng bạn muốn, một khung nhập hình lượn sóng, một nhãn tên nhiều màu, một danh sách bằng những bậc thang…. Thì bạn nên dùng một class mở rộng từ class View, và rồi trong hàm .onDraw(Canvas) của nó, bạn có thể vẽ vời bất cứ thứ gì lên Canvas đó. Dưới đây là 1 ví dụ:
Với những gì bạn, thấy trong ví dụ đó, khi bạn chạy thử chương trình, bạn sẽ thấy được ý nghĩa của nó như thế nào.
Còn có nhiều lệnh vẽ trên Canvas nữa, hãy tìm hiểu thêm.
Điều nên chú ý là lệnh .invalidate(); nó dùng để lặp lại hàm onDraw(Canvas) và vì vậy, khi bạn đặt nó vào trong onDraw thì nó sẽ khiến cho vòng lặp onDraw được vẽ lại mãi. Trong một trường hợp chuyên nghiệp hơn, bạn nên dùng 1 Thread bên ngoài để lặp lại vòng lặp này, ngoài ra người ta cũng khuyên nên dùng 1 SurfaceView thay cho 1 View đơn giản như trên, hoặc bạn có thể nghĩ đến việc dùng DrawingCache để tăng tốc việc xử lý hình ảnh trước khi đưa ra ngoài.
Nếu như bạn nghĩ rằng việc sử dụng những view có sẵn không mấy gì màu mè, đẹp đẽ, bạn có ý nghĩ sử dụng đến một thứ mà nơi đó bạn có thể tạo hình tất cả những đối tượng bạn muốn, một khung nhập hình lượn sóng, một nhãn tên nhiều màu, một danh sách bằng những bậc thang…. Thì bạn nên dùng một class mở rộng từ class View, và rồi trong hàm .onDraw(Canvas) của nó, bạn có thể vẽ vời bất cứ thứ gì lên Canvas đó. Dưới đây là 1 ví dụ:
package com.holyeyed.ctrcanvas;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
public class MainActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//khởi tạo và cho hiện thị mCanvas
setContentView(new mCanvas(this));
}
}
class mCanvas extends View {
// Biến tổng liển kết với MainActivity
MainActivity main;
// biến Paint dùng để định kiểu vẽ như nét, màu,..
Paint p;
// một dòng chữ để vẽ ra
String text = "here me";
// một đối tượng để vẽ
Bitmap bm;
// biến lưu kích cỡ màn hình
int w, h;
// biến lưu vị trí đối tượng vẽ text và hình ảnh
int tx, ty,bx,by;
// hàm khởi tạo, View luôn cần 1 Context để khởi tạo, ta truyền cho nó thông
// qua MainActivity
public mCanvas(MainActivity main) {
super(main);
// truyền tham số vào biến tổng MainActivity
this.main = main;
//thiết đặt màu, nét vẽ cho paint, ta nên làm trước, không nên làm trong vòng lặp onDraw
p=new Paint();
p.setColor(0xff00ff00);
p.setTextSize(24);
//khởi tạo bitmap, không nên khởi tạo trong vòng onDraw
try{
bm=BitmapFactory.decodeStream(main.getAssets().open("eye.png"));
}catch(Exception e){}
}
// hàm onDraw(Canvas) dùng để vẽ ra ngoài cho View này
public void onDraw(Canvas cv) {
//chúng ta chỉ có thể lấy kích thước màn hình qua canvas này
//chúng ta xét khi mà w bằng 0 thì chúng ta lấy giá trị, không lặp lại nữa
if(w==0){
w=cv.getWidth();
h=cv.getHeight();
//đặt vị trí vẽ text ban đầu
tx=0;
ty=h/2;
}
//tô màu nền cho canvas
cv.drawRGB(0, 0, 0);
//vẽ text ra màn hình
cv.drawText(text, tx, ty, p);
//vẽ bitmap ra màn hình
cv.drawBitmap(bm, bx, by, p);
//tự động cập nhật vị trí cho text
tx+=3;
if(tx>w)tx=0;
//và cho lặp lại vòng onDraw();
this.invalidate();
}
// hàm nhận sự kiện, mặc định đã ở đây
public boolean onTouchEvent(MotionEvent me) {
int action=me.getAction();
//nếu là sự kiện nhấn xuống thì cập nhật vị trí vẽ ngay tại điểm nhấn
if(action==MotionEvent.ACTION_DOWN){
bx=(int)me.getX();
by=(int)me.getY();
}
return false;
}
}
Với những gì bạn, thấy trong ví dụ đó, khi bạn chạy thử chương trình, bạn sẽ thấy được ý nghĩa của nó như thế nào.
Còn có nhiều lệnh vẽ trên Canvas nữa, hãy tìm hiểu thêm.
Điều nên chú ý là lệnh .invalidate(); nó dùng để lặp lại hàm onDraw(Canvas) và vì vậy, khi bạn đặt nó vào trong onDraw thì nó sẽ khiến cho vòng lặp onDraw được vẽ lại mãi. Trong một trường hợp chuyên nghiệp hơn, bạn nên dùng 1 Thread bên ngoài để lặp lại vòng lặp này, ngoài ra người ta cũng khuyên nên dùng 1 SurfaceView thay cho 1 View đơn giản như trên, hoặc bạn có thể nghĩ đến việc dùng DrawingCache để tăng tốc việc xử lý hình ảnh trước khi đưa ra ngoài.