IOS Autolayout- Multiple images in one horizontal line of subview programmatically - ios

I created a tableview header and added a subview to it.
I am trying to center multiple avatar images(fixed width and height) in a single line of this ui subview.
Max number of images=max(predefined).
Number of images that I would like to fit is n.
When 5 is max number of image,
n=1:
[......................image 1........................... ]
n=2:
[.................image 1.....image2...............]
n=3
[.........image 1.....image2....image3.........]
n=4
[...image 1....image2....image3......image4...]
n=5
[.imag 1....imag2....imag3....imag4....imag5.]
That is the placement should be centred with equal spacings.
How can I achieve this programatically?
I can do this by story board, by placing max images in a row, keeping equal leading and trailing spaces,
and when n=1, i will hide 1,2,4 and 5
while when n=2, i will hide 1,2,5

If you can target a Deployment Target of iOS 9 and up, use UIStackView. It's designed to handle this scenario.
If you can't do that yet, the following algorithm will work. It doesn't use constraints.
CGFloat tableWidth = ...; // This may change if you allow rotation.
CGFloat spacer = ...; // Amount of space between images goes here.
CGFloat imageWidth = images.count > 0 ? [[images[0] size] width] : 0.0;
CGFloat imageHeight = images.count > 0 ? [[images[0] size] height] : 0.0;
CGFloat totalWidth = images.count * imageWidth + (images.count - 1) * spacer;
CGFloat leftEdge = (tableWidth / 2.0) - (totalWidth / 2.0);
for (int i = 0; i < images.count; i++) {
UIImageView *iv = ...; // Create and configure with image[i].
CGRect frame = CGMakeRect(0, 0, imageWidth, imageHeight);
frame.origin.x = leftEdge + (i * imageWidth + i * spacer);
iv.frame = frame;
}

Related

How to Resize button animations programmatically

I am new to Objective-C. I created an animation that move 3 buttons upwards. These buttons contain images. However, when this button animation occurs it resizes the button images and makes them HUGE. I tried to correct the code below to resize the button images, but I still get HUGE buttons. Can someone please help me? It should be Width:78 Height:76. I tried replacing width and height but it still doesn't work. Note: Just correct the code, I don't need a completely different answer.
-(IBAction)Search:(id)sender {
CGFloat screenWidth = self.view.bounds.size.width;
CGFloat screenHeight = self.view.bounds.size.height;
CGFloat normalizedX = (124 / 320); // You calculate these 'normalized' numbers, possibly from a designer's spec.
// it's the percent the amount should be over, as number from 0-1.
// This number is based on screen width of 320 having x 124 pt.
CGFloat startingX = normalizedX * screenWidth;
CGFloat startingY = (475 / 200) * screenHeight;
CGFloat width = (42 / 40) * screenWidth;
CGFloat height = (30 / 30) * screenHeight;
CGRect startingRect = CGRectMake(startingX, startingY, width, height);
self.button.frame = startingRect;
self.buttonTwo.frame = startingRect;
self.buttonThree.frame = startingRect;
// animate
[UIView animateWithDuration:0.75 animations:^{
CGFloat firstX = (13 / 770) * screenWidth;
CGFloat lowerY = (403 / 370) * screenHeight;
self.button.frame = CGRectMake(firstX, lowerY, width, height);
CGFloat secondX = (124 / 424) * screenWidth;
CGFloat upperY = (347 / 447) * screenHeight;
self.buttonTwo.frame = CGRectMake(secondX, upperY, width, height);
CGFloat thirdX = (232 / 680) * screenWidth;
self.buttonThree.frame = CGRectMake(thirdX, lowerY, width, height);
}];
}
Looks to me like your height and width math is wrong.
(42/40) * screenWidth will simplify to (1) * screenWidth, or the full width of the screen (The expression 42/40 will be done using integer math, resulting in 1.0. If it used floating point, you'd get 1.05 * screenWidth, which would make the images even bigger.)
You have a similar problem with your height calculation. You are setting the button to be the full height of the screen, and slightly wider.

iCarousel swift set view attribute

I want to set the attributes for icarousel in order to get this shape
I have this code to set it but the result not 100% right
CGFloat count = [self circularCarouselItemCount];
CGFloat spacing = [self valueForOption:iCarouselOptionSpacing withDefault:2.5];
CGFloat arc = [self valueForOption:iCarouselOptionArc withDefault:M_PI * 1.0];
CGFloat radius = [self valueForOption:iCarouselOptionRadius withDefault:MAX(_itemWidth * spacing / 2.0, _itemWidth * spacing / 2.0 / tanf(arc/2.0/count))];
CGFloat angle = [self valueForOption:iCarouselOptionAngle withDefault:offset / count * arc];
the result looks like
And if I change device size I get only 1 image.
How can I modify the attributes to get it in all screen sizes?

Horizontal parallax not working as intended

I'm attempting a parallax effect with a UIScrollView whereby there will be an UIImageView and UILabel per 'page', and as the user scrolls through the pages, the UIImageView will disappear off of the current page at a faster rate than the UILabel, while the next UIImageView and UILabel appear.
My code is working perfectly when on the first page as the amplifier is not taken into account, thus not working on any other page; the UIImageView is not centered horizontally within the page, which it should be.
Please can you tell me where I'm going wrong?
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
CGPoint offset = scrollView.contentOffset;
NSInteger currentPage = floorf(offset.x / CGRectGetWidth(self.view.frame));
if (currentPage >= 0 && currentPage < CINNumberOfWalkthroughs) {
NSInteger lastPage = self.pageControl.currentPage;
self.pageControl.currentPage = currentPage;
float imageViewAmplifier = offset.x / scrollView.contentSize.width;
UIImageView *imageView = self.imageViews[currentPage];
float w = CGRectGetWidth(self.view.frame);
float a = CGRectGetWidth(imageView.frame);
imageView.center = CGPointMake((currentPage * w) + ((w + a) / 2) + (offset.x * imageViewAmplifier), imageView.center.y);
}
}
I used the following calculation to determine the center position of each of the UIImageViews, and then add a portion of the offset to add the moving effect.
I managed to fix the issue by simplifying things - I have the tendency to overcomplicate everything which made this task a lot more difficult than it needed to be.
Instead of working out the current center of the imageView and performing the translation by transforming the center point, I used a simple CGAffineTransformMakeTranslation() which effectively deals with all of this for me. All I had to do from there was work out the actual offset from the origin of the page, and then fix the amplifier, which was corrected by working out the ration between the actual offset and the content size of the scroll view. My working solution can be found below:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
CGPoint offset = scrollView.contentOffset;
NSInteger currentPage = floorf(offset.x / CGRectGetWidth(self.view.frame));
if (currentPage >= 0 && currentPage < CINNumberOfWalkthroughs) {
self.pageControl.currentPage = currentPage;
UIImageView *imageView = self.imageViews[currentPage];
float multiplier = -1 * (offset.x / scrollView.contentSize.width);
float w = CGRectGetWidth(self.view.frame);
imageView.transform = CGAffineTransformMakeTranslation((offset.x - currentPage * w) * multiplier, 0);
UILabel *instructionLabel = self.instructionLabels[currentPage];
instructionLabel.transform = CGAffineTransformMakeTranslation((offset.x - currentPage * w) * (multiplier - 0.4), 0);
}
}

Dyamic frame calculation for UIImages in UITableViewCell

I am putting few icons on UITableViewCell. The number of icons can vary from 1 to 6. Icons should not have fixed X position and instead they should be dynamically placed considering the cell space. So if there are 3 icons they should look placed centric to the cell. Also, the icon spacing should also vary. For instance when it is 6 icons all of them will be placed with less margins in between and when there are 3 then margin will be more and so will be the X position.
Please suggest some quick way to calculate this frame. I am running the app both on iOS 6 and iOS 7.
This is what I have tried by far but this does not seems to work well with icon count variation. Also, in between space is not dynamic with this.
int maxIconTypes = 6;
CGFloat innerPadding = ([self isIOS7]) ? 15.0f : 9.0f;
CGRect adjustedBoundsIOS6 = [self bounds];
CGFloat adjustedWidth = ([self isIOS7]) ? self.bounds.size.width : adjustedBoundsIOS6.size.width;
CGFloat xOrigin = innerPadding;
CGFloat iconViewSize = 25.0f;
CGFloat ySpacer = (self.bounds.size.height - iconSize) / 2;
CGFloat xSpacer = ((adjustedWidth - (innerPadding * 2)) - (maxRequestTypes * iconViewSize)) / (maxIconTypes - 1);
for (NSString *icon in iconList) {
UIImageView *anIconView = [[UIImageView alloc] initWithImage:[UIImage icon]];
if (anIconView.image) {
anIconView.frame = CGRectMake(xOrigin + originPadding, ySpacer, anIconView.image.size.width, anIconView.image.size.height);
[self.contentView addSubview:anIconView];
xOrigin += anIconView.frame.size.width + xSpacer;
}
}
However many items you have, the number of spaces is the same if you want equal spacing with half spacing at the start and end:
half width full width half
half width full width full width half
So, you just need to know the full width available and the combined width of the items. A simple multiply (to get the combined width of the items) and subtract (from the full width available) gives you the remaining width for the 'spacers'. Divide by the number of items to get the xSpacer, set the initial xOrigin to xSpacer * 0.5
Here is an example of what Wain is explaining:
//Im doing this in a UIView rather than in a UITableViewCell but idea is the same
int cellWidth = CGRectGetWidth(self.view.bounds);
//num of icons
int iconCount = 6;
//size of icon
int iconSize = 25;
//The max padding we can have
float maxPadding = (cellWidth - (iconSize * iconCount)) / iconCount;
//Our offset
float xOrigin = maxPadding / 2;
//Loooop
for (int i = 0; i < iconCount; i++) {
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(xOrigin, self.view.center.y, iconSize, iconSize)];
xOrigin += (iconSize + maxPadding);
label.backgroundColor = [UIColor blueColor];
[self.view addSubview:label];
}

iOS: How to align (left/right) a UIImageView when using UIViewContentModeScaleAspectFill?

I'm playing with the contentMode property of the UIImageView.
When I set it to UIViewContentModeScaleAspectFill, the image is scaled to fit the screen.
It's centered. So right and left (or top and bottom, depending on the screen orientation) part of the picture are clipped.
I'd like to have the same behaviour but not centered. Is that possible to have the image to be clipped only on the right (or left) side? (again top or bottom depending on the orientation) ?
thanks
I know it's been a while since February, but I just encountered the same need in the app I am developing.
I solved it using a custom UIImageView which can be easily integrated into your existing code (it's a drop-in replacement of UIImageView).
You can find the class on github, along with an example:
https://github.com/reydanro/UIImageViewAligned
Hope this helps you on your next projects
The iOS way to do this is to manipulate the contentsRect of the layer of the UIImageView. Consider the following example (in my custom UIImageView sub class) to align left or right (instead of center which is default):
- (void)updateImageViewContentsRect {
CGRect imageViewContentsRect = CGRectMake(0, 0, 1, 1);
if (self.image.size.height > 0 && self.bounds.size.height > 0) {
CGRect imageViewBounds = self.bounds;
CGSize imageSize = self.image.size;
CGFloat imageViewFactor = imageViewBounds.size.width / imageViewBounds.size.height;
CGFloat imageFactor = imageSize.width / imageSize.height;
if (self.alignmentMode == AHTImageAlignmentModeLeft) {
if (imageFactor > imageViewFactor) {
CGFloat scaledImageWidth = imageViewBounds.size.height * imageFactor;
CGFloat xOffset = (scaledImageWidth - imageViewBounds.size.width) / 2;
imageViewContentsRect.origin.x = -(xOffset / scaledImageWidth);
} else if (imageFactor < imageViewFactor) {
CGFloat scaledImageHeight = imageViewBounds.size.width / imageFactor;
CGFloat yOffset = (scaledImageHeight - imageViewBounds.size.height) / 2;
imageViewContentsRect.origin.y = -(yOffset / scaledImageHeight);
}
} else if (self.alignmentMode == AHTImageAlignmentModeRight) {
if (imageFactor > imageViewFactor) {
CGFloat scaledImageWidth = imageViewBounds.size.height * imageFactor;
CGFloat xOffset = (scaledImageWidth - imageViewBounds.size.width);
imageViewContentsRect.origin.x = (xOffset / scaledImageWidth) / 2;
} else if (imageFactor < imageViewFactor) {
CGFloat scaledImageHeight = imageViewBounds.size.width / imageFactor;
CGFloat yOffset = (scaledImageHeight - imageViewBounds.size.height);
imageViewContentsRect.origin.y = (yOffset / scaledImageHeight) / 2;
}
}
}
self.layer.contentsRect = imageViewContentsRect;
}

Resources