2016-04-17 6 views
3

настоящее время у меня этот фрагмент кода, генерирующий тиков вокруг внешней и андроида износа циферблатКак нарисовать часовую «клещи» на квадратные часы?

float innerMainTickRadius = mCenterX - 35; 
      for(int tickIndex = 0; tickIndex < 12; tickIndex++) { 
       float tickRot = (float) (tickIndex * Math.PI * 2/12); 
       float innerX = (float) Math.sin(tickRot) * innerMainTickRadius; 
       float innerY = (float) -Math.cos(tickRot) * innerMainTickRadius; 
       float outerX = (float) Math.sin(tickRot) * mCenterX; 
       float outerY = (float) -Math.cos(tickRot) * mCenterX; 
       canvas.drawLine(mCenterX + innerX, mCenterY + innerY, mCenterX + outerX, mCenterY + outerY, mTickPaint); 
      } 

который генерирует тиков хорошо на круглом, но на циферблат квадрата получается, как это: Round ticks on Square , но я бы чтобы они не были круглыми, но вместо этого соответствовали форме немного более подходящим образом, например: Square watchface

Есть ли стандартный способ сделать это? Я предполагаю, что снова не могу использовать тригг ...

ответ

3

Конечно, вы используете геометрию и триггер. Например, любая строка, которую вы положили на циферблат, вы хотите указать на центр, так что одна часть будет данной (x, y), а другая будет arctan2 (cy-y, cx-x), дающая вам угол от (cx, cy), то просто нарисуйте линию в направлении центра заданной длины r, рисуя линию от x, y до cos (угол) * r, sin (угол) * r ,

Однако, учитывая образ вашего образца, вы можете рисовать линию от x, y до x + r, y, а затем поворачивать холст под углом, чтобы вы могли нарисовать эти числа, как это показано. Обязательно сделайте canvas.save(), прежде чем настраивать матрицу холста и canvas.restore() после настройки.

Это оставляет математику любой формы, из которой вы хотите нарисовать свои тики и положения на ней. Вы можете сделать это в пределах Пути. Поэтому определите путь для закругленного прямоугольника, а затем используйте класс PathMeasure, чтобы получить getPosTan(), а затем проигнорируйте касательную и просто используйте позицию, в которой вы можете найти свою позицию вокруг закругленного прямоугольника. Это или просто вычислить эти позиции в качестве позиций через сегмент линии или секцию безье в зависимости от принятой формы.

Например:

static final int TICKS = 12; 
static final float TICKLENGTH = 20; 

В процедуре жеребьевки,

float left = cx - 50; 
    float top = cy - 50; 
    float right = cx + 50; 
    float bottom = cy + 50; 
    float ry = 20; 
    float rx = 20; 
    float width = right-left; 
    float height = bottom-top; 
    Path path = new Path(); 
    path.moveTo(right, top + ry); 
    path.rQuadTo(0, -ry, -rx, -ry); 
    path.rLineTo(-(width - (2 * rx)), 0); 
    path.rQuadTo(-rx, 0, -rx, ry); 
    path.rLineTo(0, (height - (2 * ry))); 
    path.rQuadTo(0, ry, rx, ry); 
    path.rLineTo((width - (2 * rx)), 0); 
    path.rQuadTo(rx, 0, rx, -ry); 
    path.rLineTo(0, -(height - (2 * ry))); 
    path.close(); 

    PathMeasure pathMeasure = new PathMeasure(); 
    pathMeasure.setPath(path,true); 
    float length = pathMeasure.getLength(); 
    float[] pos = new float[2]; 
    float r = TICKLENGTH; 
    for (int i = 0; i < TICKS; i++) { 
     pathMeasure.getPosTan(i * (length/TICKS),pos,null); 
     double angle = Math.atan2(cy - pos[1], cx - pos[0]); //yes, y then x. 
     double cos = Math.cos(angle); 
     double sin = Math.sin(angle); 
     canvas.drawLine(pos[0], pos[1], (float)(pos[0] + cos * r), (float)(pos[1] + sin * r), paint); 
    } 

Правда это выглядит следующим образом:

clock picture

Так это заняло бы гораздо больше работы, чтобы получить он выглядит как ваш образ. Но это вполне выполнимо. Трюк с мерой пути будет работать для любой формы. Я избегал использования path.addRoundRect из-за ограничения Lollipop +. Вы можете увидеть мой ответ на этот вопрос here. И другие ответы, которые достаточно хороши для рисования округлой формы прямоугольника. Вы можете, если хотите написать функцию конверта, просто масштабируйте свое текущее изображение на конверте прямоугольника в соответствии с коэффициентом t, так как оно идет круглосуточно.

+0

Если у вас есть этот макет в векторе, вы можете просто использовать векторную графику и взорвать эту иконку, которая будет большой во время розыгрыша.Нарисуйте то, что вы хотите, в SVG, превратите его в векторную графику Android и просто нарисуйте выделение на холст, оно будет довольно маленьким и недвусмысленным. – Tatarize

+0

Это на самом деле неплохая идея. Я использовал ваш первый ответ, и он отлично работал в конце с небольшим количеством настроек – nuggetbram

1

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

theta(i)=arctan(y_pos(i)/x_pos(i)) 

Предполагая, что центр имеет координаты (0,0). В этом случае вам нужно только сохранить позиции для 8 последовательных тиков, потому что лицо периодическое каждые 90 градусов и симметричное относительно диагоналей.