android 实现画板
时间: 2023-12-20 16:04:25 浏览: 66
要实现 Android 画板,可以按照以下步骤:
1. 创建一个新的 Android 项目,选择 Empty Activity。
2. 在 XML 布局文件中添加一个 SurfaceView,用于绘制图形。
3. 在代码中获取 SurfaceView 对象,并实现 SurfaceHolder.Callback 接口,用于监听 SurfaceView 的状态变化。
4. 在 SurfaceHolder.Callback 接口的 surfaceCreated 方法中获取 Canvas 对象,并设置画笔的属性。
5. 在 SurfaceHolder.Callback 接口的 surfaceChanged 方法中设置画布的宽高。
6. 在 SurfaceHolder.Callback 接口的 surfaceDestroyed 方法中释放画布资源。
7. 实现 onTouchEvent 方法,监听用户的手势操作,根据手势绘制图形。
8. 在清空画布时,可以调用 Canvas.drawColor(Color.WHITE) 方法清空画布。
以上是 Android 画板的基本实现步骤,具体实现可以参考相关的教程和示例代码。
相关问题
Android实现画板包括涂鸦 改变颜色 橡皮擦 调节画笔粗细 撤销上一步 保存图片等功能的详细代码
好的,下面是一个简单的 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>
```
这个示例代码中包含了涂鸦、改变颜色、橡皮擦、调节画笔粗细、撤销上一步和保存图片等功能,你可以根据自己的需求进行修改和扩展。
Android 标签画板
你需要在 Android 应用中实现标签画板功能,对吗?那么,你可以遵循以下步骤:
1. 创建一个画布布局
在你的 XML 布局文件中创建一个画布,这个画布将用于绘制标签。你可以使用 `Canvas` 类来实现这个画布。
```
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/image_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitXY"/>
<View
android:id="@+id/drawing_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
```
2. 创建绘图类
创建一个 `DrawingView` 类,这个类将实现标签的绘制功能。在这个类中,你需要重写 `onDraw()` 方法,这个方法会在每次绘制时调用。在这个方法中,你可以使用 `Canvas` 对象来绘制标签。
```
public class DrawingView extends View {
private Paint paint;
private Path path;
private List<Path> paths;
public DrawingView(Context context) {
super(context);
init();
}
public DrawingView(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(5f);
path = new Path();
paths = new ArrayList<>();
paths.add(path);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (Path path : paths) {
canvas.drawPath(path, paint);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
path.moveTo(x, y);
return true;
case MotionEvent.ACTION_MOVE:
path.lineTo(x, y);
break;
case MotionEvent.ACTION_UP:
path = new Path();
paths.add(path);
break;
default:
return false;
}
invalidate();
return true;
}
}
```
3. 在 Activity 中使用绘图类
在你的 Activity 中,获取 `DrawingView` 对象,并将其添加到布局中。
```
public class MainActivity extends AppCompatActivity {
private DrawingView drawingView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
drawingView = findViewById(R.id.drawing_view);
}
}
```
现在,你的应用就可以使用标签画板功能了。当你在画布上绘制时,会出现红色的线条。你可以使用其他颜色和线条宽度来自定义绘制效果。