How to set content mode when using FFImageLoading on button - ios

I am not able to get the content mode working on button when I am setting the image using FFImageLoading library.I want to set the mode to ScaleAspectFill.
I tried setting the content mode of the button.imageview as well as the button itself.
button.ContentMode = UIViewContentMode.ScaleAspectFill;
button.ImageView.ContentMode = UIViewContentMode.ScaleAspectFill;
ImageService.Instance.LoadUrl(image_url).Into(button);
The image is not scaling and is appearing as ScaleAspectFit rather than Fill

Setting the button's ImageView's ContentMode will adjust the image's representation.
I used the code below to display two buttons. One has set the ContentMode and another doesn't:
UIButton btn = new UIButton(UIButtonType.Custom);
btn.Frame = new CoreGraphics.CGRect(50, 100, 100, 40);
btn.ImageView.ContentMode = UIViewContentMode.ScaleAspectFill;
ImageService.Instance.LoadUrl("https://img-prod-cms-rt-microsoft-com.akamaized.net/cms/api/am/imageFileData/RE1Mu3b?ver=5c31").Into(btn);
UIButton btn2 = new UIButton(UIButtonType.Custom);
btn2.Frame = new CoreGraphics.CGRect(50, 200, 100, 40);
ImageService.Instance.LoadUrl("https://img-prod-cms-rt-microsoft-com.akamaized.net/cms/api/am/imageFileData/RE1Mu3b?ver=5c31").Into(btn2);
View.AddSubview(btn);
View.AddSubview(btn2);
They have different effects:
The first button doesn't have enough width to display this image so it clips the left and right edges due to the configuration of content mode. But the second button stretches the image to fit the whole space. Both buttons have the same size.

Related

Why Imageview always stretched show image stretched iOS?

I am using an imageView and it contains different images, but some images are stretched. How do I display the images without any stretch? I have set the contentMode to aspect fit. However, the images are not in the size of the imageView, and it is in different sizes. I want to show the images as the same size without stretching.
imageview1 = [[UIImageView alloc]initWithFrame:CGRectMake(30, 10, 190, 190)];
imageview1.contentMode = UIViewContentModeScaleAspectFit;
imageview1.clipsToBounds = YES;
Please try setting content mode before setting frame like below
imageview1.contentMode = UIViewContentModeScaleAspectFit;
imageview1 = [[UIImageView alloc]initWithFrame:CGRectMake(30, 10, 190, 190)];
imageview1.clipsToBounds = YES;
If you want to display each image without stretching and of same size, than set contentMode property of UIImageView's instance to UIViewContentModeScaleAspectFill. For instance-
imageview1 = [[UIImageView alloc]initWithFrame:CGRectMake(30, 10, 190, 190)];
imageview1.contentMode = UIViewContentModeScaleAspectFill;
imageview1.clipsToBounds = YES;
UIViewContentModeScaleAspectFill, will fill the entire area of image view, keeping the aspect ratio intact. In the process of filling entire image view, either vertical or horizontal length will be fully covered and the filling will continue till the time other dimension is fully filled. In the process, your content(either across vertical or horizontal) will be visible outside the frame. To clip this extra content we have set clipsToBounds property of image view to YES.
UIViewContentModeScaleAspectFit, will fill the image view's area till the time any one length either vertical or horizontal is fully filled keeping the aspect ratio intact. Its useful, if you are not required to show each image as same size as the other direction (if vertical is fully filled than horizontal or vice versa), is not fully covered. Since this will show blank spaces in the direction which is not fully covered.

Can't display image in custom keyboard

i'm building custom keyboard for ios 8, so i want to display one image here but it's seems not work.
I really don't know why, here is my code:
var img = UIImageView()
img.frame = CGRectMake(0, 0, 50, 50)
img.image = UIImage(named: "interesting.jpg")
self.view.addSubview(img)
Nothing appear but if i change to display an UILabel, it's ok.
When i move this code to ViewController image display fine.
I couldn't display image in keyboard area only.
I think you could do this: UIImage(named: "interesting") and have the name of the image in the asset catalog be interesting

Scaling down a UIButton's background image when using initWithFrame:

This is the first time I have ever designed an iOS app so I want to make sure I understand this behavior correctly.
I designed a custom bar button icon for a navigation bar in Photoshop. The final image that I saved in Photoshop was 102 x 45, and yes I realize that these dimensions are bigger than the recommended 44x44 in the iOS 7 design guidelines.
Anyways, I placed my image into the asset folder, and then programmatically set the bar button item with the following code:
UIImage* firstButtonImage = [UIImage imageNamed:#"loginbutton1"];
CGRect frame = CGRectMake(0, 0, 102, 45);
UIButton * someButton = [[UIButton alloc] initWithFrame:frame];
[someButton setBackgroundImage:firstButtonImage forState:UIControlStateNormal];
[someButton addTarget:self action:#selector(didTapLoginButton:)
forControlEvents:UIControlEventTouchUpInside];
self.rightBarButton = [[UIBarButtonItem alloc] initWithCustomView:someButton];
self.navItem.rightBarButtonItem = self.rightBarButton;
As you can see I set the frame's width and height to the exact size of the image. When I first ran the app, I didn't like the image and thought it was too big. So I changed the width and height parameters in this statement:
CGRect frame = CGRectMake(0, 0, 70, 30);
And now the image looks perfect on the iPhone screen. This is on an iPhone 4s.
So my main question is, what is actually happening when I change the frame size? Since the frame is now smaller than the actual image size, does the image just get scaled down automatically to fit inside the frame?
Yes the image get scaled because you are using backgroundImage (not Image). Both images have different behaviors.
Check the Xcode Interface Builder, you can see there, that you can set two images: Image and Background. Background is the UIImage that get scaled for the whole frame of the UIButton.
The UIButton Class Reference allows you to access the imageView of the image (not theimageView of the backgroundImage)
Because you have access to the imageView, you can change the mode of the image with:
[[someButton imageView] setContentMode:UIViewContentModeBottomLeft];
In UIView Class Reference you can check all the UIViewContentModes provided by Apple.
You can check that changing a little bit your code:
[someButton setImage:firstButtonImage forState:UIControlStateNormal];
[[someButton imageView] setContentMode:UIViewContentModeBottomRight];

Shifting text in a UITextField when using leftView

Currently I am setting a leftView with an image and I am finding that the image is too close to the text input view (which in this case is the standard UITextField text input view). Is there a way to shift the frame of the text input view slightly so as to increase the distance between it and the leftView?
You should be able to modify the frame property for the UIImageView you're assigning to the UITextField's leftView.
For example you might be able to do something like this:
UIImageView *someImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"someImage"]];
// add 5 points to each side of the frame while keeping the same center point
someImageView.frame = CGRectInset(someImageView.frame, -5, 0);
textField.leftViewMode = UITextFieldViewModeAlways;
textField.leftView = someImageView;
Note that you may also need to modify the UIImageView's contentMode property to get the desired effect (e.g. you can use UIViewContentModeLeft to left-align the image or UIViewContentModeCenter to center-align it).

How do I prevent a button's background image from stretching?

I'm allocating a UIButtonTypeCustom to a UIView with a background image that is smaller than the button's frame.
Reason why the image is smaller is because I'm trying to add more of a "target area" for the UIButton. However, the image is being scaled to the full size of the frame, rather than just being the image's size.
I have tried setting the UIButton and UIButton's imageView's contentMode property to UIViewContentModeScaleAspectFit, but no luck, the image still gets stretched out.
Is there a way to do what I'm trying to do programmatically?
Thanks in advance!
A lot of people make the same mistake you do in regards to button images and then jump through hoops trying to make the button behave as they expect it to. Let's clear this up once and for all:
A UIButton has two types of images it can display -- a foreground image and a background image. The background image for a button is expected to replace the button's background texture. As such, it makes sense that it stretches to fill the entire background. However, the button's foreground image is expected to be an icon that may or may not display alongside text; it will not stretch. It may shrink if the frame is smaller than the image, but it will not stretch. You can even set the alignment of the foreground image using the Control alignment properties in Interface Builder.
A button's foreground and background image can be set in code like this:
// stretchy
[self setBackgroundImage:backgroundImage forState:UIControlStateNormal];
// not stretchy
[self setImage:forgroundImage forState:UIControlStateNormal];
You don't have access to the background imageView, but there is fully working workaround:
EDIT: There is an even better workaround then what I posted originally.
You can create a UIImage from any color, and call -setBackgroundImage:forState.
See bradley's answer, here:
https://stackoverflow.com/a/20303841/1147286
Original answer:
Instead of calling -setBackgroundImage:forState:, create a new UIImageView and add it as a subview of the button.
UIImageView *bgImageView = [[UIImageView alloc] initWithImage:img];
bgImageView.contentMode = UIViewContentModeScaleAspectFit;
[bgImageView setFrame:CGRectMake(0, 0, videoButton.frame.size.width, videoButton.frame.size.height)];
bgImageView.tag = 99;
[yourButton addSubview:bgImageView];
[yourButton bringSubviewToFront:yourButton.imageView];
Create the imageview
Set the content mode and frame
I also set a recognizable tag, so that when the screen rotates I can easily find my custom imageView in the button's subviews and reset its frame
Add it as a subview to the button
Bring the frontal imageView of the button to the front so our custom imageView doesn't overlap it
When the button needs to rotate just find the imageView by its tag and reset its frame:
UIImageView *bgImageView = (UIImageView *)[button viewWithTag:99];
[bgImageView setFrame:CGRectMake(0, 0, newWidth, newHeight)];
The cleanest and easiest way it probably to use the title insets of the button.
You set your image as the button image, and then you change the left title inset to match minus the width of your image:
myButton.titleEdgeInsets = UIEdgeInsetsMake(0, -myImage.width, 0, 0)
This will move the text back where it was before the image was added to its left. You can also use this value to add some padding to you button.
Stumbled on this problem too.
Adding image programmatically, as memmons thoroughly explained, did not help:(
I had a button 100x40 and image 100x100, it would appear squeezed, not fitted, as one would infer from "Aspect Fit" option. Actually, non of those view options had an effect.
I just had to rescale it so it would fit on a button, then use setImage:
UIImage *img=[UIImage imageNamed:#"myimage.png"];
CGImageRef imgRef = [img CGImage];
CGFloat imgW = CGImageGetWidth(imgRef);
CGFloat imgH = CGImageGetHeight(imgRef);
CGFloat btnW = myBttn.frame.size.width;
CGFloat btnH = myBttn.frame.size.height;
//get lesser button dimension
CGFloat minBtn=btnW;
if (btnW>btnH) {
minBtn=btnH;
}
//calculate scale using greater image dimension
CGFloat scl=imgH/minBtn;
if (imgW>imgH) {
scl=imgW/minBtn;
}
//scale image
UIImage *scaledImage = [UIImage imageWithCGImage:[img CGImage] scale:(img.scale * scl) orientation:(img.imageOrientation)];
//clean up
UIGraphicsEndImageContext();
//set it on a button
[myBttn setImage:scaledImage forState:UIControlStateNormal];
It is simple as:
ImageBtn.imageView?.contentMode = .scaleAspectFit
ImageBtn.setImage(chosenImage, for: .normal)
Another consideration is the BaseLine constraint. If your buttons have this constraint set (depicted as a horizontal or vertical line through multiple controls on your layout), it will cause your images to stretch without stretching the underlying button control. If your button is otherwise properly constrained (leading/trailing and top/bottom spaces, and etc...) removing the BaseLine constraint should have no impact on the layout, while allowing the foreground image to scale properly to the underlying button shape.
Answerbot answers the question with what is proper and correct to do. Don't fight the OS and use things as intended is always good advice. However, sometimes you need to break the rules.
I was able to mask the enlarged background image (not prevent it) by overlaying it with a black CAlayer then overlaying again with a properly resized image CAlayer. This was all done by creating a subclass of UIButton and overwriting the setHighlighted method.
NEED CODE?
- (void)setHighlighted:(BOOL)highlighted
{
super.highlighted = highlighted;
//
//Whenever an image needs to be highlighted, create a dimmed new image that is correctly sized. Below it is a englarged stretched image.
//
if (highlighted != _previousHighlightedSate)
{
_previousHighlightedSate = highlighted;
if (highlighted)
{
//Create a black layer so image can dim
_blackLayer = [CALayer layer];
_blackLayer.bounds = self.bounds;
CGRect rect = _blackLayer.bounds;
rect.size.width = rect.size.width*2;
rect.size.height = rect.size.height*2;
_blackLayer.bounds = rect;
_blackLayer.backgroundColor = [[UIColor blackColor] CGColor];
//create image layer
_nonStretchImageLayer = [CALayer layer];
_nonStretchImageLayer.backgroundColor = [UIColor blackColor].CGColor;
_nonStretchImageLayer.bounds = CGRectMake(0 , 0, self.bounds.size.width, self.bounds.size.height);
_nonStretchImageLayer.frame = CGRectMake(0 , 0, self.bounds.size.width, self.bounds.size.height);
_nonStretchImageLayer.contentsGravity = kCAGravityResizeAspect;//default is to resize
_nonStretchImageLayer.contents = (id)self.imageView.image.CGImage;
_nonStretchImageLayer.opacity = 0.5;
//add layers to image view
[self.imageView.layer addSublayer:_blackLayer];
[self.imageView.layer addSublayer:_nonStretchImageLayer];
}
else
{
//remove from image view
[_blackLayer removeFromSuperlayer];
[_nonStretchImageLayer removeFromSuperlayer];
//nil them out.
_blackLayer = nil;
_nonStretchImageLayer = nil;
}
}
Inspiration for this work around came from here
I guess the easiest solution is to use UIImage's resizableImageWithCapInsets method. Use UIEdgeInsetsMake to configure the free spaces.
might help someone
button.subviews.first?.contentMode = .scaleAspectFit
Swift version of Zoltán Matók answer
Just a copy of my code using SnapKit to do auto layout and syntatic sugar Then library for initilizations, it should work similar for normal Apples way of programatic layout.
let backButton = UIButton(type: .custom).then { (button) in
let image = UIImage(named: "backButtonIcon")?.withRenderingMode(.alwaysOriginal)
let imageView = UIImageView(image: image)
button.addSubview(imageView)
imageView.snp.makeConstraints { (make) in
make.center.equalTo(button.snp.center)
}
button.bringSubviewToFront(imageView)
button.contentMode = .scaleAspectFit
button.backgroundColor = .clear
button.isUserInteractionEnabled = true
button.isEnabled = true
button.imageView?.contentMode = .scaleAspectFit
button.imageView?.snp.makeConstraints({ (make) in
make.height.width.equalTo(24)
})
button.snp.makeConstraints { (make) in
make.height.width.equalTo(24)
}
}
You can use uibutton.imageView.contentMode for no stretching:
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(posX, posY, widthButton, heightButton);
[button setTitle:#"" forState:UIControlStateNormal];
[button setImage:[UIImage imageNamed:#"imageNamed"] forState:UIControlStateNormal];
[button setImage:[UIImage imageNamed:#"imageNamedHighlighted"] forState:UIControlStateHighlighted];
button.imageView.contentMode = UIViewContentModeScaleAspectFit;
[button addTarget:self action:#selector(functionMenu:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview: button];
What you need to do is add your image as a UIImageView.
Than add a button with transperent background (UIColor ClearColor) on top of it with your desired width and height.

Resources