Scroll Horizontal on Android Canvas

0

I'm working with the Canvas class and I have several problems.

I have a class called Workbench that extends the View class to use it as a canvas.

On the canvas there are X squares and I can drag them across the screen. I have added the function so that it can be done as a horizontal scroll, which actually increases or decreases the coordinate of the X axis of each object on the canvas, and this is where it fails. When I scroll from left to right, all the objects move well and follow the same positional relationship they had, but when I do it from right to left and the objects reach the limit of the screen they do not move.

If I do it fast if they exceed the limit but if it is done slowly, they remain in the limit and they all get together.

Workbench Class:

public class Workbench extends View {
    public Point puntoMedio;
    public int lastPosX =0;
    List<Objeto> objetoList = new ArrayList<Objeto>();
    int seleccionado = 0;
    public Workbench(Context context) {
        super(context);
        puntoMedio = new Point(0,0);
        for(int i=0;i<5;i++){
            Objeto o = new Objeto();
            o.coordenada.set(10,10);
            objetoList.add(o);
        }

    }

    @Override
    protected void onDraw(Canvas c) {
        super.onDraw(c);
        int HEIGHT = c.getHeight(),WIDTH = c.getWidth();

        Paint p = new Paint();
        p.setColor(Color.RED);
        c.drawRect(0,0,WIDTH,HEIGHT,p);
        dibujar(c);
        invalidate();
    }

    private void dibujar(Canvas c){
        int HEIGHT = c.getHeight(),WIDTH = c.getWidth();
        for(Objeto o:objetoList){
            Paint p = new Paint();
            p.setColor(Color.YELLOW);
            //c.drawCircle(o.coordenada.x,o.coordenada.y,30,p);
            c.drawRect(o.coordenada.x,o.coordenada.y,o.coordenada.x+30,o.coordenada.y+30,p);
            //c.drawRect(o.coordenada.x,o.coordenada.y,100,100,p);
        }
    }

    public void onDragEvent(int x,int y) {
        String datos = String.valueOf(x)+","+String.valueOf(y);
        Log.d("Inicio",datos);

        puntoMedio.set(x,y);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        String datos = String.valueOf(event.getX())+","+String.valueOf(event.getY());
        puntoMedio.set(((int) event.getX()), ((int) event.getY()));

        seleccionado = obtenerTocado(new Point(((int) event.getX()), ((int) event.getY())));
        //Log.d("Seleccionado",String.valueOf(seleccionado));

        if(seleccionado <= objetoList.size()){
            objetoList.get(seleccionado).coordenada.set(((int) event.getX()), ((int) event.getY()));
        } else {
            // Detectr izq o der
            if(event.getX()-lastPosX>0 & lastPosX!=0){
                //Derecha
                for(Objeto o:objetoList){
                    o.coordenada.x +=event.getX()-lastPosX;
                }

            }else if (lastPosX!=0){
                //Izq
                for(Objeto o:objetoList){
                    o.coordenada.x -= -1*(event.getX()-lastPosX);
                }

            }
            lastPosX = (int)event.getX();
        }
        if (event.getAction() == android.view.MotionEvent.ACTION_DOWN) {
            Log.d("TouchTest", "Touch down");
        } else if (event.getAction() == android.view.MotionEvent.ACTION_UP) {
            Log.d("TouchTest", "Touch up");
            lastPosX = 0;
        }
        return super.onTouchEvent(event);
    }
    private int obtenerTocado(Point punto){
        int out = 10;
        Log.d("Seleccionado","Punto tocado:("+punto.x+","+punto.y+")");
        for(int i=0;i<objetoList.size();i++){
            Objeto o = objetoList.get(i);
            Log.d("Seleccionado","Objeto pos: ("+o.coordenada.x+","+o.coordenada.y+")");
            if(punto.x-o.coordenada.x<=o.bounds[2]&punto.x-o.coordenada.x>=o.bounds[0]){
                if(punto.y-o.coordenada.y<=o.bounds[1]){
                    if(punto.y-o.coordenada.y>=o.bounds[3]){
                        return i;
                    }
                }
            }
        }

        return out;
    }

}

Method onCreate in the MainActivity:

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        final Workbench workbench = new Workbench(this);
        setContentView(workbench);
       workbench.setOnLongClickListener(new View.OnLongClickListener() {
           @Override
           public boolean onLongClick(View view) {
                Log.d("CANV","INICIO");
               workbench.onDragEvent((int)view.getX(),(int)view.getY());
               return false;
           }
       });

    }

Object Class:

public class Objeto {
    Point coordenada = new Point();
    int bounds[] = {-50,30,50,-30};
}
    
asked by Jose Luis Montañes 01.09.2017 в 23:07
source

1 answer

2

The main problem in this is the comparison of floating numbers, it is a subject that would give a long explanation, but in your case it is unnecessary and you do not need a completely accurate precision. With this, I mean when you move the square, mix int and float to do your calculations. That loss of precision, makes the squares automatically go to the right as it enters the condition the if.

I'll make the class easier for you:

public class Workbench extends View {
public Point puntoMedio;
public float lastPosX = 0;
List<Objeto> objetoList = new ArrayList<Objeto>();
int seleccionado = 0;

public Workbench(Context context) {
    super(context);
    puntoMedio = new Point(0, 0);
    for (int i = 0; i < 5; i++) {
        Objeto o = new Objeto();
        o.coordenada.set(10, 10);
        objetoList.add(o);
    }

}

@Override
protected void onDraw(Canvas c) {
    super.onDraw(c);
    int HEIGHT = c.getHeight(), WIDTH = c.getWidth();

    Paint p = new Paint();
    p.setColor(Color.RED);
    c.drawRect(0, 0, WIDTH, HEIGHT, p);
    dibujar(c);
    invalidate();
}

private void dibujar(Canvas c) {
    int HEIGHT = c.getHeight(), WIDTH = c.getWidth();
    for (Objeto o : objetoList) {
        Paint p = new Paint();
        p.setColor(Color.YELLOW);
        //c.drawCircle(o.coordenada.x,o.coordenada.y,30,p);
        c.drawRect(o.coordenada.x, o.coordenada.y, o.coordenada.x + 30, o.coordenada.y + 30, p);
        //c.drawRect(o.coordenada.x,o.coordenada.y,100,100,p);
    }
}

public void onDragEvent(int x, int y) {
    String datos = String.valueOf(x) + "," + String.valueOf(y);
    Log.d("Inicio", datos);

    puntoMedio.set(x, y);
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    String datos = String.valueOf(event.getX()) + "," + String.valueOf(event.getY());
    puntoMedio.set(((int) event.getX()), ((int) event.getY()));

    seleccionado = obtenerTocado(new Point(((int) event.getX()), ((int) event.getY())));
    //Log.d("Seleccionado",String.valueOf(seleccionado));

    if (seleccionado <= objetoList.size()) {
        objetoList.get(seleccionado).coordenada.set(((int) event.getX()), ((int) event.getY()));
    } else {
        // Detectr izq o der
        int pos = (int) ((event.getX() - lastPosX));
        if (pos > 0 && lastPosX != 0f) {
            //Derecha
            for (Objeto o : objetoList) {
                o.coordenada.x += pos;
            }
        } else if (lastPosX != 0f) {
            //Izq
            for (Objeto o : objetoList) {
                o.coordenada.x -= -1 * pos;
            }
        }
        lastPosX = event.getX();
    }
    if (event.getAction() == android.view.MotionEvent.ACTION_DOWN) {
        Log.d("TouchTest", "Touch down");
    } else if (event.getAction() == android.view.MotionEvent.ACTION_UP) {
        Log.d("TouchTest", "Touch up");
        lastPosX = 0;
    }
    return super.onTouchEvent(event);
}

private int obtenerTocado(Point punto) {
    int out = 10;
    Log.d("Seleccionado", "Punto tocado:(" + punto.x + "," + punto.y + ")");
    for (int i = 0; i < objetoList.size(); i++) {
        Objeto o = objetoList.get(i);
        Log.d("Seleccionado", "Objeto pos: (" + o.coordenada.x + "," + o.coordenada.y + ")");
        if (punto.x - o.coordenada.x <= o.bounds[2] & punto.x - o.coordenada.x >= o.bounds[0]) {
            if (punto.y - o.coordenada.y <= o.bounds[1]) {
                if (punto.y - o.coordenada.y >= o.bounds[3]) {
                    return i;
                }
            }
        }
    }
    return out;
}
}
    
answered by 04.09.2017 / 01:37
source