Flip UIImageViews for Right to Left Languages - ios

iOS automatically flips the entire ViewController when using a RTL language like Arabic and does a great job with most of the layout, especially text. The default behavior is to flip the layout but leave UIImageViews the same orientation (since you generally don't want to reverse images).
Is there a way to specify that some images should be flipped (such as arrows) when the phone is set to a RTL language?

iOS 9 includes the imageFlippedForRightToLeftLayoutDirection method that you can use, that automatically flips the image in a UIImageView when in an RTL localization.

The best solution I found to date is marking the image in the assets file as mirror.

We can use imageFlippedForRightToLeftLayoutDirection which returns flipped image if current language is RTL(right to left). i.e
Objective-c
UIImage * flippedImage = [[UIImage imageNamed:#"imageName"] imageFlippedForRightToLeftLayoutDirection];
Swift 3
let flippedImage = UIImage(named: "imageName")?.imageFlippedForRightToLeftLayoutDirection()
Source: Apple Docs

You have to manually flip the UIImages in the UIImageViews you want when the phone is set to a RTL language. This can be easily achieved with this code:
UIImage* defaultImage = [UIImage imageNamed:#"default.png"];
UIImage* flipImage = [UIImage imageWithCGImage:sourceImage.CGImage scale:1.0 orientation: UIImageOrientationUpMirrored];
myImageview.image = flipImage;

I ended up using localized images for the forward and back arrows. This had the advantage of not having to add code each place the image was used and gives the opportunity to clean up the arrows if there are gradients that don't work well flipped.

While we wait for iOS 9 improved right to left support you could create a UIImageView subclass and override setImage to mirror inside the images as #nikos-m suggests and calling super.image = flipImage.
That way you can easily set all the images views you want to flip using custom classes in Interface Builder instead of having to add IBOutlets.

Swift 5
If you want to individualize the image flip, you can register each image with the direction you want since the layout direction is a trait:
let leftToRight = UITraitCollection(layoutDirection: .leftToRight)
let rightToLeft = UITraitCollection(layoutDirection: .rightToLeft)
let imageAsset = UIImageAsset()
let leftToRightImage = UIImage(named: "leftToRightImage")!
let rightToLeftImage = UIImage(named: "rightToLeftImage")!
imageAsset.register(leftToRightImage, with: leftToRight)
imageAsset.register(rightToLeftImage, with: rightToLeft)
This is the same as configuring it in the asset catalogue as #SergioM answered.

Related

Memory issue decodeObjectForKey (Swift project)

Within an Swift application exporting the individual single viewController images (using the drawViewHierarchyInRect).
For each viewController I recover the contents of imageViews as follows:
self.imageView = (aDecoder.decodeObjectForKey("imageLevel") as? UIImageView)
self.imageView!.contentMode = UIViewContentMode.ScaleAspectFit
self.imageView!.multipleTouchEnabled = true
self.imageView!.autoresizesSubviews = true
self.addSubview(imageView!)
After 15 "page": crash. If I comment these lines, the code works again. Is there an alternative to decodeObjectForKey?
I'm not really sure what you're doing here, but you shouldn't be trying to encode a UIImageView and save it off as the view is tied to other items. You could encode the UIImage instead. Your UIImageView should come from your storyboard/xib and then you set the image you decoded to the UIImageView.

Merge two imageViews into one and save iOS swift

I have 2 imageViews like below. (ScrollView has subview of imageView)
i want to take the image of each one and merged to one.
i tried using taking screenshot and crop. but when it comes to different iphone screensizes and resolutions it doesn't work well.
can any one guide me how to do this?
Why not just add them both to one UIView?
It is also possible to add a subview to your image view and extend the frame.
[secondImageView setFrame:CGRectMake(x,y + newImageHeight,width,height)];
[self.myImageView setFrame:CGRectMake(x,y,width,height + newImageHeight)];
[self.myImageView addSubview:secondImageView];
I think your way is right, also you can solve scale size problem very easily with this method.
func mergeScreenshot() {
let layer = UIApplication.sharedApplication().keyWindow.layer
let scale = UIScreen.mainScreen().scale
UIGraphicsBeginImageContextWithOptions(layer.frame.size, false, scale); // reconsider size property for your screenshot
layer.renderInContext(UIGraphicsGetCurrentContext())
let screenshot = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
UIImageWriteToSavedPhotosAlbum(screenshot, nil, nil, nil)
}
But you should edit sizes again. For example if you're using autolayout you can create IBOutlet and than use it instead of layer.frame.size property which I used.
Hope it helps.

Repeat image horizontally and vertically

I want to repeat the following image:
to achieve the following background:
I tried a few codes as follow:
bluePatternView.backgroundColor = [UIColor colorWithPatternImage:
[[UIImage imageNamed:#"blue_pattern.png"] stretchableImageWithLeftCapWidth:0 topCapHeight:0]];
and:
bluePatternView.backgroundColor =
[[UIColor alloc] initWithPatternImage:[UIImage imageNamed:#"blue_pattern.png"]];
I also tried to draw image with CGContextDrawTiledImage with no success.
How that can be done?!
EDIT: result of implementing luk2302. please give him recognition by upvoting
bluePatternView.backgroundColor =
[UIColor colorWithPatternImage:[UIImage imageNamed:#"blue_pattern.png"]];
result:
I found solution in images.xcassets,
Step 1:- Put your image to images.xcassets
Step 2:- Click on image, then click on bottom right corner written “Show Slicing”
Step 3:- Click on Start Slicing
Step 4:- Click on "Slice Horizontally and Vertically" button
Step 5:- Here you will see 3-Horizontal and 3-Vertical slice lines.
Put the most left vertical line to left side of image and both right most lines to right side of image.
Put the most top line to top of image and both bottom most lines to bottom of image.
So the final result will be looking like this.
Step 6:- Use this image.
And now image will be repeated.
Note:- If you give slicing to 2x image it will repeat just 2x image, for 3x images you need to do the same slicing.
Example by Apple
As my comment already said: use
bluePatternView.backgroundColor =
[UIColor colorWithPatternImage:[UIImage imageNamed:#"blue_pattern.png"]];
You dont want to stretch your image. Let UIKit take care of the repetition.
Assuming that your bluePatternView is the actual large view for which you want to set a pattern as background. Maybe you are setting the background property of the wrong view if that code is still not working.
Note: duplicating the SAME image with #2x and #3x extension will lead to behaive properly for better resolution devices.
bluePatternView.backgroundColor = UIColor(patternImage: UIImage(named: "blue_pattern")!)
You need to save image in Assets then put those lines in viewdidload
bluePatternView.backgroundColor = UIColor.init(patternImage: #imageLiteral(resourceName: "f8"))
This is for Swift 4.1.
this with Bellow Method using stretchableImageWithLeftCapWidth like this way:-
UIImage *backgroundImage = [[UIImage imageNamed:#"SheetBackground.png"] stretchableImageWithLeftCapWidth:0.5 topCapHeight:0];
as par your need example:-
UIImage *backgroundImage = [[UIImage imageNamed:#"q4Ses.png"] stretchableImageWithLeftCapWidth:0.5 topCapHeight:0];
[_scro setBackgroundColor:[UIColor colorWithPatternImage:backgroundImage]];

Instantiate an image to appear at several different points on the screen?

I have an image called Empty.png, it is a small-ish square tile, how could I instantiate the image to appear at several different points on the screen?
Thank you for any help in advance :)
You can can place UIImageView's wherever you want the image to appear.And then set the image property of each image view as this image. (UIImage object).
If you are using interface builder then you just have to type in the name of the file in the attributes inspector of the imageview in the interface builder.
Or you could do this:
UIImage *img = [UIImage imageName:#"Empty.png"];
imageView.image = img; //Assuming this is your utlet to the image view.
It depends on how you want to use it.
If you just draw it with core graphics, let's say in drawInRect: or so, then you simply draw it several times.
If you want to display it within one or a number of image views, then instanciate your UIImageViews and assign the same object to all of them. Or let the Interface Builder do the instanciation for you. But you cannot add a single UIView object several times to one or a number of subview-hierarchies. If you add a UIView as subview to a view then it will disappear from the position where it was before.
10 UIImageView may use the same UIView but you need 10 UIImageViews to display all of them.
The same applies to UIButtons and every UI-thing that has an image or background image.
this will get you one image into some view
CGPoint position = CGPointMake(x,y);
UIImageView *img = [[UIImageView alloc] init];
img.image = [UIImage imageNamed:#"Empty.png"];
img.frame = CGRectMake(position.x, position.y, img.image.size.width, img.image.size.height);
[someUIView addSubview:img];
if you make an array for the positions (x,y) of all the images, then you can just run it in a for loop and it will place the images into the view at the positions you want
note: CGPoints cant be stored in an NSArray since its not an NSObject type, either use a C/C++ array or use something else that can fit into a NSArray

How to truncate a UIImage in iOS

How can I truncate the left side of an image stored in a UIImage object. Basically in certain situations I just want to show part of an image.
How can I do this on with the iOS sdk?
P.S. I tried changing the frame size of the UIImage but that just scales the image and distorts it.
A very simple way is to load the image into a UIImageView, and then add the view to another view. You can then position the image view so that its .frame.origin.x property is negative, which will place it off to the left. The parent view needs to have setMasksToBounds:YES called on it, or else the image view will still be fully-visible.
There are many other ways to achieve this effect as well, but this may be the simplest for you to implement.
to crop a UIImage, you can use one of the UIImage categories available out there, such as http://www.hive05.com/2008/11/crop-an-image-using-the-iphone-sdk/
For example, this frame will remove 100 pixel from the left side of a 200x200 pixel UIImage
CGRect clippedRect = CGRectMake(100, 0, 100, 200);
UIImage *cropped = [self imageByCropping:lightsOnImage toRect:clippedRect];

Resources