NSView not scaling all content - objective-c

I'm trying to scale an NSView for a larger display when I'm testing on my Mac screen, so I can see everything in proportion.
NSRect wFrame = self.window.frame;
wFrame.origin.x = 200;
wFrame.origin.y = 100; // from bottom of my screen
wFrame.size.width = 1080 * 0.5; // so it will fit on my screen
wFrame.size.height = 1920 * 0.5;
[self.window setFrame:wFrame display:YES]; // the window is smaller, but not everything is scaled (e.g., font sizes)
That creates the correct size window, and most of the contents are drawn at half size. But, some things are not scaled.
An NSButton's title text is still the original, large size. If the button contains an image, the image is scaled properly.
The content of a WebView are not rendered at the small size.
How can I scale all of the content, including button titles and Webview content?

I found the answer here: https://stackoverflow.com/a/33293423/236415
I wrapped my full sized NSView (and its subviews) in an NSScrollView (sized for my screen) and then set the magnification to 0.5.

Related

Make image smaller inside UIImageView

I have an UIImageView that shows and image of a creditCard, My problem is that I want to make boarders around it, so the credit card wont touch the edges of the UIimageView, I dont want to change the UIImageView position on the screen so what can I do ?
image 1
image 2
( unlike the example of the blue card it dosnt have to leave spaces only from the sides, it could shrink it from all sides )
You basically have (3) three options that can fix this.
Adjust the UIViewContentMode contentMode of the UIImageView so that it appropriately displays the image (this will only work however if the image you are using scales to fit without touching the border.
Use a UIButton instead and simply adjust the image insets until your satisfied (just disable the button or set user interaction to no here to "mimic" an image view)
Create a wrapper method that creates a new image to your desired size. Something like this should work just fine
CGSize size = CGSizeMake(< some width > , < some height >);
Then just create a new image capture with the size you've chosen
CGFloat scale = MAX(size.width/image.size.width, size.height/image.size.height);
CGFloat width = image.size.width * scale;
CGFloat height = image.size.height * scale;
CGRect imageRect = CGRectMake((size.width - width)/2.0f,
(size.height - height)/2.0f,
width,
height);
UIGraphicsBeginImageContextWithOptions(size, NO, 0);
[image drawInRect:imageRect];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
From here you should then be able to just apply a border width and color to get your desired result!
I guess a fourth (4th) option could be manually shrinking the image (with some photo editor) so that it renders (fits) into your image view with the appropriate padding around the image. I think the others are easier and best practice though.

UIImageView not cropping to circle

I have a UIImageView. For some reason, the circle crop is not working properly. What it winds up doing is cropping the edges to a circle, but leaves the sides completely straight, any ideas why?
Here is my code:
self.avatarTwo.layer.cornerRadius = self.avatarTwo.frame.size.height /2;
self.avatarTwo.layer.masksToBounds = YES;
self.avatarTwo.layer.borderWidth = 0;
The image is 2448 by 3264 (pixels) and this is how it looks right now cropped:
Although the UIImageView is square, the UIImage's height is much larger than the width. The default content mode for UIImageView is UIViewContentModeScaleToFill which scales the content "to fit the size of itself by changing the aspect ratio of the content if necessary." To make the image centered and filling the UImageView you must use:
self.avatarTwo.contentMode = UIViewContentModeScaleAspectFill;
See contentMode for more information on this.
In essence, your UIImageView is being cropped fine, but the content in that image view is being scaled to not crop any of the content.

Get image from AVCaptureVideoPreviewLayer

I'm essentially cloning Cropping a captured image exactly to how it looks in AVCaptureVideoPreviewLayer since asking the original poster if they found a solution isn't an "answer" and I am unable to comment yet because I don't have enough reputation...
The app I'm building will always be in portrait mode because rotation isn't important in this case.
I have an AVCaptureSession with the AVCaptureVideoPreviewLayer connected to a UIView of size 320x240 that is positioned against the top layout guide.
I have capturing the input working but the image that I'm receiving is skewed and shows a lot more than the portion I'm displaying. How can I capture just the area that is shown in my AVCaptureVideoPreviewLayer?
Have a look at AVCaptureVideoPreviewLayer s
-(CGRect)metadataOutputRectOfInterestForRect:(CGRect)layerRect
This method lets you easily convert the visible CGRect of your layer to the actual camera output.
One caveat: The physical camera is not mounted "top side up", but rather rotated 90 degrees to the right. (So if you hold your iPhone - Home Button right, the camera is actually top side up).
Keeping this in mind, you have to convert the CGRect the above method gives you, to crop the image to exactly what is on screen.
Example:
CGRect visibleLayerFrame = THE ACTUAL VISIBLE AREA IN THE LAYER FRAME
CGRect metaRect = [self.previewView.layer metadataOutputRectOfInterestForRect:visibleLayerFrame];
CGSize originalSize = [originalImage size];
if (UIInterfaceOrientationIsPortrait(_snapInterfaceOrientation)) {
// For portrait images, swap the size of the image because
// here, the output image is actually rotated relative to what you see on screen.
CGFloat temp = originalSize.width;
originalSize.width = originalSize.height;
originalSize.height = temp;
}
// metaRect is fractional, that's why we multiply here
CGRect cropRect;
cropRect.origin.x = metaRect.origin.x * originalSize.width;
cropRect.origin.y = metaRect.origin.y * originalSize.height;
cropRect.size.width = metaRect.size.width * originalSize.width;
cropRect.size.height = metaRect.size.height * originalSize.height;
cropRect = CGRectIntegral(cropRect);
This may be a bit confusing, but what made me really understand this is this:
Hold your device "Home Button right" -> You'll see the x - axis actually lies along the "height" of your iPhone, while the y - axis lies along the "width" of your iPhone. That's why for portrait images, you have to swap the size ;)

Problems scaling a UIImage to fit a UIButton

I have a set of buttons and different sized images. I want to scale each image in order that it fits the button in the correct aspect ratio. Once I've scaled the image, I set the button's image property to the scaled version.
UIImage *scaledImage = [image scaledForButton:pickerButton];
[pickerButton setImage:scaledImage forState:UIControlStateNormal];
my scaledForButton method is defined in a class extension for UIImage. It looks like this:
- (UIImage *)scaledForButton:(UIButton *)button
{
// Check which dimension (width or height) to pay respect to and
// calculate the scale factor
CGFloat imageRatio = self.size.width / self.size.height;
CGFloat buttonRatio = button.frame.size.width / button.frame.size.height;
CGFloat scaleFactor = (imageRatio > buttonRatio ? self.size.width/button.frame.size.width : self.size.height/button.frame.size.height);
// Create image using scale factor
UIImage *scaledimage = [UIImage imageWithCGImage:[self CGImage]
scale:scaleFactor
orientation:UIImageOrientationUp];
return scaledimage;
}
When I run this on an iPad2 it works fine and the images are scaled correctly. However if I run it on a retina display (both in the simulator and on a device) the image does not scale correctly and is squished into the button.
Any ideas why this would happen on retina only? I've been scratching my head for a couple of days but can't figure it out. They're both running the same iOS and I've checked the scale and ratio outputs, which are always the same, regardless of device. Many thanks.
Found the answer here: UIButton doesn't listen to content mode setting?
If you're setting the .contentMode, it seems you have to set the imageView property of the UIButton, not just the UIButton, then it worked properly.
The problem on iPad 3 was as Herman suggested - the CGImage was still a lot larger than the UIButton, so even though it was scaled down, it still had to be resized to fit the button.

Maintain scroll position in UIWebView when resizing

I have a UIWebView which resizes when the device is rotated. When the webview is resized the scroll position from the top of the page remains the same, but since the height of the content is changing, you end up in a different place at the end of the rotation.
The content of the webview is text and images which are not being scaled to fit. At a smaller width the text breaks more making it taller.
Is there a good way to maintain the scroll position?
One way to kind of work around this problem is to adjust the contentOffset of the webviews's scrollview after a rotation. Due to changes in line breaks in texts the overall size of the page may change during a rotation.
So to solve this, you have to save the old size of the webviews content in the "willRotateToInterfaceOrientation"-method, then calculate the relative change in the "didRotateFromInterfaceOrientation"-method and adjust the scrollviews contentOffset. (That 'almost' solve the problem - i say almost because due to the changes in line breaks, you might end up one or two lines off your desired position.)
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
oldSize = self.webView.scrollView.contentSize;
}
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
CGSize newSize = self.webView.scrollView.contentSize;
float xFactor = newSize.width / oldSize.width;
float yFactor = newSize.height / oldSize.height;
CGPoint newOffset = webView.scrollView.contentOffset;
newOffset.x *= xFactor;
newOffset.y *= yFactor;
webView.scrollView.contentOffset = newOffset;
}
Take a look at my solution: https://github.com/cxa/WebViewContentPositioner. In short, I use document.caretRangeFromPoint(0, 0) to capture the Range, and insert an element to track its position. After resizing, use the captured Range info to decide position.