首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Android Canvas 繪圖儲存後全黑:缺少背景填充與繪製順序錯誤

     編輯:程式設計綜合問答

問題現象

使用 Canvas 繪製圖形/文字後儲存為 Bitmap/檔案,結果圖片全黑或背景透明但內容不見。

常見原因

  1. 未填充背景色:Bitmap.createBitmap() 預設像素為 0(透明黑),若不先 canvas.drawColor(Color.WHITE),背景即為透明/黑。
  2. 繪製順序錯誤:先畫內容再填背景,會蓋掉內容。
  3. Paint 未設定顏色/抗鋸齒:paint.setColor() 遺漏,導致繪製無色。
  4. 儲存格式不支援透明:JPEG 不支援透明通道,透明區會變黑;需用 PNG 或先填白底。

正確儲存流程

// 1. 建立可變更 Bitmap
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);

// 2. **優先** 填充背景(白色或所需顏色)
canvas.drawColor(Color.WHITE); // 或 canvas.drawRGB(255,255,255);

// 3. 設定 Paint
Paint paint = new Paint();
paint.setColor(Color.RED);           // 必須設色
paint.setAntiAlias(true);            // 抗鋸齒
paint.setTextSize(48);               // 文字大小
paint.setStyle(Paint.Style.STROKE);  // 或 FILL

// 4. 繪製內容
canvas.drawRect(100, 100, 500, 500, paint);
canvas.drawText("Hello", 120, 200, paint);

// 5. 儲存檔案
FileOutputStream fos = new FileOutputStream(new File(path));
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos); // PNG 保留透明/品質
fos.flush(); fos.close();

關鍵修正點

  • 第 2 步驟 canvas.drawColor() 必須在繪製內容之前。
  • 若需透明背景,儲存為 PNG 且不呼叫 drawColor;若儲存為 JPEG,必須先填背景色。
  • Paint 物件建議複用(建立一次於 onDraw 外),避免頻繁 GC。

完整 Activity 範例

public class DrawSaveActivity extends AppCompatActivity {
    @Override protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_draw_save);
        findViewById(R.id.btnSave).setOnClickListener(v -> saveDrawing());
    }

    private void saveDrawing() {
        int w = 800, h = 600;
        Bitmap bmp = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        Canvas cv = new Canvas(bmp);
        cv.drawColor(Color.WHITE); // 關鍵!

        Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
        p.setColor(Color.BLUE);
        p.setTextSize(60);
        cv.drawText("Android Canvas", 100, 200, p);
        p.setColor(Color.RED);
        p.setStyle(Paint.Style.STROKE);
        p.setStrokeWidth(8);
        cv.drawCircle(400, 400, 150, p);

        File dir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
        File file = new File(dir, "drawing_" + System.currentTimeMillis() + ".png");
        try (FileOutputStream fos = new FileOutputStream(file)) {
            bmp.compress(Bitmap.CompressFormat.PNG, 100, fos);
            Toast.makeText(this, "已儲存:" + file.getAbsolutePath(), Toast.LENGTH_LONG).show();
        } catch (IOException e) {
            e.printStackTrace();
            Toast.makeText(this, "儲存失敗", Toast.LENGTH_SHORT).show();
        }
    }
}

進階:截取 View 內容(含背景)

// 取得任意 View 的繪圖快照(含背景、子 View)
public static Bitmap getViewBitmap(View view) {
    view.setDrawingCacheEnabled(true);
    view.buildDrawingCache(true);
    Bitmap bmp = Bitmap.createBitmap(view.getDrawingCache());
    view.setDrawingCacheEnabled(false);
    return bmp;
}
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved