ios 7 - Force view layout flip to RTL without language change - ios

I have a few views in my app that need to be able to display both LTR and RTL content (not at the same time though), and it has to be unrelated to the general app layout direction. Meaning, I want to be able to tell a specific view to flip its layout from LTR to RTL and vice versa, on the fly, without changing the system language.
I researched this quite a bit, but aside of the following two solutions, it seems like it's not possible:
Flip layout on iPhone for RTL languages
How to force "Respect Language Direction" from RTL to LTR and vice versa
The first solution is not relevant in my case. The second solution gave me the idea to just keep two versions for every view, one for RTL and one for LTR, and use the relevant one on the fly. That means I'm going to have to update twice the views on every UI update though.
A third solution, of course, is to manually change the view's layout, programatically, according to the relevant direction, before showing the view.
So, are those my only options?
P.S: I'm talking about the layout only, not the localisation strings, as i'm handling the proper text myself.

I found it's quite easy to implement that, just:
func setRTL(_ sender: UIButton) {
UIView.appearance().semanticContentAttribute = .forceRightToLeft
UINavigationBar.appearance().semanticContentAttribute = .forceRightToLeft
if let vc = storyboard?.instantiateViewController(withIdentifier: "root") {
UIApplication.shared.keyWindow?.rootViewController = vc
}
}
Preview:
And check out the full DEMO.

As of iOS 9, you are now able to do this on a per-view basis using UIView's semanticContentAttribute property. If you are using Auto Layout or if your controls are/inherit from UIKit, they should just do the right thing whenever this property is set.
Do note that for labels, text fields and views, you might also have to change the text alignment depending on the text you are displaying.

Related

MKMapView Legal label shows as <unlocalized>

I've added an MKMapView as a subview on one of my ViewControllers in an XIB. The map works alright in terms of showing directions. But the Legal text on the map (bottom left) shows as <unlocalized> instead of having a text saying Legal in whatever language is selected (or even English).
How do I fix this? Thanks.
Note: My app supports 6 languages if it makes a difference (but none of the XIBs are localized)
I couldn`t reproduce this but it seems like an issue in the localization file. This guy has a similar problem and resolved it by removing localization files (and creating new I think).
Of course, you can always set directly your localized string to Legal MKAttributionLabel, by getting it from MKMapView subviews, and using setValue(_:forKey:) with _innerText and _strokeText keys. But notice that this is private API :)
I can think of 2 possible solution but didn't. One is to check which subview of all your MKMapView's subviews for that specific label and add move it out of the window or scale it down to 0. The other one would be similar but by subclassing you MKMapView and try to hide this label in layoutSubviews method.

Accessibility for controls in stack view

I have a horizontal stackview with a button and label horizontally
When I turn on voice over, text in these buttons are not reading at all. All others works fine.
Below is how i setup my code. Please guide how to enable these. Not sure why this isn't working
I have my button text and label text taking dynamic values
Also if any info why the accessibilityIdentifier is used would really help. I couldn't find clear explanation for this
self.myHorizontalStackView.isAccessibilityElement = true
//Accessibility for Button
self.submitButton.isAccessibilityElement = true
self.submitButton.accessibilityTraits = UIAccessibilityTraitStaticText
self.submitButton.accessibilityLabel = screenControls.buttonTitle
//Accessibility for Label
self.addressLabel.isAccessibilityElement = true
self.addressLabel.accessibilityTraits = UIAccessibilityTraitStaticText
self.addressLabel.accessibilityLabel = screenControls.address1
So the problem looks like it's coming from your stackView itself. See this other SO question/answer on the subject:
If a container view is accessible, its child views are often obscured to avoid confusion about what the user is trying to interact with.
So here, change your first line in the snippet you shared to:
self.myHorizontalStackView.isAccessibilityElement = false
and that should enable VoiceOver to find the subviews of the stackView.
As far as your other question:
Also if any info why the accessibilityIdentifier is used would really help. I couldn't find clear explanation for this
If you are asking what the identifier would be used for, it's primarily for testing purposes. By setting unique identifiers to your views, your tests can easily use the accessibility engine to find specific views and perform any actions you'd want to test. In terms of VoiceOver, the accessibilityIdentifier does not have a role.

UIsegmentedControl title appearance

HI, i set my uisegmentedcontrol's width manually, but when the width gets too small, the words becomes ...
Is that anyway that it won't behave in this way? Instead, i just want to show the text just like the picture shown below.
I'd suggest changing your design here and going for a different approach.
The design that you seem to want makes readability pretty much impossible.
Plus, what happens if I'm using your app and add another "Active Project". What happens if I have 10 active projects?
Take the fact that the UI does not work as a sign that you are using the wrong UI for the problem you are trying solve.
I'd suggest possibly just have the current project title here with a button to maybe present a list of projects to switch to... or something.
The text has been truncated. If you want it to fit your segment, you need to update the segment control size based on the text length. If you just want to get rid of truncation, you can use the following snippet. However, it's not recommended, as later Apple might change the UISegmentControl hierarchy.
for item in segmentedControl.subviews {
for subview in item.subviews {
if subview.isKind(of: UILabel.self) {
let _label = subview as! UILabel
_label.numberOfLines = 0
_label.lineBreakMode = .byWordWrapping
}
}
}

Disable RTL direction for UICollectionView

I'm building a custom calendar view with UICollectionView. Everything is pretty well but when I tried to test when language is set to Arabic, the cells are listed from right to left. Is there a way to disable this in RTL mode.
I have checked the documentation but there is no such option.
You can disable it by setting view semantics property
You have to set it on UICollectionView
there is a property in UIView Class
semanticContentAttribute
with following value
UISemanticContentAttributeUnspecified = 0,
UISemanticContentAttributePlayback,
UISemanticContentAttributeSpatial,
UISemanticContentAttributeForceLeftToRight,
UISemanticContentAttributeForceRightToLeft
To Disable RTL on specific view in Swift 4.
myView.semanticContentAttribute = .unspecified

iOS 7 status bar overlaps with view - did they have to make it like this?

I know this has been asked before, but none of these solutions work, and that's the reason of my posting. Please do not close before considering my case.
My plist already has UIViewControllerBasedStatusBarAppearance = false.
I have already tried applying deltas, but to no result.
Changing the top level view frame in ViewWillAppear (like self.view.frame) did not succeed.
I thought of increasing the view height (storyboard attribute inspector), in combination with deltas, but my top level view X, Y are disabled in storyboard attribute inspector.
My main view doesn't have any children views because I load them into main view either dynamically or load them from XIBs which are again shared by more than view controllers. These XIBs provide layout for both Portrait and Landscape. I don't know what approach is ideal for this kind of configuration, but I would like it better if solution lies along these lines.
This approach worked partially, but gave me inconsistent results.
What makes the solution tricky is the fact that I have to support all 4 orientations - this is something I handle in code via didRotate and willRotate delegates for my other views, but failing to do it for statusbar.
Please help...
Could this link be of any help?
You might have to use the new setEdgesForExtendedLayout: method to get this working consistently?
Also, have a look at these official docs if you haven't already done so.
I ended up writing my own function to shift my all subviews (remember, not top level views whose frame is fixated by IB).
It didn't spoil my work but imagine if this was the case for a very big project with so many screens, the limitations would have made it a nightmare.

Resources