Search code examples
androidandroid-custom-view

Partial View invalidation not working as expected


In trying to tackle custom views, I'm attempting to work with touch events and partial invalidation. For this, it's just a row of numbers in squares spaced to fill the screen.

Now when I press on a single block, I get the block's rectangle using this:

private Rect getDirtyRegion(float e){
    // The value is the slot number
    mValue = ((int)e / mBlockSize);

    // start X of the "stall"
    int x1 = mValue * mBlockSize;
    int y1 = 0;

    int x2 = x1 + mBlockSize;
    int y2 = getMeasuredHeight();

    return new Rect(x1, y1, x2, y2);
}

It works as expected. When there's just a few on screen it works great. Here's my onTouchEvent:

@Override
public boolean onTouchEvent(MotionEvent e){        

    switch(e.getAction()){
    case MotionEvent.ACTION_DOWN:
        Log.d(TAG, "ActionDown");

        setPaint(PinEntry.PAINT_PRESSED);
        invalidate(getDirtyRegion(e.getX()));
        break;

    case MotionEvent.ACTION_UP:
    case MotionEvent.ACTION_CANCEL:

        setPaint(PinEntry.PAINT_NORMAL);
        invalidate();
        break;
    }
    return true;
}

(This has been rewritten quite a few times, so the call to invalidate without a rectangle hasn't always been the case.)

What I'm after is, when I tap on a number, it redraws to indicate a PRESSED state by whatever I do in setPaint. When I release, reset.

When I have multiple views in a ScrollView, however it breaks. When I press and release, or even drag outside the bound (triggering ACTION_CANCEL), it resets. However, going back to that row causes the whole thing to invalidate as "PRESSED".

Is this a TouchEvent logic issue, a drawing issue, or some combination of my inexperience with creating custom views?


Solution

  • I ended up splitting it into two different classes, one for the container (parent), and another for each individual block and using the draw(Canvas) method of the View class.