Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Android

Cách vẽ đường thẳng (Line) trong Android với Canvas

Hướng dẫn này trình bày cách vẽ một đường thẳng đơn giản lên Bitmap bằng Canvas và Paint, sau đó hiển thị lên ImageView. Đây là kỹ thuật cơ bản của custom drawing trong Android.

Các bước thực hiện

Bước 1: Tạo dự án mới

Mở Android Studio, chọn File → New Project và điền thông tin cần thiết.

Bước 2: Layout (res/layout/activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/relativeLayout"
    tools:context=".MainActivity">

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true" />

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Vẽ đường"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="70dp" />

</RelativeLayout>

Bước 3: Code MainActivity (src/MainActivity.java)

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.RelativeLayout;

public class MainActivity extends AppCompatActivity {
    RelativeLayout relativeLayout;
    Button button;
    ImageView imageView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        relativeLayout = findViewById(R.id.relativeLayout);
        button = findViewById(R.id.button);
        imageView = findViewById(R.id.imageView);

        button.setOnClickListener(v -> {
            // 1. Tạo Bitmap mutable (có thể vẽ lên)
            // Width=10px là rất nhỏ - trong thực tế nên dùng kích thước View thực tế
            Bitmap bitmap = Bitmap.createBitmap(400, 400, Bitmap.Config.ARGB_8888);

            // 2. Tạo Canvas gắn với Bitmap
            Canvas canvas = new Canvas(bitmap);

            // 3. Tùy chọn: fill background (mặc định trong suốt)
            canvas.drawColor(Color.WHITE); // Nền trắng

            // 4. Cấu hình Paint (bút vẽ)
            Paint paint = new Paint();
            paint.setColor(Color.RED);           // Màu đường
            paint.setStyle(Paint.Style.STROKE);  // Chỉ vẽ viền (STROKE), không fill
            paint.setStrokeWidth(8);             // Độ dày 8px
            paint.setAntiAlias(true);            // Chống răng cưa (mượt)

            // 5. Vẽ đường thẳng: drawLine(startX, startY, stopX, stopY, paint)
            int offset = 50; // Lề 50px từ mép
            canvas.drawLine(
                    offset,                          // startX
                    canvas.getHeight() / 2f,         // startY (giữa chiều cao)
                    canvas.getWidth() - offset,      // stopX
                    canvas.getHeight() / 2f,         // stopY (giữa chiều cao)
                    paint
            );

            // 6. Hiển thị bitmap lên ImageView
            imageView.setImageBitmap(bitmap);
        });
    }
}

Bước 4: Cấu hình AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
    package="app.com.sample">
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

Chạy ứng dụng

Kết nối thiết bị, nhấn Run. Nhấn nút "Vẽ đường" - một đường ngang đỏ xuất hiện giữa ImageView.

Cách vẽ đường thẳng (Line) trong Android với Canvas

Giải thích thành phần chính

1. Bitmap - "Cái vải" vẽ

  • Bitmap.createBitmap(width, height, Config.ARGB_8888): Tạo bitmap mutable (có thể chỉnh sửa)
  • Config.ARGB_8888: 32-bit, 4 kênh (Alpha, Red, Green, Blue) - chất lượng cao
  • Kích thước nên dựa trên view.getWidth(), view.getHeight() hoặc DisplayMetrics

2. Canvas - "Bàn tay" vẽ

  • new Canvas(bitmap): Mọi lệnh vẽ trên Canvas sẽ ghi vào Bitmap
  • Cung cấp các phương thức: drawLine, drawRect, drawCircle, drawPath, drawText, drawBitmap...

3. Paint - "Bút vẽ" (Style & Color)

Phương thức Mô tả
setColor(int) Màu vẽ (ARGB)
setStyle(Style) FILL (tô đầy), STROKE (viền), FILL_AND_STROKE
setStrokeWidth(float) Độ dày nét (pixel)
setAntiAlias(boolean) Bật/tắt chống răng cưa (mượt)
setStrokeCap(Cap) Đầu nét: BUTT, ROUND, SQUARE
setStrokeJoin(Join) Góc nối: MITER, ROUND, BEVEL
setPathEffect(PathEffect) Hiệu ứng: nét đứt (DashPathEffect), cong...
setShader(Shader) Gradient, texture, bitmap pattern

Cách đúng: Custom View (Kế thừa View)

Vẽ trong onClick của Activity không phải pattern tốt. Cách chuẩn: tạo class kế thừa View và override onDraw(Canvas).

public class LineView extends View {
    private Paint paint;

    public LineView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        paint = new Paint();
        paint.setColor(Color.RED);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(8f);
        paint.setAntiAlias(true);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int offset = 50;
        float centerY = getHeight() / 2f;
        canvas.drawLine(offset, centerY, getWidth() - offset, centerY, paint);
    }
}

XML: <com.example.LineView android:layout_width="match_parent" android:layout_height="200dp" />

Mở rộng: Vẽ đường nét đứt (Dashed Line)

PathEffect dashEffect = new DashPathEffect(new float[] {20, 10}, 0); // 20px vẽ, 10px bỏ
paint.setPathEffect(dashEffect);

Mở rộng: Vẽ đường cong (Path)

Path path = new Path();
path.moveTo(50, 300);
path.quadTo(200, 50, 350, 300); // Đường cong bậc 2
canvas.drawPath(path, paint);

Tóm tắt

  • Bitmap + Canvas + Paint = bộ ba cốt lõi custom drawing
  • Luôn tạo Paint một lần (trong constructor/init), không tạo trong onDraw
  • Dùng Custom View (kế thừa View) cho vẽ lặp lại/hiệu năng
  • ImageView chỉ để hiển thị Bitmap tĩnh, không phải container vẽ