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

Cách cắt vùng tròn từ Bitmap trong Android

Hướng dẫn này minh họa cách tạo hình ảnh tròn (circular bitmap) từ bitmap gốc, kèm viền và bóng đổ, sử dụng Canvas, Paint và PorterDuffXfermode.

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

Mở Android Studio, chọn File → New Project.

Bước 2: Giao diện (res/layout/activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:app="https://schemas.android.com/apk/res-auto"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/rl"
    android:padding="16dp"
    android:background="#edf2ea"
    tools:context=".MainActivity">

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

    <Button
        android:id="@+id/btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:text="Tạo hình tròn"/>

</RelativeLayout>

Bước 3: Logic xử lý Bitmap (src/MainActivity.java)

package com.medkart.sample;

import androidx.appcompat.app.AppCompatActivity;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
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 {
    private Context mContext;
    private Resources mResources;
    private RelativeLayout mRelativeLayout;
    private Button mBtn;
    private ImageView mImageView;
    private Bitmap mBitmap;

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

        mContext = getApplicationContext();
        mResources = getResources();
        mRelativeLayout = findViewById(R.id.rl);
        mImageView = findViewById(R.id.iv);
        mBtn = findViewById(R.id.btn);

        final int bitmapResId = R.drawable.flower;
        mImageView.setImageBitmap(BitmapFactory.decodeResource(mResources, bitmapResId));

        mBtn.setOnClickListener(v -> {
            mBitmap = BitmapFactory.decodeResource(mResources, bitmapResId);
            mBitmap = getCircularBitmap(mBitmap);
            mBitmap = addBorderToCircularBitmap(mBitmap, 15, Color.WHITE);
            mBitmap = addShadowToCircularBitmap(mBitmap, 4, Color.LTGRAY);
            mImageView.setImageBitmap(mBitmap);
        });
    }

    // 1. Tạo bitmap tròn
    private Bitmap getCircularBitmap(Bitmap src) {
        int size = Math.min(src.getWidth(), src.getHeight());
        Bitmap dst = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(dst);
        Paint paint = new Paint();
        paint.setAntiAlias(true);

        RectF rectF = new RectF(0, 0, size, size);
        canvas.drawOval(rectF, paint);

        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        float left = (size - src.getWidth()) / 2f;
        float top = (size - src.getHeight()) / 2f;
        canvas.drawBitmap(src, left, top, paint);

        src.recycle();
        return dst;
    }

    // 2. Thêm viền
    private Bitmap addBorderToCircularBitmap(Bitmap src, int borderWidth, int borderColor) {
        int dstSize = src.getWidth() + borderWidth * 2;
        Bitmap dst = Bitmap.createBitmap(dstSize, dstSize, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(dst);
        canvas.drawBitmap(src, borderWidth, borderWidth, null);

        Paint paint = new Paint();
        paint.setColor(borderColor);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(borderWidth);
        paint.setAntiAlias(true);

        float radius = dstSize / 2f - borderWidth / 2f;
        canvas.drawCircle(dstSize / 2f, dstSize / 2f, radius, paint);

        src.recycle();
        return dst;
    }

    // 3. Thêm bóng đổ
    private Bitmap addShadowToCircularBitmap(Bitmap src, int shadowWidth, int shadowColor) {
        int dstSize = src.getWidth() + shadowWidth * 2;
        Bitmap dst = Bitmap.createBitmap(dstSize, dstSize, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(dst);
        canvas.drawBitmap(src, shadowWidth, shadowWidth, null);

        Paint paint = new Paint();
        paint.setColor(shadowColor);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(shadowWidth);
        paint.setAntiAlias(true);

        canvas.drawCircle(dstSize / 2f, dstSize / 2f, dstSize / 2f - shadowWidth / 2f, paint);

        src.recycle();
        return dst;
    }
}

Bước 4: Manifest (AndroidManifest.xml)

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android" package="com.medkart.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>

💡 Giải pháp hiện đại: RoundedImageView / Coil / Glide

Thay vì tự vẽ, hãy dùng thư viện:

  • Glide: Glide.with(this).load(url).circleCrop().into(imageView)
  • Coil (Kotlin): imageView.load(url) { transformations(CircleCropTransformation()) }
  • ShapeableImageView (Material Components): XML set app:shapeAppearanceOverlay

Chạy ứng dụng

Kết nối thiết bị, nhấn Run. Nhấn nút để thấy hình ảnh gốc biến thành hình tròn có viền và bóng.