iCarousel swift set view attribute - ios

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?

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.

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

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;
}

Zoom a rotated image inside scroll view to fit (fill) frame of overlay rect

Through this question and answer I've now got a working means of detecting when an arbitrarily rotated image isn't completely outside a cropping rect.
The next step is to figure out how to correctly adjust it's containing scroll view zoom to ensure that there are no empty spaces inside the cropping rect. To clarify, I want to enlarge (zoom in) the image; the crop rect should remain un-transformed.
The layout hierarchy looks like this:
containing UIScrollView
UIImageView (this gets arbitrarily rotated)
crop rect overlay view
... where the UIImageView can also be zoomed and panned inside the scrollView.
There are 4 gesture events that occur that need to be accounted for:
Pan gesture (done): accomplished by detecting if it's been panned incorrectly and resets the contentOffset.
Rotation CGAffineTransform
Scroll view zoom
Adjustment of the cropping rect overlay frame
As far as I can tell, I should be able to use the same logic for 2, 3, and 4 to adjust the zoomScale of the scroll view to make the image fit properly.
How do I properly calculate the zoom ratio necessary to make the rotated image fit perfectly inside the crop rect?
To better illustrate what I'm trying to accomplish, here's an example of the incorrect size:
I need to calculate the zoom ratio necessary to make it look like this:
Here's the code I've got so far using Oluseyi's solution below. It works when the rotation angle is minor (e.g. less than 1 radian), but anything over that and it goes really wonky.
CGRect visibleRect = [_scrollView convertRect:_scrollView.bounds toView:_imageView];
CGRect cropRect = _cropRectView.frame;
CGFloat rotationAngle = fabs(self.rotationAngle);
CGFloat a = visibleRect.size.height * sinf(rotationAngle);
CGFloat b = visibleRect.size.width * cosf(rotationAngle);
CGFloat c = visibleRect.size.height * cosf(rotationAngle);
CGFloat d = visibleRect.size.width * sinf(rotationAngle);
CGFloat zoomDiff = MAX(cropRect.size.width / (a + b), cropRect.size.height / (c + d));
CGFloat newZoomScale = (zoomDiff > 1) ? zoomDiff : 1.0 / zoomDiff;
[UIView animateWithDuration:0.2
delay:0.05
options:NO
animations:^{
[self centerToCropRect:[self convertRect:cropRect toView:self.zoomingView]];
_scrollView.zoomScale = _scrollView.zoomScale * newZoomScale;
} completion:^(BOOL finished) {
if (![self rotatedView:_imageView containsViewCompletely:_cropRectView])
{
// Damn, it's still broken - this happens a lot
}
else
{
// Woo! Fixed
}
_didDetectBadRotation = NO;
}];
Note I'm using AutoLayout which makes frames and bounds goofy.
Assume your image rectangle (blue in the diagram) and crop rectangle (red) have the same aspect ratio and center. When rotated, the image rectangle now has a bounding rectangle (green) which is what you want your crop scaled to (effectively, by scaling down the image).
To scale effectively, you need to know the dimensions of the new bounding rectangle and use a scale factor that fits the crop rect into it. The dimensions of the bounding rectangle are rather obviously
(a + b) x (c + d)
Notice that each segment a, b, c, d is either the adjacent or opposite side of a right triangle formed by the bounding rect and the rotated image rect.
a = image_rect_height * sin(rotation_angle)
b = image_rect_width * cos(rotation_angle)
c = image_rect_width * sin(rotation_angle)
d = image_rect_height * cos(rotation_angle)
Your scale factor is simply
MAX(crop_rect_width / (a + b), crop_rect_height / (c + d))
Here's a reference diagram:
Fill frame of overlay rect:
For a square crop you need to know new bounds of the rotated image which will fill the crop view.
Let's take a look at the reference diagram:
You need to find the altitude of a right triangle (the image number 2). Both altitudes are equal.
CGFloat sinAlpha = sin(alpha);
CGFloat cosAlpha = cos(alpha);
CGFloat hypotenuse = /* calculate */;
CGFloat altitude = hypotenuse * sinAlpha * cosAlpha;
Then you need to calculate the new width for the rotated image and the desired scale factor as follows:
CGFloat newWidth = previousWidth + altitude * 2;
CGFloat scale = newWidth / previousWidth;
I have implemented this method here.
I will answer using sample code, but basically this problem becomes really easy, if you will think in rotated view coordinate system.
UIView* container = [[UIView alloc] initWithFrame:CGRectMake(80, 200, 100, 100)];
container.backgroundColor = [UIColor blueColor];
UIView* content2 = [[UIView alloc] initWithFrame:CGRectMake(-50, -50, 150, 150)];
content2.backgroundColor = [[UIColor greenColor] colorWithAlphaComponent:0.5];
[container addSubview:content2];
[self.view setBackgroundColor:[UIColor blackColor]];
[self.view addSubview:container];
[container.layer setSublayerTransform:CATransform3DMakeRotation(M_PI / 8.0, 0, 0, 1)];
//And now the calculations
CGRect containerFrameInContentCoordinates = [content2 convertRect:container.bounds fromView:container];
CGRect unionBounds = CGRectUnion(content2.bounds, containerFrameInContentCoordinates);
CGFloat midX = CGRectGetMidX(content2.bounds);
CGFloat midY = CGRectGetMidY(content2.bounds);
CGFloat scaleX1 = (-1 * CGRectGetMinX(unionBounds) + midX) / midX;
CGFloat scaleX2 = (CGRectGetMaxX(unionBounds) - midX) / midX;
CGFloat scaleY1 = (-1 * CGRectGetMinY(unionBounds) + midY) / midY;
CGFloat scaleY2 = (CGRectGetMaxY(unionBounds) - midY) / midY;
CGFloat scaleX = MAX(scaleX1, scaleX2);
CGFloat scaleY = MAX(scaleY1, scaleY2);
CGFloat scale = MAX(scaleX, scaleY);
content2.transform = CGAffineTransformScale(content2.transform, scale, scale);

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];
}

Rotation changing UIImageView frame. How to avoid this?

I have two sliders - one for changing image size and one for rotating this image. My imageview is 60x60. The problem is that I rotate the image using CGAffineTransformMakeRotation, but when I try to resize it after that (like, from 60x60 to 65x65 using the slider), it acts weirdly - the frame of the image view has changed like 80x2. How can I avoid this? Here is my code for the slider that resizes the image:
-(IBAction)imageSliderAction:(UISlider *)sender
{
NSUInteger value = sender.value;
float oldCenterX = logoImageView.center.x;
float oldCenterY = logoImageView.center.y;
newWidth = value;
newHeight = value;
CGRect frame = [logoImageView frame];
frame.size.width = newWidth;
frame.size.height = newHeight;
[logoImageView setFrame:frame];
logoImageView.center = CGPointMake(oldCenterX, oldCenterY);
}
And here is the code for my rotating slider:
-(IBAction)rotationSliderAction:(UISlider *)sender
{
NSUInteger angle = sender.value;
if (sender.value >= 1)
{
CGAffineTransform rotate = CGAffineTransformMakeRotation(angle / 180.0 * 3.14);
[logoImageView setTransform:rotate];
}
if (sender.value <= 0 )
{
CGAffineTransform rotate = CGAffineTransformMakeRotation( (360 + sender.value) / 180.0 * 3.14);
[logoImageView setTransform:rotate];
}
}
How can I avoid autochanging frame's width and height when rotating? Because after that I can't resize the image correctly.
From UIView reference
Warning: If the transform property is not the identity transform, the
value of this property is undefined and therefore should be ignored.
If you want to change the size of view that has nontrivial transform you should do that by changing its bounds property (view's center will remain the same so you won't need any extra logic to maintain its position):
[logoImageView setBounds:CGRectMake(0,0,sender.value, sender.value)];

Resources