Is it possible to create a properly aligned UIImageView that has a resizable image?
I tried everything (e.g. images power of two, etc) and cannot make it work.
The coordinates of the UIImageView are:
po _Background
(UIImageView *) $1 = 0x14c42bd0
<UIImageView: 0x14c42bd0;
frame = (16 38; 992 672);
opaque = NO;
autoresize = LM+RM+TM+BM;
userInteractionEnabled = NO;
layer = <CALayer: 0x14c42ba0>> - (null)
The UIImage itself is 96x96 (retina, i.e. png is 192x192 with a scale of 2). The resizable UIImage is created using:
UIEdgeInsets edgeInsets = UIEdgeInsetsMake(32, 32, 32, 32);
UIImage* resizableImage = [originalImage resizableImageWithCapInsets:edgeInsets];
[_Background setImage:resizableImage];
When turning on 'Color misaligned images' in the simulator the UIImageView _Background is highlighted with yellow. Removing its UIImage in the debugger:
[_Background setImage:nil];
removes the yellow highlight, i.e. no image -> no mis-alignment.
Anyone knows what is going on and how I can make sure it aligns?
thanks.
According to this answer: What does yellow tinting represent when using "color misaligned images" on iPhone/iOS, the yellow highlight indicates the image is stretched. Since that's what you're asking for with the resizable image, it makes sense that it's always the case.
Related
My app sends a GET request to google to attain certain user information. One piece of crucial returned data is a users picture which is placed inside a UIImageView that is always exactly (100, 100) then redrawn to create a round mask for this imageView. These pictures come from different sources and thus always have different aspect ratios. Some have a smaller width compared to their height, sometimes it's vice-versa. This results in the image looking compressed. I've tried things such as the following (none of them worked):
_personImage.layer.masksToBounds = YES;
_personImage.layer.borderWidth = 0;
_personImage.contentMode = UIViewContentModeScaleAspectFit;
_personImage.clipsToBounds = YES;
Here is the code I use to redraw my images (it was attained from user fnc12 as the third answer in Making a UIImage to a circle form):
/** Returns a redrawn image that had a circular mask created for the inputted image. */
-(UIImage *)roundedRectImageFromImage:(UIImage *)image size:(CGSize)imageSize withCornerRadius:(float)cornerRadius
{
UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0.0); //<== Notice 0.0 as third scale parameter. It is important because default draw scale ≠ 1.0. Try 1.0 - it will draw an ugly image...
CGRect bounds = (CGRect){CGPointZero, imageSize};
[[UIBezierPath bezierPathWithRoundedRect:bounds cornerRadius:cornerRadius] addClip];
[image drawInRect:bounds];
UIImage *finalImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return finalImage;
}
This method is always called like so:
[_personImage setImage:[self roundedRectImageFromImage:image size:CGSizeMake(_personImage.frame.size.width, _personImage.frame.size.height) withCornerRadius:_personImage.frame.size.width/2]];
So I end up having a perfectly round image but the image it self isn't right aspect-wise. Please help.
P.S. Here's how images look when their width is roughly 70% that of their height before the redrawing of the image to create a round mask:
Hello dear friend there!
Here is my version that works:
Code in ViewController:
[self.profilePhotoImageView setContentMode:UIViewContentModeCenter];
[self.profilePhotoImageView setContentMode:UIViewContentModeScaleAspectFill];
[CALayer roundView:self.profilePhotoImageView];
roundView function in My CALayer+Additions class:
+(void)roundView:(UIView*)view{
CALayer *viewLayer = view.layer;
[viewLayer setCornerRadius:view.frame.size.width/2];
[viewLayer setBorderWidth:0];
[viewLayer setMasksToBounds:YES];
}
May be you should try to change your way to create rounded ImageView using my version that create rounded ImageView by modifying ImageView's view layer . Hope it helps.
To maintain aspect ratio of UIImageView, after setting image use following line of code.
[_personImage setContentMode:UIViewContentModeScaleAspectFill];
For detailed description follow reference link:
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIImageView_Class/
I set Custom navigationBar by KVO in iOS8,and the custom navigationBar setBackgroundImage.
I found that the viewContoller.view.frame.origin.y is 64 and viewController is Navigation's rootViewController.
why viewContoller.view.frame.origin.y is 64 in iOS 8?
the following is demo code:
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
UINavigationBar *temp = [[UINavigationBar alloc]init];
[temp setBackgroundImage:[UIImage imageNamed:#"navbar_bg"] forBarMetrics:UIBarMetricsDefault];
[self.navigationController setValue:temp forKey:#"navigationBar"];
}
- (void)viewDidAppear:(BOOL)animated
{
NSLog(#"view : %#",self.view); // print :<UIView: 0x7ff8fa72cfa0; frame = (0 64; 375 603); autoresize = RM+BM; layer = <CALayer: 0x7ff8fa72b2b0>>
}
If I cancel [temp setBackgroundImage:[UIImage imageNamed:#"navbar_bg"] forBarMetrics:UIBarMetricsDefault]; , the view.origin.y is 0 correctly.
what i should do correctly to set custom navigationBar which setBackgroundImage and keep self.view.orgin is (0,0)?
Please check the image assets.
The image "navbar_bg#2x" should exists in the assets, If you are tested on device or simulators ,which has UIKit Scale factor 2.0, such as a iPhone 8 .
The image "navbar_bg#3x" should exists in the assets, if tested on iPhone 8 Plus. And so on.
It should be OK, according to Apple's Demo Code Customizing Your App’s Navigation Bar.
Two cases , your issue happens.
In my case , It does not work, when converting color to image.
Firstly I thought it is image size issue.
Accoring to Debug View Hierarchy, I got the BackgroundImageView's size, 414 X 88.Tested in simulator of iPhone XR.
When debugging, I think maybe the image should be smaller than imageView'size.
Still not work, after many times of adjusting the image size.
the code of converting color to image:
public static func color(_ color: UIColor, width w: CGFloat, height h: CGFloat) -> UIImage {
let rect = CGRect(x: 0.0, y: 0.0, width: w, height: h)
UIGraphicsBeginImageContextWithOptions(rect.size, false, UIScreen.main.scale)
let ctx = UIGraphicsGetCurrentContext()
ctx?.setFillColor(color.cgColor)
ctx?.fill(rect)
var image = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
let imageData = UIImageJPEGRepresentation(image, 1.0)!
image = UIImage(data: imageData)!
return image
}
case two: image#2x ("navbar_bg#2x") doesn't exist in assets when tested in simulator of iPhone XR, which has UIKit Scale factor 2.0.
Then it doesn't work either in my experiment.
You can set title of navigationController.navigationItem instead of setting up UINavigationBar and providing with KVO.
- (void)viewDidLoad {
[super viewDidLoad];
UIImageView *img = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"navbar_bg"]];
//Here you can create your own Custom View and provide as title of self.navigationController.navigationItem
[self.navigationController.navigationItem setTitleView:img];
}
- (void)viewDidAppear:(BOOL)animated
{
NSLog(#"view : %#",self.view); // print :<UIView: 0x79ea0a30; frame = (0 0; 375 603); autoresize = W+H; layer = <CALayer: 0x79ea0ac0>>
}
I did an experiment too.
I think the problem is caused by color space.
According to the answer above, I created three images of white with imageMagick.
And use white image#2x with simulator iPhone XR .
The issue happens too.
The example image of Apple's Demo Code Customizing Your App’s Navigation Bar is of SRBG, my color image is simply gray scale.
I think it is the difference.
from image magick community
-colorspace changes the way the image is stored in memory
-set colorspace just sets the colorsapce of the image without conversion
Many image formats (like JPG) do not use difference colorspaces
without using some time of color profile, as such the image is
converted back to RGB colorspace unless a color profile has been
defined.
That is why you don't see a difference. It is only different IN
MEMORY!
Maybe iOS did some optimization because of this.
I am using the UIImageView in my xib. App is designed for multi device without auto layout. It means I am using autoresizing.What I want to do is, only my UIImageView should autoresize not my Image inside the UIImageView, but unfortunately my image also getting stretched with UIImageView. I have tried the different ways but could not get success. Changed the content mode also but didn't work for me.
Try this...
//set content mode
self.imageView.contentMode = UIViewContentModeScaleAspectFit;
//clear background color
self.imageView.backgroundColor=[UIColor clearColor];
UIViewContentMode
UIViewContentModeScaleToFill,
UIViewContentModeScaleAspectFit, // contents scaled to fit with fixed aspect. remainder is transparent
UIViewContentModeScaleAspectFill, // contents scaled to fill with fixed aspect. some portion of content may be clipped.
UIViewContentModeRedraw, // redraw on bounds change (calls -setNeedsDisplay)
UIViewContentModeCenter, // contents remain same size. positioned adjusted.
UIViewContentModeTop,
UIViewContentModeBottom,
UIViewContentModeLeft,
UIViewContentModeRight,
UIViewContentModeTopLeft,
UIViewContentModeTopRight,
UIViewContentModeBottomLeft,
UIViewContentModeBottomRight,
Don't add the UIImage to the UIImageView whose size is going to change. Add it to another UIImageView and make this second UIImageView a subview of the first UIImageView.
UIImage *exampleImage = [UIImage imageWithContentsOfFile:filePath];
UIImageView *variableImageView = [[UIImageView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
CGFloat imageX = (variableImageView.bounds.size.width - exampleImage.size.width) / 2;
CGFLoat imageY = (variableImageView.bounds.size.height - exampleImage.size.height) / 2;
UIImageView *helperImageView = [[UIImageView alloc] initWithFrame:CGRectMake(imageX, imageY, exampleImage.size.width, exampleImage.size.height)];
helperImageView.image = exampleImage;
helperImageView.contentMode = UIViewContentModeScaleAspectFit;
[self.view addSubview:variableImageView];
[variableImageView addSubview:helperImageView];
I hope this helps.
This how I add an image:
UIImageView *imageHolder = [[UIImageView alloc] initWithFrame:
CGRectMake((self.view.frame.size.width/2) - (290/2),(self.view.frame.size.height) - (140 * 1.8), 290, 140)];
UIImage *image = [UIImage imageNamed:#"no-pins.png"];
imageHolder.image = image;
imageHolder.contentMode = UIViewContentModeScaleAspectFit;
// optional:
// [imageHolder sizeToFit];
[self.view addSubview:imageHolder];
The size of the image (retina version) is exactly the same size as in CGRectMake above. However the image is a little blurred. I only can reduce the blur when I edit the image and give it a higher resolution in photoshop.
But images that I add through storyboard are all fine in quality. Any ideas what might be wrong?
For retina graphics, the image size should be twice the size of the frame of the image view. This allows the image to use a scale of 2 to take advantage of the retina screen capability. So, you should have one image of size 290x140 (if you are supporting non-retina devices) and one image of size 580x280 (this is the #2x image).
The frame of the view is the description of the position and size of the view within the view hierarchy (in terms of the superview coordinate system). If you have fractional values in the frame size or position you can get 'blurring' effects.
I'm building an iphone app.
I have a tableview and i set a background image like so:
UIImageView * bg = [[UIImageView alloc] initWithImage:somebackgroundimage];
CGRect framebg = bg.frame;
framebg.origin.y = -64;
framebg.origin.x = 0;
framebg.size.width = 320;
framebg.size.height = 480;
[bg setFrame:framebg];
[_tblview setBackgroundView:bg];
no matter what framebg.size.width or framebg.size.height I set, the image always appears distorted or compressed with a size of maybe 320 width and 400 height. It is almost as if the app will forcefully resize the image to fit between the top navigation bar and my bottom tab bar.
How do I force tableview background image to be of 320px width by 480px height?
Also it seems the origin.y and origin.x aren't being respected either.
I know this question is a bit old, but I thought i would share what I was able to use to get around a similar issue (using setContentMode for the image view):
UIImageView *bg = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"background.png"]];
[bg setContentMode:UIViewContentModeScaleAspectFit];
self.tableView.backgroundView = bg;
Hope this helps.