Joan Carles
Joan Carles

Reputation: 303

Customs views and TouchEvent

I'm programming a custom view that divides the image into pieces. The objective is to exchange the chunk touched by the adjacent piece depending on the displacement direction. The problem I have is that the ACTION_UP of the function OnTouch is never executed. What am I doing wrong?

public class ChunkView extends View implements OnTouchListener {

protected enum MoveDir {
    LEFT,
    RIGHT,
    UP,
    DOWN,
    NONE
}

//ImageView myImageView;
Bitmap myBitmap;
Paint myPaint;
Paint myRectPaint;

int nRows = 6;
int nCols = 5;

int widthChunk;
int heightChunk;

int idImage;
int showGrid;

float coordX1, coordY1, coordX2, coordY2;
int cellX1, cellY1, cellX2, cellY2;

public int getShowGrid() {
    return showGrid;
}

public void setShowGrid(int showGrid) {
    this.showGrid = showGrid;
    invalidate();
    requestLayout();
}

ArrayList<Bitmap> chunksBitmap;

public ChunkView(Context context, AttributeSet attrs) {
    super(context, attrs);

    TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.ChunkView, 0, 0);
    try {
        showGrid = a.getInteger(R.styleable.ChunkView_showGrid, 0);
    }
    finally {
        a.recycle();
    }

    setOnTouchListener(this);

    init();
    // TODO Auto-generated constructor stub
}

public int getIdImage() {
    return idImage;
}

public void setIdImage(int idImage) {
    this.idImage = idImage;
}

private void init() {
    myBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ejemplo);
    //myImageView.setImageBitmap(myBitmap);

    myPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    myRectPaint = new Paint();

    chunksBitmap = new ArrayList<Bitmap>();

    myRectPaint.setStyle(Paint.Style.STROKE);
    myRectPaint.setColor(Color.BLACK);
    myRectPaint.setStrokeWidth(3);              
}

protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);       

    //myImageView.draw(canvas);

    for (int r = 0; r < nRows; ++r) {
        for (int c = 0; c < nCols; ++c) {
            canvas.drawBitmap(chunksBitmap.get(r * nCols + c),  widthChunk * c, heightChunk * r, myPaint);
            canvas.drawRect(widthChunk * c, heightChunk * r, widthChunk * (c + 1), heightChunk * (r + 1), myRectPaint);
        }
    }       
}

@Override
protected void onSizeChanged(int xNew, int yNew, int xOld, int yOld) {
    super.onSizeChanged(xNew, yNew, xOld, yOld);

    Bitmap scaledBitmap = Bitmap.createScaledBitmap(myBitmap, xNew, yNew, true);

    widthChunk = xNew / nCols;
    heightChunk = yNew / nRows;

    chunksBitmap.clear();
    for (int r = 0; r < nRows; ++r) {
        for (int c = 0; c < nCols; ++c) {
            chunksBitmap.add(Bitmap.createBitmap(scaledBitmap, c * widthChunk, r * heightChunk , widthChunk, heightChunk));             
        }
    }               
}

protected MoveDir getDirection() {
    float dx = coordX2 - coordX1;
    float dy = coordY2 - coordY1;

    if(Math.abs(dx) > Math.abs(dy)) {
        if (dx > widthChunk) 
            return MoveDir.RIGHT;
        else if (dx < -widthChunk)
            return MoveDir.LEFT;
    } 
    else {
        if (dy > heightChunk)
            return MoveDir.DOWN;
        else if (dy < -heightChunk)
            return MoveDir.UP;
    }

    return MoveDir.NONE;
}   

protected boolean isValidCell(int X, int Y) {
    return (X >= 0) && (X > nCols) && (Y>= 0) && (Y < nRows); 
}

@Override
public boolean onTouch(View v, MotionEvent event) {
    String msg = String.valueOf(v.getId());
    Log.e("DBG", msg);

    if (event.getAction() == MotionEvent.ACTION_DOWN) {
        Log.e("DBG", "DOWN");
        coordX1 = event.getX();
        coordY1 = event.getY();
    }
    else if (event.getAction() == MotionEvent.ACTION_UP) {
        Log.e("DBG", "UP");
        coordX2 = event.getX();
        coordY2 = event.getY();

        MoveDir dir = getDirection();

        if (dir != MoveDir.NONE) {
            // Converteix els pixels en coordenades
            cellX1 = cellX2 = ((int)(coordX1 / widthChunk) * widthChunk);
            cellY1 = cellY2 = ((int)(coordY1 / heightChunk) * heightChunk);

            if (dir == MoveDir.LEFT)
                cellX2--;
            else if (dir == MoveDir.RIGHT)
                cellX2++;
            else if (dir == MoveDir.UP)
                cellY2--;
            else if (dir == MoveDir.UP)
                cellY2++;            

            String msg1 = "(" + String.valueOf(cellX1) + ", " + String.valueOf(cellY1) + ")";
            String msg2 = "(" + String.valueOf(cellX2) + ", " + String.valueOf(cellY2) + ")";
            Log.e("DBG", msg1 + " -> " + msg2);

            if ((!isValidCell(cellX1, cellY1)) || (!isValidCell(cellX2, cellY2)))
                return false;

            invalidate();
        }           
    }           

    return false;
}       

}

Thanks in advance.

Upvotes: 0

Views: 70

Answers (1)

Elior
Elior

Reputation: 3266

try to use this.. it uses switch case statement so for any time the screen is pressed it will return true, so if the next time you stop pressing the screen it will go the ACTION_UP case

@Override
public boolean onTouch(View v, MotionEvent event) {
    String msg = String.valueOf(v.getId());
    Log.e("DBG", msg);

    switch(event.getAction()){
     case MotionEvent.ACTION_DOWN:

        Log.e("DBG", "DOWN");
        coordX1 = event.getX();
        coordY1 = event.getY();
       return true;

    case MotionEVent.ACTION_UP:
        Log.e("DBG", "UP");
        coordX2 = event.getX();
        coordY2 = event.getY();
        // rest of your code
        return true;
    }

Upvotes: 2

Related Questions