Như đã đề cập ở trên, để có thể vẽ lên được màn hình ta cần xây dựng một lớp con của lớp View. Lớp này sẽ chứa đựng các đối tượng thuộc lớp Bitmap, Canvas, Path và Paint. Đồng thời trong lớp này cần phải ghi đè lại các phương thức onDraw(Canvas canvas) và onTouchEvent(MotionEvent event). Lớp này sẽ giữ vai trò chính cho việc vẽ, tô màu. Khi ta vẽ lên màn hình, lúc đó tay ta sẽ di chuyển trên màn hình vì thế các hành động vẽ sẽ được định nghĩa trong phương thức touch_move(float x, float y). Để biết được ta đang chọn nét vẽ nào thì ta cần khai báo một biến kiểu int , biến này sẽ được gán những giá trị khác nhau ứng với mỗi nét vẽ, và hành dạng muốn vẽ . Lúc đó,trong lớp MyView ta cũng cần định nghĩa thêm một phương thức để gán giá trị cho biến này :
public class MyView extends View {
int choose_number = 1;//chọn nét vẽ, hình dạng vẽ
public void setChooseNumber(int n) { choose_number = n;
}
private void touch_move(float x, float y) { float dx = Math.abs(x - mX);
float dy = Math.abs(y - mY); switch (choose_number) {
case 1:
//nét vẽ bình thường
paint.setMaskFilter(null); // hủy nét nổi và mờ
paint.setPathEffect(null);// hủy thiết lập nét vẽ đứt đoạn
paint.clearShadowLayer();// hủy thiết lập bóng đỗ
if (dx >= 4 || dy >= 4) {
path.quadTo(mX, mY, x, y); mX = x; mY = y; } break; case 2: //nét vẻ nổi paint.setPathEffect(null); paint.clearShadowLayer();
emboss = new EmbossMaskFilter(new float[] { 1, 1, 1 },0.4f, 6, 3.5f);
paint.setMaskFilter(emboss);//thiết lập nét vẽ nổi
if (dx >= 4 || dy >= 4) {
path.quadTo(mX, mY, (x + mX)/2, (y + mY)/2); mX = x; mY = y; } break; // . . . } //... }
Các nét còn lại ta làm tương tự như trên , chỉ khác nhau ở chỗ :
Nét mờ : paint.setMaskFilter(new
BlurMaskFilter(10,Blur.INNER));
Nét đứt đoạn :
PathEffect ef =new DashPathEffect(new float[] {20,10,5,10},0);
paint.setPathEffect(ef);
Nét sáp 1 :
MyFill f = new MyFill();
f.fillCircle_gradient(bitmap, new
Point((int)x,(int)y), (int)(5+
paint.getStrokeWidth()), paint.getColor());
Nét sáp 2 :
MyFill f = new MyFill();
f.fillCircle(bitmap, new Point((int)x,(int)y), (int)(5+ paint.getStrokeWidth()), paint.getColor()); Đối với việc lựa chọn hình dạng để vẽ , ta cũng làm tương tự như trên :
//...
case number: {
path.reset();//xóa các hình dạng trước đó // phương thức vẽ hình chữ nhật,
path.addRect(mX, mY, x, y,Path.Direction.CW);
break; }
//...
Đối với một ứng dụng Android, bao giờ ta cũng có một lớp MainActivity( tên này có thể thay đổi do người lập trình đặt), đối với ứng dụng của ta lớp này có tên là BabyPaintActivity, lớp này là lớp chính của ứng dụng, mọi chức năng điều được thực hiện thông qua lớp này. Ta cần tạo một đối tượng thuộc lớp MyView đã được xây dựng, việc vẽ,tô màu sẽ thực thông qua đối tượng này, để thể hiện đối tượng này lên màn hình (thể hiện lên FrameLayout đã được thiết kế trong phần giao diện) ta cần thêm đối tượng này vào đối tượng thuộc lớp FrameLayout liên kết với FrameLayout đã khai báo trong tập tin XML:
Trong tập tin XML định nghĩa giao diện : // … <FrameLayout android:id="@+id/display" android:layout_width="match_parent" android:layout_height="match_parent" > </FrameLayout> // … Trong lớp BabyPaintActivity : @Override
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);//không hiển thị tiêu đề
mview = new MyView(this);
display = (FrameLayout)findViewById(R.id.display); display.addView(mview);
// … }
Trong ứng dụng, để thực hiện việc chọn nét vẽ, hình dạng hình cần vẽ ta sẽ nhấn vào một nút tương ứng với chức năng này. Khi nhấn vào nút này, một dialog sẽ xuất hiện, trên đó sẽ có những nút tương ứng với nét vẽ, hình dạng ta cần chọn. Dialog này được thiết kế trong một lớp riêng, trong lớp này có một phương thức với một tham số kiểu MyView. Thông qua tham số này, ta sẽ xác định được được nét vẽ hoặc hình dạng muốn vẽ thông qua tham số setChooseNumber(int n)như đã thiết kế ở phần trên.
public class ShapeDialog { // …
public void ChooseShape(final MyView mv) {
final Dialog da = new Dialog(context); da.setContentView(R.layout.shape_dialog); da.setTitle("Choose shape");
// …
OnClickListener listener = new OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
switch(v.getId()){
case R.id.bt_pencil:{
mv.setChooseNumber(1); da.dismiss();
break; }
case R.id.bt_tron:{
mv.setChooseNumber(2); da.dismiss(); break; } //… } // … }
Để hiển thị được dialog này, trong lớp BabyPaintActivity ta cần thiết kế một phương thức cho sự kiện onClick() của nút tương ứng với chức năng chọn nét vẽ, hình dạng cần vẽ :
public void ChooseShape(View v) {
da_shape.ChooseShape(mview); }
Khi đó trong tập tin XML định nghĩa giao diện, tại nút (ImageButton ) tương ứng chức năng này ta thêm thuộc tính android:onClick="ChooseShape"
// ... <ImageButton android:id="@+id/bt_choose_shape" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/icon_pen" android:onClick="ChooseShape"/> // …
Kết quả sau khi ứng dụng hoàn thành :
Hình 11: Dialog chọn nét vẽ