安卓开发-手绘板自定义绘画的保存,清空与恢复
写这篇文章是因为代码中刚实现过这些功能,害怕自己之后会忘记,所以把整个方法写出来,方便自己日后复习用。还是老样子,先上图:1.首页2.点击手绘板图片后跳出的窗口3.用手指进行绘制4.点击保存按钮原理什么的就不说了,直接上代码:1.MainActivityimport androidx.appcompat.app.AppCompatActivity;import android.graphics.B
·
写这篇文章是因为代码中刚实现过这些功能,害怕自己之后会忘记,所以把整个方法写出来,方便自己日后复习用。
还是老样子,先上图:
1.首页
2.点击手绘板图片后跳出的窗口
3.用手指进行绘制
4.点击保存按钮
原理什么的就不说了,直接上代码:
1.MainActivity
import androidx.appcompat.app.AppCompatActivity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Base64;
import android.view.View;
import android.widget.ImageView;
import android.widget.Toast;
import java.io.ByteArrayOutputStream;
public class MainActivity extends AppCompatActivity {
private ImageView iv_wacom_may;//显示图片用的控件
private MakeWacomDialog makeWacomDialog;//用来显示手绘板的对话框
private String savedphoto = "";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();//代码初始化
setClick();//设置点击方法
}
/**
* 设置点击方法
*/
private void setClick() {
iv_wacom_may.setOnClickListener(new MainAcitivytClick());
}
/**
* 代码初始化
*/
private void initView() {
iv_wacom_may = findViewById(R.id.iv_wacom_may);
}
/**
* 设置MainActivity的点击方法
*/
private class MainAcitivytClick implements View.OnClickListener {
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.iv_wacom_may://点击了手绘板图片
BitmapFactory.Options options = new BitmapFactory.Options();
if (TextUtils.isEmpty(savedphoto)) {//修改后图片的数据,首次进入数据会是空的,这里用默认图片代替
savedphoto = changeBitmapToString(BitmapFactory.decodeResource(getResources(),
R.mipmap.wacom, options));
}
String defaultimg = changeBitmapToString(BitmapFactory.decodeResource(getResources(),
R.mipmap.wacom, options));//默认图片的数据
makeWacomDialog = new MakeWacomDialog(MainActivity.this, new saveResult(), savedphoto, defaultimg);
makeWacomDialog.setCancelable(false);//失去焦点后不会自动关闭对话框
makeWacomDialog.show();//展示对话框
break;
default:
break;
}
}
}
/**
* 将图片转换成String形式
*
* @param bitmap
*/
private String changeBitmapToString(Bitmap bitmap) {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayOutputStream);
byte[] byteArray = byteArrayOutputStream.toByteArray();
return Base64.encodeToString(byteArray, Base64.DEFAULT);
}
/**
* 手绘板界面点击保存按钮后执行的监听
*/
private class saveResult implements MakeWacomDialog.GetSignature {
@Override
public void getSignature(MakeWacomView makeWacomView, Bitmap bitmap) {
savedphoto = changeBitmapToString(bitmap);
byte[] imageBytes = Base64.decode(savedphoto, Base64.DEFAULT);
Bitmap photobitmap = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length);
iv_wacom_may.setImageBitmap(photobitmap);
makeWacomDialog.dismiss();//关闭手绘板
}
}
}
2.activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="首页"
android:textSize="20sp"
android:gravity="center"
/>
<ImageView
android:id="@+id/iv_wacom_may"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_gravity="center_horizontal"
android:src="@mipmap/wacom"
android:layout_centerInParent="true"
/>
</RelativeLayout>
3.MakeWacomDialog
import android.app.Dialog;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Base64;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.Toast;
import androidx.annotation.NonNull;
/**
* @author Jay
* @date 2021/3/9
* File description.
* 手绘板提示框
*/
public class MakeWacomDialog extends Dialog {
private Button btn_save_dmm, btn_cancel_dmm, btn_clear_dmm, btn_reset_dmm;
private LinearLayout ll_wacom_dmm;
private Context context;
private MakeWacomView makeWacomView;
private GetSignature mGetSignature;
private String localphoto = "";
private String defaultimg;
private Boolean isdefaultimg = false;
protected MakeWacomDialog(@NonNull Context context, GetSignature getSignature, String localphoto, String defaultimg) {
super(context);
this.context = context;
makeWacomView = new MakeWacomView(context);
this.mGetSignature = getSignature;
this.localphoto = localphoto;
this.defaultimg = defaultimg;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.dialog_makewacom);
initWeightandHeight();//设置对话框的宽高
initView();//代码初始化
setClick();//设置点击方法
ll_wacom_dmm.addView(makeWacomView, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
setBakcground(localphoto);//设置背景图
}
/**
* 设置背景图
*
* @param localphoto
*/
private void setBakcground(String localphoto) {
try {
if (TextUtils.isEmpty(localphoto)) {
return;
}
byte[] imageBytes = Base64.decode(localphoto, Base64.DEFAULT);
Bitmap decodedImage = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length);
Drawable d = new BitmapDrawable(getContext().getResources(), decodedImage);
// mSignContent.setBackground(d);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
makeWacomView.clear();//赋值前先清空之前的图
makeWacomView.setBackground(d);
} else {
Toast.makeText(context, "当前版本不支持", Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 设置对话框的宽高
*/
private void initWeightandHeight() {
getWindow().setLayout(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT
);
}
/**
* 设置点击方法
*/
private void setClick() {
btn_save_dmm.setOnClickListener(new MakeWacomClick());
btn_cancel_dmm.setOnClickListener(new MakeWacomClick());
btn_clear_dmm.setOnClickListener(new MakeWacomClick());
btn_reset_dmm.setOnClickListener(new MakeWacomClick());
}
/**
* 代码初始化
*/
private void initView() {
btn_save_dmm = findViewById(R.id.btn_save_dmm);//保存按钮
btn_cancel_dmm = findViewById(R.id.btn_cancel_dmm);//取消按钮
btn_clear_dmm = findViewById(R.id.btn_clear_dmm);//清空按钮
btn_reset_dmm = findViewById(R.id.btn_reset_dmm);//重置按钮
ll_wacom_dmm = findViewById(R.id.ll_wacom_dmm);//显示手绘板的控件
}
/**
* 设置手绘板提示框的点击方法
*/
private class MakeWacomClick implements View.OnClickListener {
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_save_dmm://保存按钮
Bitmap bitmap = getBitmapFromView(makeWacomView);
mGetSignature.getSignature(makeWacomView, bitmap);
break;
case R.id.btn_cancel_dmm://取消按钮
MakeWacomDialog.this.dismiss();//关闭页面
break;
case R.id.btn_clear_dmm://清空按钮
if (TextUtils.isEmpty(localphoto)) {
makeWacomView.clear();
} else {
if (isdefaultimg) {//如果用户恢复了原图,这里就将原图作为底图
setBakcground(defaultimg);
} else {//如果用户没有恢复原图,就将接口传递过来的历史图作为底图
setBakcground(localphoto);
}
}
break;
case R.id.btn_reset_dmm://重置按钮
setBakcground(defaultimg);//设置背景图
isdefaultimg = true;
break;
}
}
}
/**
* 获取bitmap图
*
* @param makeWacomView
* @return
*/
private Bitmap getBitmapFromView(MakeWacomView makeWacomView) {
Bitmap returnedBitmap = Bitmap.createBitmap(makeWacomView.getWidth(), makeWacomView.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(returnedBitmap);
Drawable bgDrawable = makeWacomView.getBackground();
if (bgDrawable != null)
bgDrawable.draw(canvas);
else
canvas.drawColor(Color.WHITE);
makeWacomView.draw(canvas);
return returnedBitmap;
}
public interface GetSignature {
public void getSignature(MakeWacomView makeWacomView, Bitmap bitmap);
}
}
4.MakeWacomView
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
/**
* @author Jay
* @date 2021/3/9
* File description.
* 手绘板的核心代码
*/
public class MakeWacomView extends View {
private static final float STROKE_WIDTH = 5f;
private static final float HALF_STROKE_WIDTH = STROKE_WIDTH / 2;
private Paint paint = new Paint();
private Path path = new Path();
private float lastTouchX;
private float lastTouchY;
private final RectF dirtyRect = new RectF();
public MakeWacomView(Context context) {
super(context);
paint.setAntiAlias(true);
paint.setColor(Color.RED);//设置画笔为红色
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeWidth(STROKE_WIDTH);
}
public void clear() {
path.reset();
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawPath(path, paint);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float eventX = event.getX();
float eventY = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
path.moveTo(eventX, eventY);
lastTouchX = eventX;
lastTouchY = eventY;
return true;
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_UP:
resetDirtyRect(eventX, eventY);
int historySize = event.getHistorySize();
for (int i = 0; i < historySize; i++) {
float historicalX = event.getHistoricalX(i);
float historicalY = event.getHistoricalY(i);
expandDirtyRect(historicalX, historicalY);
path.lineTo(historicalX, historicalY);
}
path.lineTo(eventX, eventY);
break;
default:
Log.v("Ignored touch event: ", event.toString() + "");
return false;
}
invalidate((int) (dirtyRect.left - HALF_STROKE_WIDTH),
(int) (dirtyRect.top - HALF_STROKE_WIDTH),
(int) (dirtyRect.right + HALF_STROKE_WIDTH),
(int) (dirtyRect.bottom + HALF_STROKE_WIDTH));
lastTouchX = eventX;
lastTouchY = eventY;
return true;
}
private void expandDirtyRect(float historicalX, float historicalY) {
if (historicalX < dirtyRect.left) {
dirtyRect.left = historicalX;
} else if (historicalX > dirtyRect.right) {
dirtyRect.right = historicalX;
}
if (historicalY < dirtyRect.top) {
dirtyRect.top = historicalY;
} else if (historicalY > dirtyRect.bottom) {
dirtyRect.bottom = historicalY;
}
}
private void resetDirtyRect(float eventX, float eventY) {
dirtyRect.left = Math.min(lastTouchX, eventX);
dirtyRect.right = Math.max(lastTouchX, eventX);
dirtyRect.top = Math.min(lastTouchY, eventY);
dirtyRect.bottom = Math.max(lastTouchY, eventY);
}
public void setSignature(Canvas signature) {
signature.drawPath(path, paint);
}
5.dialog_makewacom.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/btn_save_dmm"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:padding="10dp"
android:text="保存" />
<Button
android:id="@+id/btn_cancel_dmm"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:padding="10dp"
android:text="取消" />
<Button
android:id="@+id/btn_clear_dmm"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:padding="10dp"
android:text="清空" />
<Button
android:id="@+id/btn_reset_dmm"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:padding="10dp"
android:text="恢复" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_wacom_dmm"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="vertical"
/>
</LinearLayout>
6.图片文件wacom.png
上面已经把所有的代码都贴出来了,当然,如果想要源码,地址在这里:https://download.csdn.net/download/u010802275/15681435
更多推荐
已为社区贡献4条内容
所有评论(0)