Android MotionEvent ACTION_MOVE efficiency. How to

2020-07-16 12:46发布

问题:

I am currently working on an app that allows for free-drawing.

The current method I am using is as follows:

currentLine is a list that keeps a history of all points that ACTION_MOVE returns.

public boolean onTouchEvent (MotionEvent event) {

        switch (event.getAction()) {
            case MotionEvent.ACTION_MOVE:
                Point p = new Point(event.getX(),event.getY());
                currentLine.addPoint(p);
                    invalidate();
                break;
        }

        return true;

}

I then take these points and draw them in the onDraw method of my class.

@Override
protected void onDraw(Canvas c) {
    super.onDraw(c);

    //Draw Background Color
    c.drawColor(Color.BLUE);

    //Setup Paint
    Paint p = new Paint();
    p.setStyle(Style.FILL);
    p.setColor(COLOR.WHITE);

    //iterate through points
    if(currentLine.size()>0){
        for(int x = 0;x<currentLine.size();x++){
            c.drawCircle(currentLine.get(x).getX(), currentLine.get(x).getY(), 3, p);
        }
    }

}

And this method works great, with no lag or anything.

Except, it does not get enough of the points that it needs to.

For example, if I am to drag my finger quickly across the entire screen, it may only draw 15 points of the whole event.

How can I improve the performance/speed of the MotionEvent? How can I get more points? Or is there something else I should be doing?

----EDIT----

I have managed to solve it myself.

Instead of using drawCircle, I switched to drawLine.

Example:

if(points.size()>0){
        for(int x = 0;x<points.size()-1;x++){
            c.drawLine(points.get(x).getX(), points.get(x).getY(), points.get(x+1).getX(), points.get(x+1).getY(), p);
        }
}

This produces solid lines, which is what I wanted.

However, for the sake of knowledge, I would still like to know how to speed up MotionEvents.

A detailed answer would be appreciated

回答1:

The bottleneck is the drawing method, obviously.

If you are working on android 3.0+, draw all those crazy things on the GPU. Add the attribute

android:hardwareAccelerated="true"

to the <application> tag in your manifest. This will unbelievably increase drawing time.

Additionally, try to not redraw the whole thing if only a little needs to be updated. Invoke invalidate(Rect dirty) instead of invalidate().



回答2:

You should also get more points by utilizing event.getHistoricalX/Y() functions



回答3:

Put a small thread sleep in the motion event; that helped me solve the problem when a ton of movement events were jamming the listener.

Thread.sleep(100);


回答4:

invalidate(); is harmful for performance. Try to calculate bounds rect and call invalidate(bounds)