У меня есть код, который мне нужно улучшить.
Вот что не так: он немного медленный и прерывистый, что означает, что линии не плавные, а рисунок немного задерживается.
public void touchStarted(Point point) {
if (null == drawingModePath) {
drawingModePath = new Path();
}
drawingModePath.moveTo(point.x, point.y);
}
public void touchMoved(Point point) {
drawingModePath.lineTo(point.x, point.y);
Bitmap bitmap = Bitmap.createBitmap((int) getWindowManager()
.getDefaultDisplay().getWidth(), (int) getWindowManager()
.getDefaultDisplay().getHeight(), Bitmap.Config.ARGB_8888);
canvas = new Canvas(bitmap);
mainDrawingView.setImageBitmap(bitmap);
// Path
paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
paint.setColor(Color.WHITE);
canvas.drawPath(drawingModePath, paint);
}
public void touchEnded(Point point) {
touchMoved(point);
}
По сути, этот код рисует путь на основе touchStarted, touchMoved и touchEnded. Если кто-то может помочь мне оптимизировать это, я был бы признателен. Возможно, если я не буду воссоздавать растровое изображение каждый раз, когда происходит touchMoved? Не уверен здесь ... не уверен ... Я использую UIBezierPath для выполнения этого кода на iOS, и он немного быстрее (и плавнее). В любом случае, я обращаюсь к вам за помощью. Вход оценен.
вы воссоздаете все на каждом шагу. это сильно повлияет на производительность рисования. событие запускается каждые 8 мс (или 16 мс, я не уверен), представьте, что вы восстанавливаете все каждые 8 мс? это сложно.
так что это должно быть в части создания экземпляра
Bitmap bitmap = Bitmap.createBitmap((int) getWindowManager()
.getDefaultDisplay().getWidth(), (int) getWindowManager()
.getDefaultDisplay().getHeight(), Bitmap.Config.ARGB_8888);
canvas = new Canvas(bitmap);
mainDrawingView.setImageBitmap(bitmap);
paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
paint.setColor(Color.WHITE);
touchMoved() должен только записывать новый путь и вызывать invalidate (), чтобы View перерисовал себя, что привело к вызову метода рисования (onDraw()).
public void touchMoved(Point point) {
drawingModePath.lineTo(point.x, point.y);
invalidate();
}
а затем реализовать метод onDraw() для рисования
Вот как я делаю интерфейс для рисования в одном из моих проектов:
public class SignatureView extends View {
public SignatureView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
// instantiating my paint object
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(5);
path = new Path();
}
@Override
protected void onSizeChanged(int xNew, int yNew, int xOld, int yOld)
{
// this is where i initialize my canvas, because in constructor, the view is not completely instantiated yet, so getting the height and width there will result in null exception.
bitmap = Bitmap.createBitmap(xNew, yNew, Bitmap.Config.ARGB_8888);
background_canvas = new Canvas(bitmap);
}
@Override
protected void onDraw(Canvas canvas)
{
// draw the new path to a buffer canvas
background_canvas.drawPath(path, paint);
// put the buffer in the real canvas
canvas.drawBitmap(bitmap, 0, 0, paint);
}
@Override
public boolean onTouchEvent(MotionEvent ev)
{
//this is like your move event, it just records the new path every move.
int action = ev.getActionMasked();
if ( action == MotionEvent.ACTION_DOWN )
{
path.moveTo(ev.getX(), ev.getY());
}
else if ( action == MotionEvent.ACTION_MOVE )
{
path.lineTo(ev.getX(), ev.getY());
// call invalidate() to make the view redraw itself, resulting in calling the onDraw() method.
invalidate();
}
else if ( action == MotionEvent.ACTION_UP )
{
onDone.method();
}
return true;
}
public void clear()
{
background_canvas.drawColor(Color.WHITE);
path.reset();
invalidate();
}
interface OnDone{
void method();
}
public void setOnDone(OnDone new_onDone)
{
onDone = new_onDone;
}
OnDone onDone;
private Paint paint;
private Bitmap bitmap;
private Canvas background_canvas;
private Path path;
public Bitmap getBitmap()
{
return bitmap;
}
}