Путь рисования на холсте, когда сенсорный ввод быстро перемещается и останавливается, последний сегмент непрерывно мигает - PullRequest
2 голосов
/ 09 августа 2011

Я работаю над приложением для рисования.Это довольно просто, использует onTouchEvent, paths и canvas.drawPath.Всякий раз, когда пользователь делает быстрый удар и отпускает без остановки, последний сегмент пути постоянно мигает.В условии ACTION_UP я обновляю путь и устанавливаю логическое значение resetPath равным true, а в onDraw я рисую путь, и если resetPath равен true, я вызываю path.reset (), а затем устанавливаю resetPath на false.Что я делаю не так?

    class DrawingPanel extends SurfaceView implements SurfaceHolder.Callback {
    private DrawingThread _thread;
    private Path path;
    private Boolean resetPath = false;

    public DrawingPanel(Context context) {
        super(context);
        getHolder().addCallback(this);
        _thread = new DrawingThread(getHolder(), this);
        path = new Path();
    }


    private float mX, mY;
    private static final float TOUCH_TOLERANCE = 25;



    public boolean onTouchEvent(MotionEvent event) {

        synchronized (_thread.getSurfaceHolder()) {
            if(event.getAction() == MotionEvent.ACTION_DOWN){
                path.reset();
                path = new Path();
                path.moveTo(event.getX(), event.getY());
                mX = event.getX();
                mY = event.getY();
            }else if(event.getAction() == MotionEvent.ACTION_MOVE){
                float dx = Math.abs(event.getX() - mX);
                float dy = Math.abs(event.getY() - mY);
                if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
                    path.quadTo(mX, mY, (event.getX() + mX)/2, (event.getY() + mY)/2);
                    mX = event.getX();
                    mY = event.getY();
                }
            }else if(event.getAction() == MotionEvent.ACTION_UP){
                resetPath = true;
            }
            return true;
        }
    }

    @Override
    public void onDraw(Canvas canvas) {
        canvas.drawPath(path, mPaint);
        if (resetPath) {
            path.reset();
            resetPath = false;
        }
    }

1 Ответ

0 голосов
/ 17 мая 2013

Рассмотрим следующее

  1. В onDraw вы не рисуете и не сбрасываете весь холст перед тем, как рисовать свой путь. Обычно вы должны. Если нет, он всегда рисует путь поверх предыдущего растрового изображения. Если в вашей краске использовалась прозрачность, из-за перекрытия самые старые части пути, которые вы рисуете, были бы менее прозрачными, чем самые новые.
  2. OnTouchEvent и onDraw не работают в одном потоке.
  3. SurfaceView прозрачно использует технику двойной буферизации. Два последовательных вызова onDraw будут отображаться на двух разных холстах. Следовательно, если между двумя вызовами onDraw есть ACTION_MOVE и ACTION_UP, второй буфер будет иметь больше рисунков, чем первый. Вот почему у вас есть мигающий эффект.

Решение

Измените resetPath на целое число, чтобы вы могли дважды нарисовать путь перед его сбросом.

private int resetPath = 0;

...else if(event.getAction() == MotionEvent.ACTION_UP){
            resetPath = 2;
   }...

public void onDraw(Canvas canvas) {
    canvas.drawPath(path, mPaint);
    if (resetPath == 1) {
        path.reset();
        resetPath = 0;
    } else if(resetPath == 2) {
        resetPath = 1
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...