我通过从AppCompatImageView
扩展一个类来实现一个绘图应用程序,它工作得很好,但是当绘制很多路径时,它的速度会降低
绘制任何新路径时是否可以,只绘制添加到视图中的新路径?
换句话说,只需更新视图的特定部分并且不必每次都更新所有视图。
PaintView.java
import android.content.Context;
import android.graphics.*;
import android.support.annotation.ColorInt;
import android.support.annotation.IntRange;
import android.support.v7.widget.AppCompatImageView;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.Stack;
public class PaintView extends AppCompatImageView implements View.OnTouchListener {
private int defaultColor = 0xffff0000;
private int defaultLineStrokeWidth = 4;
private int defaultAlpha = 255;
private int currentPathIndex = 0;
private boolean isTouchDown = false;
private boolean showBounds = false;
private boolean isDeleteMode = false;
private Paint linePaint;
private Paint rectPaint;
private Stack<PathHolder> paths;
private Stack<PathHolder> memoryList;
public GestureView(Context context) {
super(context);
init();
}
public GestureView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public GestureView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
setOnTouchListener(this);
setBackgroundColor(Color.WHITE);
linePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
linePaint.setStrokeWidth(defaultLineStrokeWidth);
linePaint.setDither(true);
linePaint.setAntiAlias(true);
linePaint.setColor(Color.BLACK);
linePaint.setStyle(Paint.Style.STROKE);
linePaint.setStrokeCap(Paint.Cap.ROUND);
linePaint.setStrokeJoin(Paint.Join.ROUND);
linePaint.setPathEffect(new CornerPathEffect(10));
rectPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
rectPaint.setStrokeWidth(0.5f);
rectPaint.setAntiAlias(true);
rectPaint.setColor(Color.RED);
rectPaint.setStyle(Paint.Style.STROKE);
paths = new Stack<>();
memoryList = new Stack<>();
}
public void setPaintColor(@ColorInt int color) {
defaultColor = color;
}
public void showBounds(boolean show) {
showBounds = show;
invalidate();
}
public void setDeleteMode(boolean deleteMode) {
this.isDeleteMode = deleteMode;
invalidate();
}
public void setLineStrokeWidth(int width) {
if (width > 0) {
defaultLineStrokeWidth = width;
} else {
Log.e("GestureView", "Stroke width can't be zero or less.");
}
}
public void setLineAlpha(@IntRange(from = 0, to = 255) int alpha) {
defaultAlpha = alpha;
}
public int getDefaultLineStrokeWidth() {
return defaultLineStrokeWidth;
}
public void clearScreen() {
currentPathIndex = 0;
paths.clear();
memoryList.clear();
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
if (paths.size() > 0) {
for (int i = 0; i < paths.size(); i++) {
paths.get(i).setColor(paths.get(i).getColor() != 0 ? paths.get(i).getColor() : defaultColor);
paths.get(i).setStrokeWidth(paths.get(i).getStrokeWidth() != 0 ? paths.get(i).getStrokeWidth() : defaultLineStrokeWidth);
paths.get(i).setAlpha(paths.get(i).getAlpha() != 0 ? paths.get(i).getAlpha() : defaultAlpha);
linePaint.setColor(paths.get(i).getColor());
linePaint.setStrokeWidth(paths.get(i).getStrokeWidth());
linePaint.setAlpha(paths.get(i).getAlpha());
canvas.drawPath(paths.get(i).getPath(), linePaint);
paths.get(i).getPath().computeBounds(paths.get(i).getRect(), true);
if (showBounds && (!isTouchDown || currentPathIndex != i)) {
canvas.drawRect(paths.get(i).getRect(), rectPaint);
}
}
}
}
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (isDeleteMode) {
for (int i = 0; i < paths.size(); i++) {
if (RectF.intersects(paths.get(i).getRect(), new RectF(motionEvent.getX(), motionEvent.getY(), motionEvent.getX(), motionEvent.getY()))) {
memoryList.push(paths.get(i));
paths.remove(i);
currentPathIndex--;
invalidate();
break;
}
}
} else {
switch (motionEvent.getAction()) {
case MotionEvent.ACTION_DOWN:
isTouchDown = true;
Path path = new Path();
path.moveTo(motionEvent.getX(), motionEvent.getY());
RectF rectF = new RectF();
path.computeBounds(rectF, true);
PathHolder pathHolder = new PathHolder();
pathHolder.setPath(path);
pathHolder.setRect(rectF);
paths.add(currentPathIndex, pathHolder);
break;
case MotionEvent.ACTION_UP:
isTouchDown = false;
paths.get(currentPathIndex).getPath().lineTo(motionEvent.getX(), motionEvent.getY());
currentPathIndex++;
invalidate();
break;
case MotionEvent.ACTION_MOVE:
paths.get(currentPathIndex).getPath().lineTo(motionEvent.getX(), motionEvent.getY());
invalidate();
break;
}
}
return true;
}
public void undo() {
if (paths.isEmpty()) {
return;
}
memoryList.push(paths.pop());
currentPathIndex--;
invalidate();
}
public void redo() {
if (memoryList.isEmpty()) {
return;
}
paths.push(memoryList.pop());
currentPathIndex++;
invalidate();
}
public Bitmap getCaptureBitmap() {
setDrawingCacheEnabled(true);
return getDrawingCache();
}
public void saveCaptureTo(String path, int quality) {
Bitmap b = getCaptureBitmap();
try {
b.compress(Bitmap.CompressFormat.PNG, quality, new FileOutputStream(path));
} catch (FileNotFoundException e) {
Log.e(GestureView.class.getSimpleName(), e.getMessage());
}
}
}
答案 0 :(得分:0)
因此,当您在Canvas上绘图时,您必须再次绘制整个Canvas。根据我的理解,每当onDraw被调用(60ps)
时,你基本上都会使用一张新纸