UIImageView show image out of bounds in a UICollectionViewCell sub class - objective-c

I have to create a customize UICollectionViewCell to show a image and a name for the image, And on top of the image, there is a frame image which is 2 pixels bigger in width and height than the image. However, no matter what I do, the image seems to be bigger than the frame image. I did the same thing for the table view, and it works perfect.
Here is the code:
//GridCell.h
#interface GridCell : UICollectionViewCell
#property(nonatomic, strong) UILabel *lblName;
#property(nonatomic, strong) UIImageView *image;
#end
//GridCell.m
#import "GridCell.h"
#implementation GridCell
#synthesize image, lblName;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
UIImage *bg = [UIImage imageNamed:#"borderUIimgLg.png"];
UIImageView *bgImage = [[UIImageView alloc] initWithFrame:CGRectMake(0.0, 0.0, frame.size.width, frame.size.width)];
[bgImage setImage:bg];
[bgImage setContentMode:UIViewContentModeScaleAspectFill];
NSLog(#"BG Image size %f, %f", bgImage.frame.size.width, bgImage.frame.size.height);
UIImageView *contentImage = [[UIImageView alloc] initWithFrame:CGRectMake(2.0, 2.0, frame.size.width-4.0, frame.size.width-4.0)];
[contentImage setContentMode:UIViewContentModeScaleAspectFill];
[contentImage setClipsToBounds:YES];
self.image = contentImage;
[self.contentView addSubview:self.image];
[self.contentView addSubview:bgImage];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(2.0, frame.size.width, frame.size.width - 4.0, 21.0)];
[label setFont:[UIFont fontWithName:#"HelveticaNeue-Bold" size:11.0]];
[label setTextAlignment:NSTextAlignmentCenter];
[label setBackgroundColor:[UIColor clearColor]];
self.lblName = label;
[self.contentView addSubview:self.lblName];
}
return self;
}
The UICollectionViewCell has a size of 67 x 100, so in the code, the bgImage supposed to be always to be 67 x 67 and its origin is (0,0) and the contentImage supposed to have a frame of (0,0,63,63). By debugging, it seems correct. However, the conentimage always bigger than the bgImage. The original size of the image is 80 x 80 though. I have tried setClipToBounds,
setContentViewMode on either the cell.ContentView or the imageView, but none works.
A screenshot about the problem is attached.
Any help is appreciated.

This might have found the answer by now, try:
contentImage.clipsToBounds = YES;

you are using 2 times frame.size.width instead of frame.size.height on the other one
edit, try this:
in the cell, when using initWithFrame methods, use the self.bounds property of the cell.
if you init the imageview inside the border use CGRectInset method to initialize the imageview with smaller bounds and set the imageviews center to same as the contentview of the cell

Try changing UIViewContentModeScaleAspectFill to UIViewContentModeScaleAspectFit.

Related

How to pin width of subviews relative?

I have one view controller with two subviews.
I would like to pin both of the subviews to have the same relative width.
Like this:
Thanks!
You need to pin subviews to top, left, right sides. Also set equal width property.
You should look at this tutorial, there is a good example of equal width containers.
Here is a simple version of doing the same thing with code,
#interface ViewController ()
#property (nonatomic, weak) UIView *view1;
#property (nonatomic, weak) UIView *view2;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[self prepareView];
[self setupConstraints];
}
- (void)prepareView
{
UIView *view1 = [self createView];
UIView *view2 = [self createView];
[self.view addSubview:view1];
[self.view addSubview:view2];
self.view1 = view1;
self.view2 = view2;
}
- (void)setupConstraints
{
NSDictionary *views = #{
#"view1": self.view1,
#"view2": self.view2
};
NSString *horizontalFormat = #"H:|[view1][view2(==view1)]|";
NSString *verticalFormat = #"V:|[view1]|";
NSArray *horizontalConstraints;
NSArray *verticalConstraints;
horizontalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:horizontalFormat
options:NSLayoutFormatAlignAllTop | NSLayoutFormatAlignAllBottom
metrics:nil
views:views];
verticalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:verticalFormat
options:0
metrics:nil
views:views];
[self.view addConstraints:horizontalConstraints];
[self.view addConstraints:verticalConstraints];
}
- (UIView *)createView
{
UIView *view = [[UIView alloc ] initWithFrame:CGRectZero];
view.translatesAutoresizingMaskIntoConstraints = NO;
view.backgroundColor = [self randomColor];
return view;
}
- (UIColor *)randomColor
{
float red = arc4random_uniform(255) / 255.0;
float green = arc4random_uniform(255) / 255.0;
float blue = arc4random_uniform(255) / 255.0;
return [UIColor colorWithRed:red
green:green
blue:blue
alpha:1.0];
}
#end
The horizontalConstraint's options pin both the views top and bottom, while the format string also says that both the views has the same width. We have the first view pinned to the left edge, second view pinned to the right edge and both of them are equal, and also their top and bottom are pinned. Now, we need to tell the view that one of them is pinned to the top edge of the superView and bottom edge of the superView, which the verticalFormat describes. Now, that we have the views with equal widths, their top is pinned to superView's top and bottom to superView's bottom, the subviews will have layout as you have described. It would be quite easy to setup the constraints in storyboard knowing the above details.
You can also look at my previous answer which preserves the views position on rotation IOS AutoLayout Change possition on Rotation.

How should I go about recreating the iOS home screen open folder animation?

At first I thought it wouldn't be too hard, but turns out there's a bit more to it than I thought.
At the moment my code's based around this: https://github.com/jwilling/JWFolders. However, it's not very clean, the biggest problem being that it takes a screenshot every time the folder opens (renderInContext: is pretty taxing on the CPU so turns out being very low fps). Aside from that this implementation doesn't look as clean and as polished as the Apple animation does.
Apple manages to pull off a pixel perfect animation that doesn't lag. I'd like to do the same! What is the best way to go about this/how would you do this - a cleanly coded, good looking and fluid animation? At the moment, my animation's lacking in all those areas, and I'm stumped about how I could do it better (like Apple does it).
-
I'm not begging for code, just a best method/how to. But if you want to go ahead and code it then there's no way I'd say no (that would definitely be bouty worthy)!!
I would separate the Springboard into several views, where each view is one row of icons.
If a folder icon is clicked, I would animate all following views to move down and up to make place for the folder content. at the same time I would add a subview that represents the folder content and animates with the same speed its size and position if necessary.
To support a background image that spans over the whole screen I would cut that into pieces and add this pieces as background image views to each row's view.
I wrote a quick and dirty sample code with the animation starting on any tap location, also available as complete project on github.
#interface ViewController ()
#property (nonatomic, strong) UIView *upperView;
#property (nonatomic, strong) UIView *lowerView;
#property (nonatomic, strong) UIImageView *upperImageView;
#property (nonatomic, strong) UIImageView *lowerImageView;
#property (nonatomic, strong) UIView *folderContentsView;
#property (nonatomic, assign) CGRect startRect;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
UIImage *bgImg = [UIImage imageNamed:#"bg.png"];
self.upperImageView = [[UIImageView alloc] initWithImage:bgImg];
self.lowerImageView = [[UIImageView alloc] initWithImage:bgImg];
[self.upperImageView setContentMode:UIViewContentModeTop];
[self.lowerImageView setContentMode:UIViewContentModeTop];
self.upperView = [[UIView alloc] initWithFrame:self.upperImageView.frame];
self.lowerView = [[UIView alloc] initWithFrame:self.lowerImageView.frame];
[self.upperView addSubview:_upperImageView];
[self.lowerView addSubview:_lowerImageView];
[self.view addSubview:_lowerView];
[self.view addSubview:_upperView];
UITapGestureRecognizer *upperTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(openOverlay:)];
UITapGestureRecognizer *lowerTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(openOverlay:)];
[self.upperView setUserInteractionEnabled:YES];
[self.upperView addGestureRecognizer:upperTapRecognizer];
[self.upperView setClipsToBounds:YES];
[self.lowerView setUserInteractionEnabled:YES];
[self.lowerView addGestureRecognizer:lowerTapRecognizer];
[self.lowerView setClipsToBounds:YES];
self.folderContentsView = [[UIView alloc] initWithFrame:CGRectZero];
self.folderContentsView.backgroundColor = [UIColor redColor];
UITapGestureRecognizer *closeTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(closeOverlay:)];
[self.folderContentsView addGestureRecognizer:closeTapRecognizer];
[self.view addSubview:self.folderContentsView];
[self.folderContentsView addSubview:[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"bgFolder.png"]]];
[self.folderContentsView setClipsToBounds:YES];
self.startRect = [self.upperView frame];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
-(void)openOverlay:(UITapGestureRecognizer *) sender
{
[self.upperView setUserInteractionEnabled:NO];
[self.lowerView setUserInteractionEnabled:NO];
CGPoint location = [sender locationInView:sender.view];
self.folderContentsView.frame = CGRectMake(0, location.y,
_lowerView.frame.size.width, 0);
self.lowerView.frame = CGRectMake(0, location.y,
_lowerView.frame.size.width, _lowerView.frame.size.height);
self.upperView.frame = CGRectMake(0, 0,
_upperView.frame.size.width, location.y);
self.lowerImageView.frame = CGRectMake(_lowerImageView.frame.origin.x, -location.y,
_lowerImageView.frame.size.width, _lowerImageView.frame.size.height);
[UIView animateWithDuration:.5 animations:^{
self.folderContentsView.frame = CGRectMake(0, location.y,
_lowerView.frame.size.width, 200);
self.lowerView.frame = CGRectOffset(_lowerView.frame, 0, 200);
}];
}
-(void) closeOverlay:(UITapGestureRecognizer*) sender
{
[UIView animateWithDuration:.5 animations:^{
self.lowerView.frame = CGRectOffset(_lowerView.frame, 0, -200);
self.folderContentsView.frame = CGRectMake(0, self.folderContentsView.frame.origin.y,
self.folderContentsView.frame.size.width, 0);
} completion:^(BOOL finished) {
[self.upperView setUserInteractionEnabled:YES];
[self.lowerView setUserInteractionEnabled:YES];
self.upperView.frame = self.startRect;
}];
}
#end
two views a equipped with the same background in layers. If a tap is detected, both views are resized so that the upper view ends at the tap's y-coordinate, while the lower view starts there. the UIImageView added to the lowerView is moved in the opposite direction, so that the images stays in place.
Now the lowerView slides down while a contentView is added and resized at the same speed.
As you can see no image rendering or other tough action is required. just UIView animations.

Zoom with Zoomed Buttons on a UIImageView

I have a flat image of a map in a UIImageView and its my job to add clear buttons to some pre-defined "hot spots" that represent locations of interest on the map. However, given the size of the image on the iPhone, the hotspots they have defined are very close together and would be difficult to touch / tap.
Is there a way to zoom in on an image have those buttons scale larger so that they can be pressed more easily?
Yes add the imageview inside a scroll view,
Use this code
- (void)viewDidLoad {
[super viewDidLoad];
UIImageView *imageview = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"yourimage"]];
self.imageView = imageview;
[imageview release];
scrollView.contentSize = CGSizeMake(imageView.frame.size.width, imageView.frame.size.height);
scrollView.maximumZoomScale = 4.0;
scrollView.minimumZoomScale = 0.75;
scrollView.clipsToBounds = YES;
scrollView.delegate = self;
[scrollView addSubview:imageView];
}
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView{
return imageView;
}
In the .h file you would have
#property (nonatomic, retain) UIScrollView *scrollView;
#property (nonatomic, retain) UIImageView *imageView;
For more info please check StackOverFlow on how to add to use UIScrollView
such as Adding UIImageViews to UIScrollView

How can I use UIScrollView?

How can I use UIScrollView? please give me a simple example with one scrolling image?
This will get you an insight of the UIScrollView control:
Learning the basics of UIScrollView
Referenced from UIScrollView Tutorials
Some good samples with the basic functionalities covered
http://halmueller.wordpress.com/2008/10/08/a-very-simple-uiscrollview-demo/
http://developer.apple.com/iphone/library/samplecode/Scrolling/index.html
http://www.vimeo.com/1642150
http://jonathanwatmough.com/2008/12/implementing-tap-to-zoom-in-uiscrollview-on-an-iphone/
http://cocoawithlove.com/2009/01/multiple-virtual-pages-in-uiscrollview.html
Not to mention:
https://stackoverflow.com/search?q=UIScrollView
This can be one example. Basically we create a scrollview, set its frame, add content as a subview, and then set the content size. The image (iphone.png) below is bigger than the iphone screen so that we can scroll it.
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 20, 320, 460)];
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"iphone.png"]];
[scrollView addSubview:imageView];
[imageView release];
scrollView.contentSize = CGSizeMake(imageView.image.size.width, imageView.image.size.height);
[window addSubview:scrollView];
[scrollView release];
You can use below code to add UIScrollView on yourView :-
[self.ScrollView setContentSize:(CGSizeMake(self.view.frame.size.width, self.view.frame.size.height))];
Step:1
Create a UiScrollView,
#interface ViewController : UIViewController
#property (strong, nonatomic) IBOutlet UIScrollView *MyScrollView;
#end
Step2:
In your ViewController.m,
[self.MyScrollView setContentSize:(CGSizeMake(self.view.frame.size.width, self.view.frame.size.height))];
Add UIImageView in to UIScrollView.
then,
Use
imageView.image = [UIImage imageNamed:#"image1.png"];
imageView.frame = CGRectMake(0.0, 0.0, imageView.image.size.width, imageView.image.size.height);
scrollView.contentSize = CGSizeMake(imageView.image.size.width, imageView.image.size.height);

Cocoa Touch - Adding a UIImageView programmatically?

How can I create and position a new imageview in objective-c?
Thanks!
I tried this but it doesnt seem to do anything...
-(void)drawStars{ //uses random numbers to display a star on screen
//create random position
int xCoordinate = arc4random() % 10;
int yCoordinate = arc4random() % 10;
UIImageView *starImgView = [[UIImageView alloc] initWithFrame:CGRectMake(xCoordinate, yCoordinate, 58, 40)]; //create ImageView
starImgView.image = [UIImage imageNamed:#"star.png"];
[starImgView release];
I placed this method in my viewcontroller. I see some CG stuff do I need to import core graphics or something? (what is core graphics anyway?)
You are asking about iPhone image view. Right? Then try this
UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake(10, 10, 100, 50)];
This will create an image view of 100 x 50 dimension and locating (10, 10) of parent view.
Check the reference manual for UIImageView and UIView. You can set an image by using image property of imageView.
imgView.image = [UIImage imageNamed:#"a_image.png"];
And you can use the contentMode property of UIView to configure how to fit the image in the view. For example you can use
imgView.contentMode = UIViewContentModeCenter to place the desired image to the center of the view. The available contentModes are listed here
You haven't added your view as a subview to another view, meaning it isn't in the view hierarchy.
Assuming you are doing this in a view controller, it might look something like:
[self.view addSubview: imgView];
(void)viewDidLoad {
[super viewDidLoad];
UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, self.view.layer.frame.size.width, self.view.layer.frame.size.height)];
imgView.image = [UIImage imageNamed:#"emptyCart.jpeg"];
imgView.backgroundColor = [UIColor whiteColor];
imgView.contentMode = UIViewContentModeCenter;
[self.view addSubview: imgView];
}
I had problem with passing the value NSSArray to NSString,
I got the answer:
//Display all images....
NSString *imgstring= [self.allimages objectAtIndex:indexPath.row];
cell.myimages.image=[UIImage imageNamed:imgstring]; //displaying Images in UIImageView..noproblem.
// Display all numbers...
cell.mylables.text=[NSString stringWithFormat:#"%#", [mysetobjectAtIndex:indexPath.row ]]; //showing results fine ArghyA..