CALayer cornerRadius няма ефект върху 4" устройство (симулатор)

Работя върху динамично, програмно оформление на изглед за 3,5" устройства, както и за 4" устройства. Като такъв, който работи добре. Но искам заоблени ъгли, така че изображенията ми да изглеждат като карти за игра. И получавам заоблени ъгли, добре показани в 3,5-инчови устройства на симулатора за симулирани iOS 6.1 и 7. Но когато избера iPhone retina 4 инча на 6.1 или 7, тогава UIImage в UIImageView се показва напълно. Работи добре на симулирани iPad устройства (в режим на симулация на iPhone - това е приложение само за iPhone).

За днес нямам 4" устройство с мен, за да го тествам. Мога да тествам на устройство през следващата седмица.

Тук е съответният код:

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    self.imageV.image = self.image; // The image property was set by the caller.

    // Layout imageV within self.view with a margin of MARGIN
    self.imageV.frame = CGRectMake(self.view.frame.origin.x + MARGIN, self.view.frame.origin.y + MARGIN, self.view.frame.size.width - 2 * MARGIN, self.view.frame.size.height - 2 * MARGIN);

    // set the raidus and the mask to follow the rounded corners.
    self.imageV.layer.cornerRadius = CORNER_RADIUS;
    self.imageV.layer.masksToBounds = YES;
}

BTW: CORNER_RADIUS е 18, а MARGIN е 15. Промяната на тези стойности няма ефект върху проблема.

АКТУАЛИЗАЦИЯ: Благодарение на Мат разбрах, че проблемът изчезва, когато създам UIImageView програмно. Това е наистина хубаво решение плюс сочи в правилната посока, предполагам, но не е решение. Някакви идеи каква настройка в редактора на сценария може да е причинила проблема? Доколкото мога да видя, автоматичното оформление е деактивирано за всички контролери за изглед в тази сценария.

3.5 устройство4 устройство


person Hermann Klecker    schedule 30.03.2014    source източник
comment
Очевидно няма нищо лошо в кода ви, така че трябва да вярвам, че тук става нещо друго.   -  person matt    schedule 30.03.2014
comment
Нека само да проверя няколко неща с вас. Къде се създава изгледът на изображението? Ако е в разкадровката/перото, има ли включено автоматично оформление? Ако е така, имате проблем, защото не можете да зададете рамката директно по този начин.   -  person matt    schedule 30.03.2014
comment
Освен това, когато кажете frame, трябва да кажете bounds - рамката на изгледа на изображението е позиционирана спрямо границите на self.view, а не неговата рамка.   -  person matt    schedule 30.03.2014
comment
Въпреки това, след като поправих всичко това, не мога да възпроизведа проблема, така че предполагам, че имате друг код, който не показвате, който обърква нещата по някакъв начин.   -  person matt    schedule 30.03.2014
comment
Благодаря @matt, UIImageView се създава в сценарий, където автоматичното оформление е деактивирано. Прав си за рамката и границите. Въпреки това, тъй като self.view се намира на (0/0), се случва да работи. Мислите ли, че това е свързано с проблема със заоблените ъгли?   -  person Hermann Klecker    schedule 30.03.2014
comment
Не е мой проект. Просто добавям гъвкавото оформление за различните размери на екрана на iPhone. Така че може да сте прави, че има нещо друго... Радвам се да споделя повече код и да проверя настройките в IB/Storyboard, но ще бъда благодарен за съвет какво да гледам.   -  person Hermann Klecker    schedule 30.03.2014
comment
Не, сигурен съм, че не е свързано. :) Може да има проблем с позиционирането на рамката, но това няма да повлияе на закръгляването!   -  person matt    schedule 30.03.2014
comment
Забелязвам друга разлика във вашите екранни снимки: на втората горната част е избутана много надолу, сякаш има навигационна лента, която не се показва. Това може да е УЛИКА!   -  person matt    schedule 30.03.2014


Отговори (2)


Отговорът е лесен. Кодът проработи. Той добави заоблени ъгли към обекта UIImageView и maskToBounds работи добре.

Но действителното показано изображение е по-малко. Използвах AspectFit като режим, за да гарантирам, че действителното изображение не се притиска, а се показва в оригиналното си съотношение на аспектите. Поради по-дългото оформление на размерите на iPhone5 изображението запълваше само част от собствения UIImageView. Промених цвета на фона на сив за екранната снимка и сега става ясно.

Така че решението ще бъде, че ще трябва да изчисля правилния размер на изгледа на изображението, така че да съответства точно на размера на мащабираното изображение. След това трябва да работи.

(Ще актуализирам този отговор, когато приключи).

въведете описание на изображението тук

Актуализация: това е, което най-накрая направих: премахнах UIImageView от Storyboard и се справям с него програмно.

Не се обърквайте от сложността. Добавих друг изглед само за да хвърля сянка, въпреки че това не е свързано с първоначалния въпрос. Сянката, която така или иначе исках да добавя. И се оказа, че сянката на CALayer и masksToBounds=YES всъщност не са съгласни. Ето защо добавих обикновен UIView, който се намира между изгледа на картата и изгледа на фона.

И накрая, това е толкова неприятно за показване на просто правоъгълно изображение, че мисля, че просто подкласиране на UIView и изчертаване на всичко с openGL или така директно в CALayer вероятно би било много по-лесно. :-)

Както и да е, това е моят код:

- (void)viewDidLoad {
    [super viewDidLoad];

    self.state = @0;

    // Create an image view to carry the image with round rects
    // and create a regular view to create the shadow.
    // Add the shadow view first so that it appears behind
    // the actual image view.

    // Explanation: We need a separate view for the shadow with the same
    // dimenstions as the imageView. This is because the imageView's image
    // is rectangular and will only be clipped to round rects when the
    // property masksToBounds is set to YES. But this setting will also
    // clip away any shadow that the imageView's layer may have.
    // Therfore we add a separate mainly empty UIView just behind the
    // UIImageview to throw the shadow.


    self.shadowV = [[UIView alloc] init];
    self.imageV = [[UIImageView alloc] initWithImage:self.image];
    [self.view addSubview:self.shadowV];
    [self.shadowV addSubview:self.imageV];

    // set the raidus and the mask to follow the rounded corners.
    [self.imageV.layer setCornerRadius:CORNER_RADIUS];
    [self.imageV.layer setMasksToBounds:YES];
    [self.imageV setContentMode:UIViewContentModeScaleAspectFit];

    // set the shadows properties
    [self.shadowV.layer setShadowColor:[UIColor blackColor].CGColor];
    [self.shadowV.layer setShadowOpacity:0.4];
    [self.shadowV.layer setShadowRadius:3.0];
    [self.shadowV.layer setShadowOffset:CGSizeMake(SHADOW_OFFSET, SHADOW_OFFSET)];
    [self.shadowV.layer setCornerRadius:CORNER_RADIUS];
    [self.shadowV setBackgroundColor:[UIColor whiteColor]];   // The view needs to have some content. Otherwise it is not displayed at all, not even its shadow.

}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    // Just to be save
    if (!self.image) {
        return;
    }

    self.imageV.image = self.image; // The image property was set by the caller.

    // Layout imageV within self.view with a margin of MARGIN
    self.imageV.frame = CGRectMake(MARGIN, MARGIN, self.view.bounds.size.width - 2 * MARGIN, self.view.bounds.size.height - 2 * MARGIN);


    // Calculate the size and position of the image and set the image view to
    // the same dimensions
    // This works under the assumption, that the image content mode is aspectFit.
    // Well, as we are doing so much of the layout manually, it would work with a number of content modes. :-)

    float imageWidth, imageHeight;
    float heightWidthRatioImageView     = self.view.frame.size.height / self.view.frame.size.width;
    float heightWidthRatioImage         = self.image.size.height / self.image.size.width;

    if (heightWidthRatioImageView > heightWidthRatioImage) {
        // The ImageView is "higher" than the image itself.
        // --> The image width is set to the imageView width and its height is scaled accordingly.
        imageWidth  = self.imageV.frame.size.width;
        imageHeight = imageWidth * heightWidthRatioImage;
    } else {
        // The ImageView is "wider" than the image itself.
        // --> The image height is set to the imageView height and its width is scaled accordingly.
        imageHeight = self.imageV.frame.size.height;
        imageWidth  = imageHeight / heightWidthRatioImage;
    }

    // Layout imageView and ShadowView accordingly.
    CGRect imageRect =CGRectMake((self.view.bounds.size.width - imageWidth) / 2,
                                 (self.view.bounds.size.height - imageHeight) / 2,
                                 imageWidth, imageHeight);
    [self.shadowV setFrame:imageRect];
    [self.imageV setFrame:CGRectMake(0.0f, 0.0f, imageWidth, imageHeight)]; // Origin is (0,0) because it overlaps its superview which just throws the shadow.

}

И ето как изглежда най-накрая: въведете описание на изображението туквъведете описание на изображението тук

person Hermann Klecker    schedule 30.03.2014
comment
И всъщност, ако погледнете това, което продължавах да казвам за оформлението - защо във втория кадър изображението е толкова по-ниско отгоре и по-високо отдолу - ще видите, че тази разлика беше улика по тези линии! Много добре. - Не го реших обаче; Мислех да ви посъветвам да дадете фонов цвят на изгледа на изображението или да проверите режима на съдържание, но никога не го казах. - person matt; 31.03.2014
comment
Още веднъж много благодаря. Ти ме тласна в правилната посока. Само в случай, че някой друг се сблъска с подобен проблем, ще разширя отговора си с окончателния код и екранните снимки. - person Hermann Klecker; 31.03.2014
comment
Можете дори да маркирате собствения си отговор след няколко дни, само за да покажете, че проблемът е решен. - person matt; 31.03.2014

Проблемът се дължи на някакъв проблем с код или конфигурация, за който не сте ни казали. Доказателство: Пуснах следното и работи добре. Обърнете внимание, че създавам изгледа на изображението в код (за да избегна проблема с автоматичното оформление) и поправих объркването ви с рамка/граници и че пропуснах вашия self.image, но нищо от това не е наистина подходящо за проблема, който виждате:

#define CORNER_RADIUS 18
#define MARGIN 15
- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    self.imageV = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"im"]];
    [self.view addSubview:self.imageV];
    // Layout imageV within self.view with a margin of MARGIN
    self.imageV.frame = CGRectMake(self.view.bounds.origin.x + MARGIN, self.view.bounds.origin.y + MARGIN, self.view.bounds.size.width - 2 * MARGIN, self.view.bounds.size.height - 2 * MARGIN);
    // set the raidus and the mask to follow the rounded corners.
    self.imageV.layer.cornerRadius = CORNER_RADIUS;
    self.imageV.layer.masksToBounds = YES;
}

Работи добре (и можете да докажете това на себе си). Ето екранна снимка на 4-инчовия симулатор:

въведете описание на изображението тук

Следователно проблемът е извън кода, който цитирате във вашия въпрос, и не може да бъде анализиран без допълнителна информация.

person matt    schedule 30.03.2014
comment
Като цяло винаги правете (когато възникнат тези загадъчни проблеми) това, което правя аз тук: направете малък проект само с кода, който изглежда странно, и нищо повече. Ако, както тук, работи добре, това доказва, че проблемът е другаде. Отнема само момент и е ценен аналитичен инструмент. - person matt; 30.03.2014
comment
Добре, благодаря ти досега. Проблемът трябва да е някъде в сценария, където не го виждам. Създадох изгледа на изображението програмно и сега работи. Ако ставаше въпрос само за преодоляване, тогава съветът ви беше полезен. Но проектът е от младши/студент и бих искал да разбера какво всъщност е причинило проблема. Но вие сочите в правилната посока. Гласувайте „за“ засега, приемането ще последва, освен ако не дойде отговор, който го стеснява още повече. - person Hermann Klecker; 30.03.2014
comment
Има ли няколко сценария? - person matt; 30.03.2014
comment
Има само един. Това е доста малък проект. Една от многобройните scrum покер игри. Основният изглед е контролер за изглед на раздели, след което един от неговите контролери за навигация идва с прав изглед на колекция в него, показващ всички карти. Когато е избрана карта, тогава се появява контролер за подробен изглед, показващ същата карта. Изобщо нищо сложно. - person Hermann Klecker; 30.03.2014
comment
Добре, но защо първата ви снимка на екрана не показва място в горната част за лентата за навигация и никакво място в долната част за лентата с раздели, а втората показва? Изглежда, че достигате до тези екранни снимки по два много различни начина/контекста. Това ме кара да се съмнявам във валидността на теста във вашата страна. - person matt; 30.03.2014
comment
Хм... Ще проверя за навигационната лента. Може да се скрие. Двете екранни снимки може да идват от симулирани устройства 3.5 и 4. 5-те устройства показват свободно пространство в горната и долната част на изгледа. Засега това е предвидено. - person Hermann Klecker; 30.03.2014
comment
За теста току-що промених режима на iPhone Simulator, стартирах отново идентичен код и направих екранните снимки. - person Hermann Klecker; 30.03.2014
comment
Най-накрая го намерих. Това е доста смущаващо. Просто, но просто не го видях. Ще публикувам отговора след минута. - person Hermann Klecker; 31.03.2014