Search code examples
androideventsscrolltouch-eventoverwrite

ScrollView event Overwrites DrawView Event


I have a drawView on a scrollView. Now when you dont scroll, and write, theres no problem. Everything looks fine. BUT, after you scrolled you can paint vertically fine, but as soon as you paint up, it sets your Y coordinate to that of the ScrollView (I think)

I suspect that the scrollevent is overwriting the onTouch event. But I have NO clue how to fix it yet.

For instance

07-11 13:17:46.903  25508-25508/ V/﹕ Y - 8859.633
07-11 13:17:46.913  25508-25508/ V/﹕ Y - 8856.579
07-11 13:17:46.913  25508-25508/ V/﹕ Y - 8856.579
07-11 13:17:46.933  25508-25508/ V/﹕ Y - 8851.542
07-11 13:17:46.933  25508-25508/ V/﹕ Y - 8851.542
07-11 13:17:46.953  25508-25508/ V/﹕ Y - 8847.878
07-11 13:17:46.973  25508-25508/ V/﹕ Y - 544.6034 (as soon as I paint vertically up or down)

Images below illustrate what happens. The yellow highlighter would be my pen/finger and the blue is the actual drawing.

When not scrolled down

enter image description here

When scrolled down and as soon as I draw up or down

enter image description here

Code

public class MainActivity extends Activity {
    DrawingView dv ;
    private Paint mPaint;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

       dv = new DrawingView(this);
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setDither(true);
        mPaint.setColor(Color.GREEN);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeJoin(Paint.Join.ROUND);
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        mPaint.setStrokeWidth(12);

        ScrollView mScrollView = new ScrollView(this);
        mScrollView.addView(dv);
        setContentView(mScrollView);

        mScrollView.setOnTouchListener( new View.OnTouchListener() {

            @Override
            public boolean onTouch(View v, MotionEvent m)
            {
                if(m.getTouchMajor() == 0.0f) {
                    Log.v("xxxx","Scroll Touch Pen");
                    dv.onTouchEvent(m);  <-- I know I am not passing the correct MotionEvent, but I have NO idea how to get the right one. At least this way I'm a "bit" closer to solving it as I can write horizontally as well without scrolling.
                    return true;
                }
                else
                {
                    Log.v("xxxx","Scroll Touch Fingure");

                    return false;
                }
            }


        });
    }

And My DrawinngView

 public class DrawingView extends View {

        public int width;
        public  int height;
        private Bitmap  mBitmap;
        private Canvas  mCanvas;
        private Path    mPath;
        private Paint   mBitmapPaint;
        Context context;
        private Paint circlePaint;
        private Path circlePath;
        Rect clipBounds_canvas;

        public DrawingView(Context c) {
            super(c);
            context=c;
            mPath = new Path();
            mBitmapPaint = new Paint(Paint.DITHER_FLAG);
            circlePaint = new Paint();
            circlePath = new Path();
            circlePaint.setAntiAlias(true);
            circlePaint.setColor(Color.BLUE);
            circlePaint.setStyle(Paint.Style.STROKE);
            circlePaint.setStrokeJoin(Paint.Join.MITER);
            circlePaint.setStrokeWidth(4f);
        }

        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            super.onSizeChanged(w, h, oldw, oldh);

            mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
            mCanvas = new Canvas(mBitmap);

        }
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            clipBounds_canvas = canvas.getClipBounds();
            canvas.drawBitmap( mBitmap, 0, 0, mBitmapPaint);

            canvas.drawPath( mPath,  mPaint);

            canvas.drawPath( circlePath,  circlePaint);
        }

        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            // Compute the height required to render the view
            // Assume Width will always be MATCH_PARENT.
            int width = MeasureSpec.getSize(widthMeasureSpec);

            int height = 10000; 
            setMeasuredDimension(width, height);
        }
        private float mX, mY;
        private static final float TOUCH_TOLERANCE = 4;


        private void touch_start(float x, float y) {
        //    mPath.reset();

            mPath.moveTo(x, y);
            mX = x;
            mY = y;
            Log.v("xxxx","Y - Start - " + y);

        }
        private void touch_move(float x, float y) {
            float dx = Math.abs(x - mX);
            float dy = Math.abs(y - mY);
            if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
                mPath.quadTo(mX, mY, (x + mX)/2, (y + mY)/2);
                mX = x;
                mY = y;

                Log.v("xxxx","Y - Move - " + y);

                circlePath.reset();
                circlePath.addCircle(mX, mY, 30, Path.Direction.CW);
            }
        }
        private void touch_up() {
            mPath.lineTo(mX, mY);
            circlePath.reset();
            // commit the path to our offscreen
            mCanvas.drawPath(mPath,  mPaint);
        }

        @Override
        public boolean onTouchEvent(MotionEvent event) {
            float x = event.getX();
            float y = event.getY();

            Log.v("xxxx","Y - " + y);

            if(event.getTouchMajor() == 0.0f) {
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        touch_start(x, y);
                        invalidate();
                        break;
                    case MotionEvent.ACTION_MOVE:
                        touch_move(x, y);
                        invalidate();
                        break;
                    case MotionEvent.ACTION_UP:
                        touch_up();
                        invalidate();
                        break;
                }
                return true;

//                handleTouch(event);
//                return true;
            }
            else
            {
                return false;
            }
        }
    }

Might you be able to see how I can keep the scrollview from overwriting my motion event (or at least have two separate ones if that is at all possible.


Solution

  • Found a great solution here, that worked perfectly

    Just use this method

    public static void disableTouchTheft(View view) {
        view.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                view.getParent().requestDisallowInterceptTouchEvent(true);
                switch (motionEvent.getAction() & MotionEvent.ACTION_MASK) {
                case MotionEvent.ACTION_UP:
                    view.getParent().requestDisallowInterceptTouchEvent(false);
                    break;
                }
                return false;
            }
        });
    }