Масштабирование пользовательского кода отрисовки для разных разрешений iOS - PullRequest
1 голос
/ 12 сентября 2010

Я изо всех сил пытаюсь заставить мой собственный код рисования отображаться в надлежащем масштабе для всех устройств iOS, то есть для старых iPhone, тех, которые имеют дисплеи Retina и iPad.

У меня есть подкласс UIView, в котором есть собственный класс, отображающий векторную графику. У него есть свойство scale, которое я могу установить. Я делаю масштабирование в initWithCoder, когда загружается UIView, и я сначала создаю экземпляр векторной графики. Это UIView отображается, когда пользователь нажимает кнопку на главном экране.

Сначала я попробовал это:

screenScaleFactor = 1.0;
if ([UIScreen instancesRespondToSelector:@selector(scale)]) {
    screenScaleFactor = [[UIScreen mainScreen] scale];
}
// and then I multiply stuff by screenScale

... который работал для перехода между обычными айфонами и айфонами с сетчаткой, но давился на iPad. Как я уже сказал, вы можете перейти к UIView, нажав кнопку на главном экране. При запуске на iPad, если вы отображаете UIView в 1X, он работает, но в 2X я получаю векторную графику, которая в два раза больше, чем должна быть.

Так что я попробовал это вместо:

ОБНОВЛЕНИЕ: Это тот блок, который является правильным. (с исправленной орфографией, конечно!)

screenScaleFactor = 1.0;
if ([self respondsToSelector:@selector(contentScaleFactor)]) { //EDIT: corrected misspellng.
    screenScaleFactor = (float)self.contentScaleFactor;
}
// again multiplying stuff by screenScale

, который работает как в 1, так и в 2 раза на iPad и на старых iPhone, но на сетчатке дисплея векторная графика вдвое меньше, чем должна быть.

В первом случае я запрашиваю UIScreen его свойство scale, а во втором случае я запрашиваю у родительского элемента view векторной графики его contentsScaleFactor. Похоже, что ни один из них не позволяет мне достичь желаемого результата во всех случаях.

Есть предложения?

UPDATE:

Вот метод в моем подклассе UIView (он называется GaugeView):

- (void)drawRect:(CGRect)rect {
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSaveGState(context);

    CGAffineTransform t0 = CGContextGetCTM(context);
    t0 = CGAffineTransformInvert(t0);
    CGContextConcatCTM(context, t0);

    [needle updateBox];
    [needle draw: context];
}

needle относится к классу VectorSprite, который является подклассом Sprite, который является подклассом из NSObject. Это из книги по программированию, через которую я работаю. needle имеет свойство масштаба, которое я установил.

updateBox происходит от Sprite и выглядит так:

- (void) updateBox {
    CGFloat w = width*scale;
    CGFloat h = height*scale;
    CGFloat w2 = w*0.5;
    CGFloat h2 = h*0.5;
    CGPoint origin = box.origin;
    CGSize bsize = box.size;
    CGFloat left = -kScreenHeight*0.5;
    CGFloat right = -left;
    CGFloat top = kScreenWidth*0.5;
    CGFloat bottom = -top;
    offScreen = NO;
    if (wrap) {
        if ((x+w2) < left) x = right + w2;
        else if ((x-w2) > right) x = left - w2;
        else if ((y+h2) < bottom) y = top + h2;
        else if ((y-h2) > top) y = bottom - h2; 
    }
    else {
        offScreen = 
        ((x+w2) < left) ||
        ((x-w2) > right) ||
        ((y+h2) < bottom) ||
        ((y-h2) > top);
    }
    origin.x = x-w2*scale;
    origin.y = y-h2*scale;
    bsize.width = w;
    bsize.height = h;
    box.origin = origin;
    box.size = bsize;
}    

Sprite также имеет методы draw и drawBody:

- (void) draw: (CGContextRef) context {

    CGContextSaveGState(context);

    // Position the sprite 
    CGAffineTransform t = CGAffineTransformIdentity;
    t = CGAffineTransformTranslate(t,x,y);
    t = CGAffineTransformRotate(t,rotation);
    t = CGAffineTransformScale(t,scale,scale);
    CGContextConcatCTM(context, t);

    // draw sprite body
    [self drawBody: context];

CGContextRestoreGState(context);
}

- (void) drawBody: (CGContextRef) context {
    // Draw your sprite here, centered
    // on (x,y)

    // As an example, we draw a filled white circle

    if (alpha < 0.05) return;

    CGContextBeginPath(context);
    CGContextSetRGBFillColor(context, r,g,b,alpha);
    CGContextAddEllipseInRect(context, CGRectMake(-width/2,-height/2,width,height));
    CGContextClosePath(context);
    CGContextDrawPath(context,kCGPathFill);
}    

1 Ответ

1 голос
/ 12 сентября 2010

Как именно вы визуализируете графику?

Это должно быть обработано автоматически в drawRect: (контекст, который вы получаете, должен быть уже 2x). Это также должно обрабатываться автоматически с помощью UIGraphicsBeginImageContextWithOptions(size,NO,0);, если доступно (если вам нужно использовать UIGraphicsBeginImageContext (), предположите, что масштаб равен 1). Вам не нужно беспокоиться об этом, пока вы сами не начнете рисовать растровое изображение.

Вы можете попробовать что-то вроде self.contentScaleFactor = [[UIScreen mainScreen] scale], сначала с соответствующими проверками (это может означать, что если вы отобразите это на iPad в 2 раза, вы получите графику в высоком разрешении).

По сути, нет большой разницы между iPad в режиме 2x и «дисплеем сетчатки», за исключением того, что iPad может переключаться между 1x и 2x.

Наконец, опечатка: у @selector (contentsScaleFactor) есть дополнительные s.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...