UIImageView content mode - ios

The blue line is the imageview's bounds.
UIImageView's contentMode is UIViewContentModeScaleAspectFit,
And I want keep the original picture's scale.
How can I make the picture's left edge is on the UIImageView's left edge?
But not like UIViewContentModeTopLeft mode. Keep the scale and no blank in the left.
My english is not good, hope you guys could understand what I'm saying.
Thank you very much.

yourimageView.contentMode = UIViewContentModeCenter;
if ( yourimageView.bounds.size.width > yourimageView.size.width && yourimageView.bounds.size.height > yourimageView.size.height) {
yourimageView.contentMode = UIViewContentModeScaleAspectFit;
}
Swift3
yourimageView.contentMode = .center
if yourimageView.bounds.size.width > yourimageView.size.width && yourimageView.bounds.size.height > yourimageView.size.height {
yourimageView.contentMode = .scaleAspectFit
}
you can change your mode as
typedef NS_ENUM(NSInteger, 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,
};

the moment i saw your situation,i thought about this:
_imageView.contentMode = UIViewContentModeLeft | UIViewContentModeScaleAspectFit;
and i tried it, but it makes things worse
so i think you may resize your imageView`s bound to fit the size you want with this code
/// resize image to fit in show area without changing image ratio
+ (CGSize)resizeImageViewFromImageSize:(CGSize)imageSize toFitShowSize:(CGSize)showSize {
CGFloat ratioW = imageSize.width / showSize.width;
CGFloat ratioH = imageSize.height / showSize.height;
CGFloat ratio = imageSize.width / imageSize.height;
if (ratioW > 1 && ratioH > 1) {
if (ratioW > ratioH) {
imageSize.width = showSize.width;
imageSize.height = imageSize.width / ratio;
} else {
imageSize.height = showSize.height;
imageSize.width = imageSize.height * ratio;
}
} else if (ratioW > 1) {
imageSize.width = showSize.width;
imageSize.height = imageSize.width / ratio;
} else if (ratioH > 1) {
imageSize.height = showSize.height;
imageSize.width = imageSize.height * ratio;
} else {
if (ratioW > ratioH) {
if (showSize.width / imageSize.width <= 2) {
imageSize.width = showSize.width;
imageSize.height = imageSize.width / ratio;
}
} else {
if (showSize.height / imageSize.height <= 2) {
imageSize.height = showSize.height;
imageSize.width = imageSize.height * ratio;
}
}
}
return imageSize;
}
then put your imageView align to left of the screen

just like this
imageView.contentMode = UIViewContentModeCenter;
if (imageView.bounds.size.width > imageView.size.width && imageView.bounds.size.height > imageView.size.height) {
imageView.contentMode = UIViewContentModeScaleAspectFit;
}

Swift
import UIKit
import AVFoundation
let originalsize = CGSizeMake(500, 500)
let rect = CGRectMake(0, 0, 320, 480)
var result = AVMakeRectWithAspectRatioInsideRect(originalsize, rect)
print(result)

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.

How to zoom from min to max coordinates positions in UIScrollView?

I have a UIScrollView, which hold an UIImageView. I have a requirements to reach and zoom to particular location in UIImageView.
So for e.g. I want to start from (x: 0, y: 0) to specified location.
What's the best practice to do that?
This is how I'm achieving this:
- (void) setInitialZoomLevelAndShowImageInCenter {
CGRect scrollViewFrame = scrollViewMap.frame;
CGFloat scaleWidth = scrollViewFrame.size.width / scrollViewMap.contentSize.width;
CGFloat scaleHeight = scrollViewFrame.size.height / scrollViewMap.contentSize.height;
CGFloat minScale = MIN(scaleWidth, scaleHeight);
scrollViewMap.minimumZoomScale = minScale/1.5;
scrollViewMap.maximumZoomScale = 10.0f;
scrollViewMap.zoomScale = minScale;
CGFloat newZoomScale = scrollViewMap.zoomScale * 2.80f;
CGFloat xPos = 0;
CGFloat yPos = 0;
BOOL isMatched = NO;
while (!isMatched) {
[self zoomToPoint:CGPointMake(xPos, yPos) withScale:newZoomScale animated:YES];
BOOL isAnyChange = NO;
if(xPos <= slotItem.xCord) {
xPos+=1.0f;
isAnyChange = YES;
}
if(yPos <= slotItem.yCord) {
yPos+=1.0f;
isAnyChange = YES;
}
if(!isAnyChange) {
isMatched = YES;
}
}
}
- (void)zoomToPoint:(CGPoint)zoomPoint withScale: (CGFloat)scale animated: (BOOL)animated
{
//Normalize current content size back to content scale of 1.0f
CGSize contentSize;
contentSize.width = (scrollViewMap.contentSize.width / scrollViewMap.zoomScale);
contentSize.height = (scrollViewMap.contentSize.height / scrollViewMap.zoomScale);
//derive the size of the region to zoom to
CGSize zoomSize;
zoomSize.width = scrollViewMap.bounds.size.width / scale;
zoomSize.height = scrollViewMap.bounds.size.height / scale;
//offset the zoom rect so the actual zoom point is in the middle of the rectangle
CGRect zoomRect;
zoomRect.origin.x = zoomPoint.x - zoomSize.width / 2.0f;
zoomRect.origin.y = zoomPoint.y - zoomSize.height / 2.0f;
zoomRect.size.width = zoomSize.width;
zoomRect.size.height = zoomSize.height;
//apply the resize
[scrollViewMap zoomToRect: zoomRect animated: animated];
}

Table View UIImage rendering issue

I'm running into a rendering issue with my tableView UIImages and was wondering if anyone has encountered the same problem and knows how to fix it.
Here is my cellForRowAtIndexPath
-(UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
cell.textLabel.text = exerciseDisplayName;
cell.textLabel.numberOfLines = 0;
cell.textLabel.lineBreakMode = NSLineBreakByWordWrapping;
[tableView setSeparatorInset:UIEdgeInsetsZero];
UtilityMethods *commonMethods = [[UtilityMethods alloc]init];
UIImage *rowImage = [commonMethods imageForRow:tempPlaceholder.bodyPart];
cell.imageView.image = rowImage;
return cell;
}
Here is my height for row.
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 96;
}
There are lots of lines and squiggles in the images in the table. I was wondering if anyone knowns any UIImage properties that I might need to apply to my image to fix the problem. Increasing the height for row in table fixes the problem at the expense of increasing the height of the table row. The number that seems to work is 128 in heightForRow. When using 128 the squiggles are much less noticeable. Now I'm pretty sure this has something to do with how iOS is rendering the image. Ive taken the image and resized it to 76x76 using Microsoft Paint just to see if I would see the same problem, and the images appear just fine without all the squiggles. The images are .png format. The original size of the images is 1024x1024. Ive just resized them downwards as I've needed them. If anyone has any tips or advice on how to fix this I'd really appreciate it.
You are going to need to resample the image to the size you need. Viewing a large image in a small space looks rather bad on iOS devices (most any really). But if you use built in functions to create a new UIImage of the proper size everything looks much better. Scaling down a UIImage when displaying will always look worse than creating a new image of the proper size and displaying that. The way to do this is as follows (taken from here):
- (UIImage*)imageByScalingAndCroppingForSize:(CGSize)targetSize
{
UIImage *sourceImage = self;
UIImage *newImage = nil;
CGSize imageSize = sourceImage.size;
CGFloat width = imageSize.width;
CGFloat height = imageSize.height;
CGFloat targetWidth = targetSize.width;
CGFloat targetHeight = targetSize.height;
CGFloat scaleFactor = 0.0;
CGFloat scaledWidth = targetWidth;
CGFloat scaledHeight = targetHeight;
CGPoint thumbnailPoint = CGPointMake(0.0,0.0);
if (CGSizeEqualToSize(imageSize, targetSize) == NO)
{
CGFloat widthFactor = targetWidth / width;
CGFloat heightFactor = targetHeight / height;
if (widthFactor > heightFactor)
{
scaleFactor = widthFactor; // scale to fit height
}
else
{
scaleFactor = heightFactor; // scale to fit width
}
scaledWidth = width * scaleFactor;
scaledHeight = height * scaleFactor;
// center the image
if (widthFactor > heightFactor)
{
thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5;
}
else
{
if (widthFactor < heightFactor)
{
thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5;
}
}
}
UIGraphicsBeginImageContextWithOptions(targetSize, 0, NO); // this will crop
CGRect thumbnailRect = CGRectZero;
thumbnailRect.origin = thumbnailPoint;
thumbnailRect.size.width = scaledWidth;
thumbnailRect.size.height = scaledHeight;
[sourceImage drawInRect:thumbnailRect];
newImage = UIGraphicsGetImageFromCurrentImageContext();
if(newImage == nil)
{
NSLog(#"could not scale image");
}
//pop the context to get back to the default
UIGraphicsEndImageContext();
return newImage;
}
That function does a bit more than you are looking for, but you should be able to cut it does to only what you need.
Make sure to use the UIGraphicsBeginImageContextWithOptions function instead of UIGraphicsBeginImageContext so you deal with retina displays properly, otherwise this will make your images more blurry than they should be and you will have a second problem to deal with.

UIScrollview calculation of new CGRect after ZoomToRect

My problem is i am not able to get the exact CGRect value after zooming for zooming in UIScrollview i am using zoomToRect method of UIScrollview. while zooming i am setting the contentOffset property.
Code follows:
if(image != nil) {
CGSize zoomViewSize = image.frame.size;
CGSize scrollViewSize = self.bounds.size;
if(zoomViewSize.width < scrollViewSize.width) {
anOffset.x = -(scrollViewSize.width - zoomViewSize.width) / 2.0;
}
if(zoomViewSize.height < scrollViewSize.height) {
anOffset.y = -(scrollViewSize.height - zoomViewSize.height) / 2.0;
}
}
super.contentOffset = anOffset;
after zooming i am setting the content inset property so that image comes in the center. for content inset the code is given below.
-(void)zoomtorect:(CGRect)rect animated:(BOOL)animated {
[super zoomtorect:rect animated:YES];
CGFloat pageWidth = image.image.size.height;
CGSize imageSize = rect.size;
CGSize zoomedImageSize = CGSizeMake(imageSize.width * 0.2, imageSize.height * 0.2);
CGSize pageSize = self.bounds.size;
//scLayer.frame = rect;
UIEdgeInsets inset = UIEdgeInsetsZero;
if (pageSize.width > zoomedImageSize.width) {
inset.left = (pageSize.width - zoomedImageSize.width) / 2;
inset.right = inset.left;
}
if (pageSize.height > zoomedImageSize.height) {
inset.top = (pageSize.height - zoomedImageSize.height) / 2;
inset.bottom = inset.top;
}
self.contentInset = inset;
}
this code shifts my image view between screen. Every thing works fine here. My problem is i have to show only zoom portion of the imageView rest will be black. For calculating the zoomed area i am doing the following calculation.
CGSize imageSize = rect.size;
CGSize zoomedImageSize = CGSizeMake(imageSize.width * scroll.maximumZoomScale, imageSize.height *scroll.maximumZoomScale);
CGSize pageSize = scroll.bounds.size;
UIEdgeInsets inset = UIEdgeInsetsZero;
if (pageSize.width > zoomedImageSize.width) {
inset.left = (pageSize.width - zoomedImageSize.width) / 2;
inset.right = inset.left;
}
if (pageSize.height > zoomedImageSize.height) {
inset.top = (pageSize.height - zoomedImageSize.height) / 2;
inset.bottom = inset.top;
}
CGRect zoomRect = [scroll convertRect:rect fromView:image];
CGRect zoomRect1 = CGRectMake(inset.left, inset.top+50, zoomRect.size.width, zoomRect.size.height);
this zoomRect1 is the zoomed area of the image this value is not exact what i am seeing in the screen. some where i am doing calculation mistake please help me out. But i am not getting the exact value of the zoomed image area.
Thanks in advance
Use this.. Works Perfectly
- (void)handleDoubleTap:(UIGestureRecognizer *)recognizer
{
if(isAlreadyZoomed)
{
CGPoint Pointview = [recognizer locationInView:recognizer.view];
CGFloat newZoomscal = 3.0;
CGSize scrollViewSize = self.scrollContainer.bounds.size;
CGFloat width = scrollViewSize.width/newZoomscal;
CGFloat height = scrollViewSize.height /newZoomscal;
CGFloat xPos = Pointview.x-(width/2.0);
CGFloat yPos = Pointview.y-(height/2.0);
CGRect rectTozoom=CGRectMake(xPos, yPos, width, height);
[self.scrollContainer zoomToRect:rectTozoom animated:YES];
[self.scrollContainer setZoomScale:3.0 animated:YES];
isAlreadyZoomed = NO;
}
else
{
[self.scrollContainer setZoomScale:1.0 animated:YES];
isAlreadyZoomed = YES;
}
}
isAlreadyZoomed is a BOOL value

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