Android实现画板包括涂鸦 改变颜色 橡皮擦 调节画笔粗细 撤销上一步 保存图片等功能的详细代码
时间: 2024-02-23 20:58:43 浏览: 47
好的,下面是一个简单的 Android 画板示例代码,包括涂鸦、改变颜色、橡皮擦、调节画笔粗细、撤销上一步和保存图片等功能:
MainActivity.java:
```java
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private static final int REQUEST_PERMISSION_CODE = 1001;
private static final int MAX_STEP = 10;
private static final int DEFAULT_COLOR = Color.BLACK;
private static final int DEFAULT_SIZE = 5;
private SurfaceView mSurfaceView;
private Button mColorButton;
private Button mEraserButton;
private SeekBar mSizeSeekBar;
private Button mUndoButton;
private Button mSaveButton;
private Paint mPaint;
private int mColor = DEFAULT_COLOR;
private int mSize = DEFAULT_SIZE;
private Bitmap mBitmap;
private Canvas mCanvas;
private Stack<Bitmap> mBitmapStack;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSurfaceView = findViewById(R.id.surface_view);
mColorButton = findViewById(R.id.color_button);
mEraserButton = findViewById(R.id.eraser_button);
mSizeSeekBar = findViewById(R.id.size_seek_bar);
mUndoButton = findViewById(R.id.undo_button);
mSaveButton = findViewById(R.id.save_button);
mColorButton.setOnClickListener(this);
mEraserButton.setOnClickListener(this);
mUndoButton.setOnClickListener(this);
mSaveButton.setOnClickListener(this);
mSizeSeekBar.setMax(100);
mSizeSeekBar.setProgress(DEFAULT_SIZE);
mSizeSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
mSize = progress;
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
mPaint = new Paint();
mPaint.setColor(mColor);
mPaint.setStrokeWidth(mSize);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mBitmap = Bitmap.createBitmap(mSurfaceView.getWidth(), mSurfaceView.getHeight(), Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
mBitmapStack = new Stack<>();
mSurfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) {
mCanvas.drawColor(Color.WHITE);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
mCanvas.setBitmap(mBitmap);
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
mBitmap.recycle();
}
});
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.color_button:
showColorPickerDialog();
break;
case R.id.eraser_button:
mColor = Color.WHITE;
mPaint.setColor(mColor);
break;
case R.id.undo_button:
undo();
break;
case R.id.save_button:
saveImage();
break;
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
mBitmapStack.push(Bitmap.createBitmap(mBitmap));
}
if (event.getAction() == MotionEvent.ACTION_MOVE || event.getAction() == MotionEvent.ACTION_DOWN) {
float x = event.getX();
float y = event.getY();
mCanvas.drawPoint(x, y, mPaint);
mSurfaceView.getHolder().unlockCanvasAndPost(mCanvas);
}
if (mBitmapStack.size() > MAX_STEP) {
mBitmapStack.remove(0);
}
return true;
}
private void showColorPickerDialog() {
ColorPickerDialogBuilder
.with(this)
.setTitle("Color Picker")
.initialColor(mColor)
.wheelType(ColorPickerView.WHEEL_TYPE.FLOWER)
.density(12)
.setPositiveButton("OK", new ColorPickerClickListener() {
@Override
public void onClick(DialogInterface dialog, int selectedColor, Integer[] allColors) {
mColor = selectedColor;
mPaint.setColor(mColor);
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
})
.build()
.show();
}
private void undo() {
if (!mBitmapStack.isEmpty()) {
mBitmap = mBitmapStack.pop();
mCanvas.setBitmap(mBitmap);
mSurfaceView.getHolder().unlockCanvasAndPost(mCanvas);
}
}
private void saveImage() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_PERMISSION_CODE);
return;
}
}
String fileName = "Drawing_" + System.currentTimeMillis() + ".png";
File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), fileName);
try {
FileOutputStream fos = new FileOutputStream(file);
mBitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
fos.flush();
fos.close();
Toast.makeText(this, "Image saved to " + file.getAbsolutePath(), Toast.LENGTH_SHORT).show();
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(this, "Failed to save image", Toast.LENGTH_SHORT).show();
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
switch (requestCode) {
case REQUEST_PERMISSION_CODE:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
saveImage();
} else {
Toast.makeText(this, "Permission denied", Toast.LENGTH_SHORT).show();
}
break;
}
}
}
```
activity_main.xml:
```xml
<RelativeLayout 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">
<SurfaceView
android:id="@+id/surface_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<LinearLayout
android:id="@+id/tool_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:orientation="horizontal"
android:padding="16dp">
<Button
android:id="@+id/color_button"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginEnd="16dp"
android:backgroundTint="@color/black"
android:textColor="@color/white"
android:text="C" />
<Button
android:id="@+id/eraser_button"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginEnd="16dp"
android:backgroundTint="@color/white"
android:textColor="@color/black"
android:text="E" />
<SeekBar
android:id="@+id/size_seek_bar"
android:layout_width="0dp"
android:layout_height="48dp"
android:layout_marginEnd="16dp"
android:layout_weight="1" />
<Button
android:id="@+id/undo_button"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginEnd="16dp"
android:backgroundTint="@color/black"
android:textColor="@color/white"
android:text="U" />
<Button
android:id="@+id/save_button"
android:layout_width="48dp"
android:layout_height="48dp"
android:backgroundTint="@color/black"
android:textColor="@color/white"
android:text="S" />
</LinearLayout>
</RelativeLayout>
```
这个示例代码中包含了涂鸦、改变颜色、橡皮擦、调节画笔粗细、撤销上一步和保存图片等功能,你可以根据自己的需求进行修改和扩展。
相关推荐
![pdf](https://img-home.csdnimg.cn/images/20210720083512.png)
![rar](https://img-home.csdnimg.cn/images/20210720083606.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)