我开发了一个绘制Android应用程序的流程图,但我正在努力保存绘图。我实现了一种保存图像的方法,但这种方法的作用基本上是打印出当前在绘图表面上可见的内容。由于表面是可缩放的,因此当时在屏幕上可见的并不总是图画的良好镜头。在保存绘图之前,应用程序需要确保所有图表都可见。
以下是一些屏幕截图,可以进一步解释问题所在。
让我们说用户绘制了一个如下图:
然后开始检查图表。您可以放大并从上到下查看所有图表。完全向下滚动并确保一切正常后,此时点击保存按钮:
这是保存在您图库中的.PNG文件:
为了更好地拍摄图表,您必须向后缩小并确保图表位于画布中间并且其所有部分都可见。如果此时单击“保存”按钮:
这是输出,非常不错:
如何在不需要用户完成工作的情况下全面拍摄图表?这是我为保存图片而编写的代码:
private void saveImage(){
View content = drawingSurface;
drawingSurface.prepareToSaveAsImage(true);
content.setDrawingCacheEnabled(true);
content.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);
Bitmap bitmap = content.getDrawingCache();
FileOutputStream ostream;
File folder = new File(pathToFolder);
if (!folder.exists()){
folder.mkdirs();
}
File file = new File (pathToImage);
try {
file.createNewFile();
ostream = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, ostream);
ostream.flush();
ostream.close();
Toast.makeText(getApplicationContext(), "image saved" + pathToImage, Toast.LENGTH_SHORT).show();
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(getApplicationContext(), "error", Toast.LENGTH_SHORT).show();
}
drawingSurface.prepareToSaveAsImage(false);
}
有没有办法获取整个Canvas并让用户选择它的一部分?
DrawingSurface是一个可缩放和可滚动的表面。
编辑:一些方法可让您了解缩放,缩放和滚动的工作原理。
DrawingSurface的onDraw()方法:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
this.canvas = canvas;
canvas.save();
posX = Math.min(MAX_COORDINATE, Math.max(MIN_COORDINATE, posX));
posY = Math.min(MAX_COORDINATE, Math.max(MIN_COORDINATE, posY));
canvas.translate(posX, posY);
canvas.scale(scaleFactor, scaleFactor);
if (!hideLines){
paint.setColor(Color.GRAY);
for (int a = -10; a < 10; a++) {
for (int b = -10; b < 10; b++) {
canvas.drawLine(1000 * a, -10000, 1000 * a, 10000, paint);
canvas.drawLine(-10000, 1000 * b, 10000, 1000 * b, paint);
}
}
paint.setColor(Color.BLACK);
}
for (Shape shape : shapes){
shape.drawThis();
}
canvas.restore();
}
ScaleListener类在用户收入或放出时放大/缩小:
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
@Override
public boolean onScale(ScaleGestureDetector detector) {
if (selectedShape != null){
float shapeScaleFactor = detector.getScaleFactor();
selectedShape.scale(shapeScaleFactor);
} else {
scaleFactor *= detector.getScaleFactor();
scaleFactor = Math.max(0.1f, Math.min(scaleFactor, 1.0f));
}
invalidate();
return true;
}
}
检测滚动的onTouch()方法:
public boolean onTouchEvent (MotionEvent event){
scaleGestureDetector.setQuickScaleEnabled(true);
scaleGestureDetector.onTouchEvent(event);
final int action = event.getAction();
float[] coords = new float[2];
coords[0] = event.getX();
coords[1] = event.getY();
Matrix matrix = new Matrix();
matrix.set(getMatrix());
matrix.preTranslate(posX, posY);
matrix.preScale(scaleFactor, scaleFactor);
matrix.invert(matrix);
matrix.mapPoints(coords);
final int x = Math.round(event.getX());
final int y = Math.round(event.getY());
cX = Math.round(coords[0]);
cY = Math.round(coords[1]);
switch (action & MotionEvent.ACTION_MASK){
case MotionEvent.ACTION_DOWN: {
startClickTime = Calendar.getInstance().getTimeInMillis();
isZooming = false;
lastX = x;
lastY = y;
break;
}
case MotionEvent.ACTION_MOVE: {
if (scaleGestureDetector.isInProgress()){
isZooming = true;
} else if (!isZooming){
final int dX = (x - lastX);
final int dY = (y - lastY);
if (selectedShape != null){
selectedShape.translate(Math.round(dX / scaleFactor), Math.round(dY / scaleFactor));
} else {
posX += dX;
posY += dY;
}
}
lastX = x;
lastY = y;
invalidate();
break;
}
case MotionEvent.ACTION_UP: {
long clickDuration = Calendar.getInstance().getTimeInMillis() - startClickTime;
if (clickDuration < MAX_CLICK_DURATION && !scaleGestureDetector.isInProgress()){
// Kullanıcı sadece dokundu. Nereye dokunduğuna bakılmalı.
boolean touchedAShape = false;
boolean addedTextOrLine = false;
Shape lastShape;
// Bir şekle dokunduysa o şekil seçili olmalı.
for (Shape shape : shapes){
if (shape.contains(new Point(cX, cY))){
if (selectedShape != null){
addedTextOrLine = true;
if (selectedShape == shape){
getShapeTextInput(shape);
} else {
selectedShape.setLine(shape);
}
}
select(shape);
touchedAShape = true;
}
}
// Boş alana dokunuldu, önceden seçilmiş olan şekil artık seçili olmamalı.
if ((!touchedAShape) || addedTextOrLine){
if (selectedShape != null) selectedShape.setSelect(false);
selectedShape = null;
}
}
invalidate();
}
}
return true;
}