Установите аналоговые часы вовремя с жестами, прикосновение к по часовой стрелке или против часовой стрелки

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

Вопрос

Я застрял, пытаясь сделать класс, который позволят пользователям устанавливать аналоговые часы вовремя. Они должны перемещать минутую руку, не часу рукой, по часовой стрелке или против часовой стрелки, чтобы установить текущее время. Часовой рукой движется по всей минуту прогресса рук, но я не могу правильно перемещать часовую руку. У него нет гладкого движения, каждый раз проходит двенадцать часов и шесть часов, где есть угловые критические точки.

Это моя тренировка до этого момента. В двенадцать часов угла равна 0 градусам, минимальный угол, конечно, и в шесть часов угла составляет 180 градусов, угла максимума. Так, от двенадцати до шести (по часовой стрелке) у нас положительные углы (0,180), а от шести до двенадцати (по часовой стрелке) у нас отрицательные углы (-180,0). Это нормально, но если я хочу рассчитать то, что будет правильное положение часовой руки, согласно минуту прогресса, я должен перевести эти углы до диапазона 0-360 градусов.

Вот где я обрабатываю жесты:

@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;
}
.

Вот где я переводю углы:

    /**
     * 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;
    }
.

А вот где я знаю, если минимальная рука начинает новое вращение:

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;
        }
    }
.

Может кто-нибудь поможет мне литл? Если кто-то может помочь мне, я обещаю поставить свое имя на свою первую нерожденную дочь ... просто шучу.

Это было полезно?

Решение

Я обнаружил, где проблема была ...

Проблема была «если условия» внутри метода Newspin (). Здесь, перед проверкой условий, я перевел углы в исходный формат (от 0 градусов до 180 градусов на двенадцать часов до шести часов, по часовой стрелке, а от -180 градусов до 0 градусов, в течение шести часов до двенадцати Часы, по часовой стрелке тоже). Итак, вместо этого проверьте, начинает ли пользователь нового спина с минутой рукой, он добавил / вычитал новый спин каждый раз, когда каждый раз проходит через шесть часов в двенадцать часов.

Итак, я исправил его, изменяя эти условия, и проверяя обе углы руки, предыдущие и текущие, на формате 360 градусов. Теперь, если предыдущий угол больше 355 градусов и угла тока меньше 5 градусов, я добавляю новое вращение на Mspinnumber. Аналогичным образом, если предыдущий угол меньше 5 градусов и угла тока больше 355 градусов, я вычитаю спин к Mspinnumber. Я также изменил имя метода из Newspin () для расчетаhourandangle ().

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);
}
.

Я также избавился от ненужного кода в методе 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;
}
.

Теперь я сможен узнать, какой час установил пользователю, потому что я знаю начальную позицию рук часов, количество спинов и минутую руку.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top