Attach UILabel to image thumbnail bottom (varying heights) - objective-c

I have a view with image view and Label. Image view displays images of varying sizes and it is fixed to the top(see image) I want to dynamically glue text label to the bottom of every image without any space between image thumbnail and UILabel.

You can do that programically. I assume that you have UILabel attached to "label" and the image to "imageView" variables.
CGRect labelFrame = label.frame;
labelFrame.origin.y = imageView.frame.origin.y + imageView.frame.size.height + any_space_you_want_between_image_and_label;
label.frame = labelFrame;
That will change the position of label just bellow the imageView. I hope this helps.

Because as you mentioned you use UIViewContentModeScaleAspectFit for the content mode the solution is a bit harder.
You have to actually calculate the final height of the image (the actual size of the image inside the UIImageView):
//UIImage *img = ...; UIImageView *imgView = ....
CGFloat imageWidth = img.size.width;
CGFloat imageHeight = img.size.height;
CGFloat viewWidth = imgView.frame.size.width;
CGFloat viewHeight = imgView.frame.size.height;
float actualHeight = imageHeight * viewWidth / imageWidth;
// this is the actual height of the UIImage inside the UIImageView
CGRect labelFrame = label.frame;
labelFrame.origin.y = imageView.frame.origin.y + actualHeight + any_space_you_want_between_image_and_label;
label.frame = labelFrame;

Related

Objective c uilabel width based on text length

I want to set the width of the uilabel based on the text length and then on top of that make it a little bit wider. The text might be different so I cannot just predefine the width of the uilabel. My approach to this is to get the width of the text and then add another 10.0 to it but it doesn't work.
CGSize tSize = [[self.label1 text] sizeWithAttributes:#{NSFontAttributeName:[self.label1 font]}];
CGFloat tWidth = tSize.width + 10.0;
self.label1.frame = CGRectMake(self.label1.frame.origin.x, self.label1.frame.origin.y, tWidth, self.label1.frame.size.height);
self.label1.backgroundColor = [UIColor blueColor];
Any advice is much appreciated.
You might want to use [yourLabel sizeToFit]; or [yourLabel sizeThatFits: <#your target size#>];
sizeToFit resizes your label within it's current frame.size according to it's current text , font and the numberOfLines you provided.
Then you can change the size
[yourLabel sizeToFit];
CGRect rect = yourLabel.frame;
rect.size.width += 10;
yourLabel.frame = rect;
sizeThatFits:(CGSize)size doesn't resize your label but it returns the size that fits the size you pass as parameter.
sizeToFit uses sizeThatFits:(CGSize)size internally.
You can change size by doing this
CGSize exampleSize = (CGSize){300, 300};
CGSize fittingSize = [yourLabel sizeThatFits: exampleSize];
CGRect rect = yourLabel.frame;
rect.size.width = fittingSize.width;
rect.size.height = fittingSize.height;
yourLabel.frame = rect;
This should be working fine even if you are working with yourLabel.attributedText

Rotate around the center of a CCLabelTTF as achnor point

I want to rotate a CCLabelTTF around it's center.
But it doesn't look like it. It does look more like a rotation at the bottom of the CCLabelTTF.
Code:
CCLabelTTF *aLabel ... init/addChild and so on
CCRotateBy *rotateLabelA = [[CCRotateBy alloc] initWithDuration:0.5f angle:-60.0f];
aLabel.string = #"0";
aLabel.anchorPoint = ccp(0.5f, 0.5f);
[aLabel runAction:rotateLabelA];
How to rotate a letter around its visible center, if it is a CCLabelTTF?
I was able to make the boundary box of a CCLabelTTF visible:
As seen in the image, the bounding box is much bigger. But there isn't a formula to determine the middle of the letter.
If you set anchorPoint = cpp(0.5f,0.5f) to some ccNode object, it will rotate around its center, which is calculated using boundingBox property.
The problem is the label's boundingBox.size.height differs with it's actual height. That is why it rotates not around the center.
I am not sure in such a manual solution, but it worked for me someday.
CCLabelTTF *label = [CCLabelTTF labelWithString:#"0" fontName:#"Marker Felt"fontSize:24];
label.position = ccp(winSize.width /2.0f, winSize.height / 2.0f);
float fontSize = label.fontSize; // actual Font size
float labelHeight = label.contentSize.height; // actual label height ( the same as boundingBox.size.height
float offset = (labelHeight - fontSize - (labelHeight - fontSize) / 2.0f) / labelHeight / 2.0f;
label.anchorPoint = ccp(0.5f, 0.5f + offset);
[layer addChild:label];
[label runAction:[CCRotateBy actionWithDuration:10.0f angle:-360]];
I found out how to find the middle point of an CCLabelTTF:
float fontSize = bLabel.fontSize; // actual Font size in pixels
float labelHeight = bLabel.contentSize.height; // actual label height ( the same as boundingBox.size.height )
float offset = labelHeight - fontSize; // the free room under the font
float halfFontSize = fontSize / 2;
float percentMiddleOfFont = (halfFontSize + offset) / labelHeight;
bLabel.anchorPoint = ccp(0.5f, percentMiddleOfFont);

What's the right way to dynamically give height to a UIScrollView depending on the content within?

Here my dilemma. I have 4 elements inside a UIScrollView.
1. Top most element is a UILabel that I give height dynamically depending upon the amount of content in it.
2. Second is a fixed height UILabel that I give position dynamically depending upon the height given to the upper UILabel
3. Third element is a UIImageView that again I have to give position dynamically depending upon the height given to the topmost UILabel
4. The fourth is a UIWebView, to which I gave both, height & position dynamically. (Height depending upon the content in it.. and position again depending on the height of topmost UILabel)
Finally, I dynamically give height to my UIScrollView to accomodate all of the above elements.
Here is the code I use in - (void)webViewDidFinishLoad:(UIWebView *)webView to accomplish all of the above.
//Adjust height of top-most UILabel
CGSize maximumLabelSize = CGSizeMake(300,9999);
CGSize expectedLabelSize = [item.label1 sizeWithFont:label1.font constrainedToSize:maximumLabelSize lineBreakMode:label1.lineBreakMode];
CGRect newFrame = label1.frame;
newFrame.size.height = 0;
newFrame.size.height = expectedLabelSize.height;
label1.frame = newFrame;
//Adjust position of second UILlabel
CGRect labelPosition = label2.frame;
labelPosition.size.height = 20;
labelPosition.origin.y = expectedLabelSize.height +14;
label2.frame = labelPosition;
//Add UIImageView and adjust it's position
UIImageView *image;
image = [[UIImageView alloc] initWithFrame:CGRectMake(0, expectedLabelSize.height +41, 320, 2)];
image.image = [UIImage imageNamed:#"image.png"];
[scrollView addSubview:image];
[image release];
//Adjust UIWebView height and position
CGRect frame = webView.frame;
frame.size.height = 0;
frame.origin.y = expectedLabelSize.height +48;
webView.frame = frame;
CGSize fittingSize = [webView sizeThatFits:CGSizeZero];
frame.size = fittingSize;
webView.frame = frame;
//Adjust Scrollview height
scrollView.contentSize = CGSizeMake(320, fittingSize.height +expectedLabelSize.height +48);
Finally, my problem is that when I first load this view, everything but the scrollview get's proper height & position. But, if I go back one view & open this view again, the scrollview has the desired height.
Any ideas what I might be doing wrong here?
My guess is that the scrollView variable isn't yet initialized when this first runs. Try setting a breakpoint somewhere in this code and checking if scrollView has a value or if it's just 0x00000000.

How to set size of UIScrollView frame programmatically?

I am newbie so my question can be really obvious, but I didn't find any solution so far.
I did in IB UIScrollView and connected it with File's Owner.
I would like to set now the frame size of my UIScrollView (named ScrollView).
const CGFloat BoardWidth = 320;
const CGFloat BoardHeight = 400;
//I tried this way but 'Expression is assignable' - said Xcode
ScrollView.frame.size.width = BoardWidth;
ScrollView.frame.size.height = BoardWidth;
So how can I the easiest set own sizes of ScrollView frame?
CGRect scrollFrame = CGRrectMake(x, y, w, h);
ScrollView.frame = scrollFrame;
Or if you need only to change the width and height;
CGRect scrollFrame;
scrollFrame.origin = ScrollView.frame.origin;
scrollFrame.size = CGSizeMake(w, h);
ScrollView.frame = scrollFrame;
Edit keeping the center unchanged:
CGRect scrollFrame;
CGFloat newX = scrollView.frame.origin.x + (scrollView.frame.size.width - w) / 2;
CGFloat newY = scrollView.frame.origin.y + (scrollView.frame.size.height - y) / 2;
scrollFrame.origin = CGPointMake(newX, newY);
scrollFrame.size = CGSizeMake(w, h);
scrollView.frame = scrollFrame;
you need to do this, for example.
ScrollView.frame = CGRectMake(0, 0, BoardWidth, BoardHeight);
Once done you need also to set contentSize property. It's the area that 'extends' behind the frame of your UIScrollView.
If you want to scroll only horizontally:
ScrollView.contentSize = CGSizeMake(w * BoardWidth, BoardHeight);
If you want to scroll only vertically:
ScrollView.contentSize = CGSizeMake(BoardWidth, h * BoardHeight);
If you want to scroll both horizontally and vertically:
ScrollView.contentSize = CGSizeMake(w * BoardWidth, h * BoardHeight);
where w and h are generic values to increment your width and/or your height.
If you want have an horizontal (for example) discrete scroll (e.g. you have some pages with the same dimension of your screen).
ScrollView.pagingEnabled = YES;
ScrollView.contentSize = CGSizeMake(p * BoardWidth, BoardHeight);
where p is the number of pages you want to display.
Hope it helps.
You can do it as below,
scrollView.frame = CGRectMake(xOrigin,yOrigin,width,height);
If you are looking for content size of scrollview then it as below,
scrollView.contentSize = CGSizeMake(width,height);
CGRect Frame = ScrollView.frame
Frame.frame.size.width = BoardWidth;
Frame.frame.size.width = BoardWidth;
ScrollView.frame = Frame;
Since frame is a structure..you can't set the frame of an object directly.. You will have to make a Cgrect and then manipulate it.
using contentSize property
ScrollView.contentSize = CGSizeMake(320, 520);
it needs to be bigger than the frame so it actually scrolls.

How to fill gaps in imageview (not covered by image) with color?

I want to create an image of fixed size e.g. 612 by 612. I am using an image picker to select photos from my iphone. So in order to ensure that all the photos fit to the 612 by 612 size without distortion, I am using the following method to re-scale the photo so that they conform to the size of 612 by 612. However as a result, blank spaces might be created in the final image. (see example below)
I am using the following code to scale my image (of fixed size 612 by 612)
//Scale the image to fit to imageview
UIImage *image = [self scaleImage:img toRectSize:CGRectMake(0, 0, 612, 612)];
//Method to scale image
- (UIImage *)scaleImage:(UIImage *)img toRectSize:(CGRect)screenRect
{
UIGraphicsBeginImageContext(screenRect.size);
float hfactor = img.size.width / screenRect.size.width;
float vfactor = img.size.height / screenRect.size.height;
float factor = MAX(hfactor, vfactor);
float newWidth = img.size.width / factor;
float newHeight = img.size.height / factor;
float leftOffset = (screenRect.size.width - newWidth) / 2;
float topOffset = (screenRect.size.height - newHeight) / 2;
CGRect newRect = CGRectMake(leftOffset, topOffset, newWidth, newHeight);
[img drawInRect:newRect blendMode:kCGBlendModePlusDarker alpha:1];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
As mentioned, as the image is sometimes not a full square, I get a result like what you see below:
How can I feel up the white spaces in the image with black color?
One way is to set the backgroundColor of UIImageView to blackColor.
Another way is to fill the rect with blackColor while you scale the image.
- (UIImage *)scaleImage:(UIImage *)img toRectSize:(CGRect)screenRect {
...
CGRect newRect = CGRectMake(leftOffset, topOffset, newWidth, newHeight);
// Fill the original rect with black color
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [[UIColor blackColor] CGColor]);
CGContextFillRect(context, screenRect);
[img drawInRect:newRect blendMode:kCGBlendModeNormal alpha:1];
...
}
Note that the blendMode in drawInRect:blendMode:alpha: method is set to kCGBlendModeNormal. If you set some other blend modes you will get undesired results. For example, if you set the blend mode to kCGBlendModePlusDarker and fill the rect with blackColor then the entire image will become black.
Set the background color on your UIImageView to black and you'll get what you want