You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android绘图画布添加悬浮保存按钮实现方案咨询

How to Add a Save Floating Action Button to Your Canvas Drawing Activity

Hey there! Adding a floating action button (FAB) for saving your drawing is totally doable—let's break down two straightforward approaches to make this work, along with the save functionality.

Right now you're setting the MyDrawView directly as the content view, which doesn't leave room for other UI elements like a FAB. Instead, create a root layout that holds both your drawing view and the FAB.

Step 1: Create an XML Layout File

Make a new layout file named activity_draw_image.xml (res/layout/activity_draw_image.xml) with a ConstraintLayout as the root:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- Your custom drawing view, takes full screen -->
    <com.yourpackage.MyDrawView
        android:id="@+id/draw_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <!-- Save FAB, positioned at bottom-right -->
    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/save_fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="16dp"
        android:src="@drawable/ic_save" <!-- Use a save icon from your drawables -->
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

Note: Replace com.yourpackage with your actual app package name, and add a save icon to your drawable resources (you can use Android Studio's vector asset generator for this).

Step 2: Update Your DrawImage Activity

Modify your DrawImage class to inflate this layout instead of setting the view directly:

public class DrawImage extends FragmentActivity {
    private MyDrawView mDrawView;

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

        // Get reference to your drawing view
        mDrawView = findViewById(R.id.draw_view);

        // Set up the save FAB
        FloatingActionButton saveFab = findViewById(R.id.save_fab);
        saveFab.setOnClickListener(v -> saveDrawing());
    }

    private void saveDrawing() {
        // Call the save method from your MyDrawView
        boolean saved = mDrawView.saveBitmapToGallery(this);
        if (saved) {
            Toast.makeText(this, "Drawing saved!", Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(this, "Failed to save drawing", Toast.LENGTH_SHORT).show();
        }
    }
}

Step 3: Add Save Functionality to MyDrawView

Add a method to MyDrawView that handles saving the bitmap to the device's gallery:

public boolean saveBitmapToGallery(Context context) {
    if (mBitmap == null) return false;

    String fileName = "MyDrawing_" + System.currentTimeMillis() + ".png";
    OutputStream outputStream = null;

    // For Android 10+ (API 29+), use MediaStore
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
        ContentValues values = new ContentValues();
        values.put(MediaStore.Images.Media.DISPLAY_NAME, fileName);
        values.put(MediaStore.Images.Media.MIME_TYPE, "image/png");
        values.put(MediaStore.Images.Media.RELATIVE_PATH, Environment.DIRECTORY_PICTURES + "/MyDrawings");

        Uri uri = context.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
        if (uri != null) {
            try {
                outputStream = context.getContentResolver().openOutputStream(uri);
                mBitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
                return true;
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (outputStream != null) outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    } else {
        // For older Android versions, use external storage (requires WRITE_EXTERNAL_STORAGE permission)
        String directoryPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) + "/MyDrawings";
        File directory = new File(directoryPath);
        if (!directory.exists()) directory.mkdirs();

        File file = new File(directory, fileName);
        try {
            outputStream = new FileOutputStream(file);
            mBitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
            // Notify gallery of new image
            MediaScannerConnection.scanFile(context, new String[]{file.getAbsolutePath()}, null, null);
            return true;
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (outputStream != null) outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    return false;
}

Step 4: Handle Permissions (For Android < 10)

If you're supporting Android versions below 10, add the WRITE_EXTERNAL_STORAGE permission to your AndroidManifest.xml:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28" />

And request the permission dynamically in your DrawImage activity before saving (you can add a check in the saveDrawing() method).


Approach 2: Create Layout Programmatically (No XML)

If you prefer to avoid XML, you can build the root layout and FAB entirely in code:

public class DrawImage extends FragmentActivity {
    private MyDrawView mDrawView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Create root RelativeLayout
        RelativeLayout rootLayout = new RelativeLayout(this);
        rootLayout.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));

        // Add your drawing view
        mDrawView = new MyDrawView(this);
        RelativeLayout.LayoutParams drawViewParams = new RelativeLayout.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
        rootLayout.addView(mDrawView, drawViewParams);

        // Create and add the FAB
        FloatingActionButton saveFab = new FloatingActionButton(this);
        RelativeLayout.LayoutParams fabParams = new RelativeLayout.LayoutParams(
                ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        fabParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
        fabParams.addRule(RelativeLayout.ALIGN_PARENT_END);
        fabParams.setMargins(0, 0, 16, 16); // Margin in dp (convert to pixels if needed)
        saveFab.setImageResource(R.drawable.ic_save);
        saveFab.setOnClickListener(v -> saveDrawing());
        rootLayout.addView(saveFab, fabParams);

        setContentView(rootLayout);
    }

    // saveDrawing() method same as Approach 1
    private void saveDrawing() {
        boolean saved = mDrawView.saveBitmapToGallery(this);
        Toast.makeText(this, saved ? "Drawing saved!" : "Save failed", Toast.LENGTH_SHORT).show();
    }
}

Key Notes:

  • Make sure you've added the Material Components dependency to your build.gradle (Module level) if using FloatingActionButton:
    implementation 'com.google.android.material:material:1.9.0' // Use latest version
    
  • Test the save functionality on both older and newer Android versions to ensure compatibility.
  • You can also add a clear button (using another FAB or a menu item) by calling the existing clear() method in MyDrawView.

内容的提问来源于stack exchange,提问作者lessthanmediocre

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:38:31