Страницы

Поиск по вопросам

вторник, 10 декабря 2019 г.

Циклическая прокрутка шкалы

#android #customview


Не могу разобраться, как можно реализовать циклическую прокрутку шкалы.
Рисую ее в customview:

public void onDraw(Canvas canvas){
startingPoint = mainPoint;
counter = 0;
for (int i = 1;; i++) {
    if (startingPoint > screenSize) {
        break;
    }

    if(i % 4 == 0) {
        size = scaleHeight / 4;
        counter = counter + 1;
    } else {
        if(i % 2 == 0) {
            size = scaleHeight / 8;
        } else {
            size = scaleHeight / 16;
        }
    }
    canvas.drawLine(startingPoint, endPoint - size, startingPoint, endPoint, rulerPaint);

    if (i % 4 == 0) {
        String c = Integer.toString(counter);
        canvas.drawText(c, startingPoint, endPoint - (size + 20), textPaint);
    }

    startingPoint = startingPoint + pxmm;
}


Ограничиваю ее до одиннадцати длинных делений:


Но мне нужна бесконечная шкала:



Допустим, можно убрать проверку значения counter в onDraw методе, но как это скажется
на производительности? Даже если ставлю его значение 1000, уже заметны "подлагивания"
при скроллинге.
Вот мой onScroll:

public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
        mainPoint = mainPoint - distanceX;
        invalidate();
        return true;
}


И onMeasure:

protected void onMeasure(int w, int h) {
        DisplayMetrics metrics = new DisplayMetrics();    ((Activity)getContext()).getWindowManager().getDefaultDisplay().getMetrics(metrics);
        h = metrics.heightPixels / 5;
        w = metrics.widthPixels;

        setMeasuredDimension(w, h);

        scaleHeight = h;
        scaleWidth = w;
        screenSize = w;
        endPoint = h;
        midScreenPoint = w / 2;
        pxmm = screenSize / 28;
    }


Каким образом реализуются подобные задачи? 
    


Ответы

Ответ 1



Надо рисовать шкалу от начала экрана до его конца. Т.е. цикл должен быть не по шкале, а по ширине экрана. А в цикле уже вести счетчик по шкале, как только он достигнет 11, обнулять. Такой подход позволит легко рисовать и шкалу со смещением, просто присваиваете счетчику шкалы это смещение вначале и готово. Скроллинг будет не нужным.

Ответ 2



В текущей реализации происходит следующее: mainPoint инициализируется нулем. в onScroll mainPoint изменяется на значение -distanceX, соответсвенно при скролле в положительное направление по оси X значение mainPoint будет уменьшатся. То есть в какой-то момент значение mainPoint будет предположим -1000. Но при этом значение, возвращаемое из getScrollX() будет как раз таки 1000, поскольку View будет проскроллено как раз на это значение. Метод onDraw считает, что координаты View следующие: (l, t, r, b) == (0, 0, getMeasuredWidth(), getMeasuredHeight()) и цикл в onDraw будет отрисовывать линейку от значения -1000 до getMeasuredWidth() каждый раз - из за этого и возникают лаги и подергивания. Чтобы их не было нужно отрисовывать линейку не от -1000, а от 0. Собственно видимо это и имел в виду Евгений. Как можно исправить: В onDraw получать значение из getScrollX()(либо брать тот же mainPoint) и рассчитывать метку линейки в нулевой координате. В моем примере с 1000 и значением pxmm предположим 24 получается, что в нулевой координате метки линейки будет 41,6(6). Соответственно метка линейки 41 и 41,5 будут за пределом видимости, а значение 42 как раз будет отрисовано со сдвигом 42 * 24 - 1000 = 8 пикселов от левого края экрана. Единственное что - надо отрисовывать немного не с нуля, а с отрицательного значения, потому что метка может быть за пределами экрана, а сама цифра может частично уже попадать на экран. В принципе, чтобы не особо заморачиваться, можно начинать отрисовывать со значения 41 * 24 - 1000 = -16 пикселов, то есть со сдвигом на одно деление линейки в левую сторону экрана.

Комментариев нет:

Отправить комментарий