Configure un reloj analógico en hora con gestos, tocando el minutero en el sentido de las agujas del reloj o en el sentido contrario a las agujas del reloj.

StackOverflow https://stackoverflow.com//questions/24039913

Pregunta

Estoy atascado intentando crear una clase que permita a los usuarios configurar un reloj analógico en hora.Tienen que mover el minutero, no el horario, en el sentido de las agujas del reloj o en el sentido contrario a las agujas del reloj para establecer la hora actual.La manecilla de las horas se mueve sola según el progreso del minutero, pero no puedo moverla correctamente.No tiene un movimiento suave cada vez que pasa entre las doce y las seis, donde hay puntos de ángulo críticos.

Este es mi entrenamiento hasta este momento.A las doce en punto, el ángulo es igual a 0 grados, el ángulo mínimo por supuesto, y a las seis en punto, el ángulo es igual a 180 grados, el ángulo máximo.Entonces, de doce a seis (en el sentido de las agujas del reloj), tenemos ángulos positivos (0,180) y, de seis a doce (en el sentido de las agujas del reloj), tenemos ángulos negativos (-180,0).Está bien, pero si quiero calcular cuál será la posición correcta de la manecilla de la hora de acuerdo con el progreso de la manecilla de los minutos, tengo que traducir esos ángulos al rango de 0 a 360 grados.

Aquí es donde manejo los gestos:

@Override
public boolean onTouch(View v, MotionEvent event) {

    // Clock is the clock sphere and the minutes hand.
    final float xc = clock.getTranslationX() + (clock.getWidth() / 2);
    final float yc = clock.getTranslationY() + (clock.getHeight() / 2);

    final float x = event.getX();
    final float y = event.getY();

    switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN:
        clock.clearAnimation();
        mMinutesCurrAngle = Math.toDegrees(Math.atan2(x - xc, yc - y));
        break;

    case MotionEvent.ACTION_MOVE:

        /**
         * Translate angles from [-179,179] to [0,360] to be able to move 
         * hours hand properly.
         */

        // Start Angle
        mMinutesCurrAngle = set360Angle(mMinutesCurrAngle);
        mMinutesPrevAngle = mMinutesCurrAngle;

        // Finish angle
        mMinutesCurrAngle = Math.toDegrees(Math.atan2(event.getX() - xc, yc - event.getY()));
        mMinutesCurrAngle = set360Angle(mMinutesCurrAngle);

        if ((mMinutesCurrAngle > mMinutesPrevAngle)) {
            // Clockwise between 12 and 6
            mHoursCurrAngle = mLastSpinHoursAngle + (mMinutesCurrAngle / 12);
        } else if ((mMinutesCurrAngle < mMinutesPrevAngle)) {
            // counter-Clockwise between 6 and 12
            mHoursCurrAngle = mLastSpinHoursAngle + (mMinutesCurrAngle / 12);
        } else if ((mMinutesCurrAngle > mMinutesPrevAngle) && (mMinutesCurrAngle < 0)) {
            // Clockwise between 6 and 12
            mHoursCurrAngle = mLastSpinHoursAngle + (- mMinutesCurrAngle / 12);
        } else if ((mMinutesCurrAngle < mMinutesPrevAngle) && (mMinutesCurrAngle < 0)) {
            // counter-Clockwise between 6 and 12
            mHoursCurrAngle = mLastSpinHoursAngle + (mMinutesCurrAngle / 12);
        }

        newSpin();

        // Transelate angles to the original format to represent them properly.
        mMinutesPrevAngle = translate360Angle(mMinutesPrevAngle);
        mMinutesCurrAngle = translate360Angle(mMinutesCurrAngle);

        animate(clock, mMinutesPrevAngle, mMinutesCurrAngle, 0);
        animate(hour, mHoursPrevAngle, mHoursCurrAngle, 0);
        mHoursPrevAngle = mHoursCurrAngle;
        break;

    case MotionEvent.ACTION_UP:
        break;        
    }
    return true;
}

Aquí es donde traduzco los ángulos:

    /**
     * Translate angles from [-179,179] to [0,360] to be able to move 
     * hours hand properly.
     * @param minutesAngle
     * @return
     */
    private double set360Angle(double angle) {
        if (angle < 0) return (360 + angle); 
        else return angle;
    }

    /**
     * Transelate angles to the original format to represent them properly.
     * @param angle
     * @return
     */
    private double translate360Angle(double angle) {
        if (angle > 180) return (-360 + angle);
        else return angle;
    }

Y aquí es donde sé si el minutero inicia un nuevo giro:

private void newSpin() {

    if (translate360Angle(mMinutesPrevAngle) < 0 && translate360Angle(mMinutesCurrAngle) > 0) {
            // New Spin clockwise
            // I must remember hour hand angle
            mLastSpinHoursAngle = mHoursPrevAngle;
        } else if (translate360Angle(mMinutesPrevAngle) > 0 && translate360Angle(mMinutesCurrAngle) < 0) {
            // New Spin counter-clockwise
            // I must remember hour hand angle
            mLastSpinHoursAngle = mHoursPrevAngle;
        }
    }

¿Alguien puede ayudarme un poco?si alguien puede ayudarme prometo ponerle su nombre a mi primera hija por nacer…es una broma.

¿Fue útil?

Solución

Descubrí dónde estaba el problema...

El problema eran las "condiciones if" dentro del método newSpin().Aquí, antes de verificar las condiciones, traduje los ángulos al formato original (de 0 grados a 180 grados, de las doce a las seis, en el sentido de las agujas del reloj, y de -180 grados a 0 grados, de las seis a las doce). 'en el sentido de las agujas del reloj también).Entonces, en lugar de verificar si el usuario comienza un nuevo giro con el minutero, estaba sumando/restando un nuevo giro cada vez que el usuario pasa por las seis en lugar de las doce.

Entonces lo arreglé modificando esas condiciones y verificando ambos ángulos de los minutos, anterior y actual, en formato de 360 ​​grados.Ahora, si el ángulo anterior es mayor que 355 grados y el ángulo actual es menor que 5 grados, agrego un nuevo giro a mSpinNumber.Del mismo modo, si el ángulo anterior es menor que 5 grados y el ángulo actual es mayor que 355 grados, resto un giro a mSpinNumber.También cambié el nombre del método de newSpin() a calcularHourHandAngle().

private void calculateHourHandAngle() {

    if ((mMinutesPrevAngle > 355) && (mMinutesCurrAngle < 5)) {
        // New Spin clockwise
        mSpinNumber++;
    } else if ((mMinutesPrevAngle < 5) && (mMinutesCurrAngle > 355)) {
        // New Spin counter-clockwise
        mSpinNumber--;
    }
    mHoursCurrAngle = (mSpinNumber * (360/12)) + (mMinutesCurrAngle / 12);
}

También me deshago del código innecesario en el método onTouch():

@Override
public boolean onTouch(View v, MotionEvent event) {

    // Clock is the clock sphere and the minutes hand.
    final float xc = clock.getTranslationX() + (clock.getWidth() / 2);
    final float yc = clock.getTranslationY() + (clock.getHeight() / 2);

    final float x = event.getX();
    final float y = event.getY();

    switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN:
        clock.clearAnimation();
        hour.clearAnimation();
        mMinutesCurrAngle = Math.toDegrees(Math.atan2(x - xc, yc - y));
        break;

    case MotionEvent.ACTION_MOVE:

        /**
         * Translate angles from [-179,179] to [0,360] to be able to move 
         * hours hand properly.
         */

        // Start Angle
        mMinutesCurrAngle = set360Angle(mMinutesCurrAngle);
        mMinutesPrevAngle = mMinutesCurrAngle;

        // Finish angle
        mMinutesCurrAngle = Math.toDegrees(Math.atan2(event.getX() - xc, yc - event.getY()));
        mMinutesCurrAngle = set360Angle(mMinutesCurrAngle);

        calculateHourHandAngle();

        animate(clock, translate360Angle(mMinutesPrevAngle), translate360Angle(mMinutesCurrAngle), 0);
        animate(hour, mHoursPrevAngle, mHoursCurrAngle, 0);
        mHoursPrevAngle = mHoursCurrAngle;
        break;

    case MotionEvent.ACTION_UP:
        break;        
    }
    return true;
}

Ahora puedo saber qué hora configuró el usuario, porque sé la posición inicial de las manecillas del reloj, el número de giros y el ángulo de las manecillas de los minutos.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top