Как я могу перерисовать увеличенный текст в преобразованном UIView?

В настоящее время я разрабатываю расширяющиеся сроки. Когда я увеличиваю масштаб временной шкалы, мне нужно, чтобы нарисованный текст оставался в тех же относительных положениях в UIView, на которых они нарисованы внутри UIScrollView, который обрабатывает масштабирование. (По сути, как булавки на GoogleMaps) Однако я не хочу увеличивать масштаб по вертикали, поэтому я применяю преобразование, переопределив:

- (void)setTransform:(CGAffineTransform)newValue;
{
    newValue.d = 1.0;
    [super setTransform:newValue];
}

Это отлично работает, удерживая временную шкалу фиксированной по вертикали и позволяя ей расширяться по горизонтали. Однако я рисую свои текстовые метки как таковые в методе, вызываемом во время setNeedsDisplay:

for (int i = 1; i < 11; i++)
{
    CGRect newFrame = CGRectMake(i * (512.0/11.0) - (512.0/11.0/2.0), self.frame.size.height - 16.0, 512.0/11.0, 32.0);
    NSString *label = [NSString stringWithFormat:@"%d", i+1];
    [label drawInRect:newFrame withFont:[UIFont systemFontOfSize:14.0]];
}

Это рисует мой текст в правильной позиции в режиме прокрутки и почти отлично работает. Однако из-за моего преобразования, чтобы сохранить статическое масштабирование по вертикали, текст расширяется по горизонтали, а не по вертикали, и поэтому растягивается ужасно. Кажется, мне не удается перерисовать текст с правильным соотношением сторон. Использование UILabels работает, однако я собираюсь отрисовывать и обрабатывать более 1000 таких меток, поэтому я бы предпочел рисовать статические изображения в drawRect или чем-то подобном.

Я попытался изменить CGRect, в котором я рисую текст (стоило попробовать), и применение CGAffineTransformIdentity невозможно, потому что я уже трансформирую представление, чтобы оно не увеличивалось по вертикали. Я также пробовал рисовать текст в различных представлениях, но безрезультатно, и, опять же, я бы предпочел не заполнять непристойное количество объектов, если я могу этого избежать.

Спасибо за любую помощь!


person JKomusin    schedule 07.04.2011    source источник
comment
Все еще озадаченный этим. В основном альтернативный способ масштабирования только по горизонтали. Я попытался установить CGContextSetTextMatrix со значением d, равным -1, чтобы отменить мое преобразование, чтобы оно продолжало масштабироваться по горизонтали, но это не помогло / не сработало (возможно, я сделал это неправильно, idk). Если кто-то знает о матрицах преобразований больше, чем я, и может помочь на этом пути, я был бы чрезвычайно признателен.   -  person JKomusin    schedule 11.04.2011


Ответы (1)


Вместо применения преобразования внутри метода setTransform: я перехватываю масштаб, в котором оно преобразуется, и изменяю размер кадра трансформируемого представления. Код (примерно) следующий:

- (void)setTransform:(CGAffineTransform)newValue;
{   
    // The 'a' value of the transform is the transform's new scale of the view, which is reset after the zooming action completes
    //  newZoomScale should therefore be kept while zooming, and then zoomScale should be updated upon completion
    _newZoomScale = _zoomScale * newValue.a;

    if (_newZoomScale < 1.0)
        _newZoomScale = 1.0;

    // Resize self
    self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, _originalFrame.size.width * _newZoomScale, self.frame.size.height);
}

Как упоминалось в комментариях, значение преобразования CGAffineTransform сбрасывается каждый раз, когда происходит новое действие масштабирования (однако оно сохраняется на время действия масштабирования). Итак, я сохраняю две переменные экземпляра в моем подклассе UIView (не уверен, что это невероятно элегантно, но это не безумно ужасно): исходный кадр, в котором был создан экземпляр представления, и «текущий» масштаб масштабирования представления (до текущее действие масштабирования).

_originalFrame - это то, на что ссылаются, чтобы определить правильный размер теперь увеличенного кадра, а _zoomScale (масштаб вида до текущего действия масштабирования) устанавливается на значение _newZoomScale, когда обратный вызов didFinishZooming вызывается в UIScrollView, содержащий этот UIView.

Все это позволяет не преобразовывать систему координат UIView во время масштабирования, поэтому текст и т. Д. Можно рисовать на виде без каких-либо искажений. Оглядываясь назад на это решение, я готов поспорить, что вы также можете учесть преобразование и рисование на основе растянутой системы координат. Не уверен, что более эффективно. Я немного обеспокоился тем, что не вызвал super в setTransform:, но я не заметил каких-либо побочных эффектов примерно через 6 месяцев использования и разработки.

person JKomusin    schedule 01.03.2012