Swift Textview Align with English and Arabic Languages

Arabic Text Alignment

you can try this code:

let currentDeviceLanguage = Locale.current.languageCode

if let currentDeviceLanguage = Locale.current.languageCode {
print("currentLanguage", currentDeviceLanguage)

if currentDeviceLanguage == "he" {
UIView.appearance().semanticContentAttribute = .forceRightToLeft
} else {
UIView.appearance().semanticContentAttribute = .forceLeftToRight
}

}

UItextView arabic text aligned to right

You can set the writing direction of a UITextView using the setBaseWritingDirection selector:

UITextView *someTextView = [[UITextView] alloc] init];
[someTextView setBaseWritingDirection:UITextWritingDirectionLeftToRight forRange:[someTextView textRangeFromPosition:[someTextView beginningOfDocument] toPosition:[someTextView endOfDocument]]];

The code is a little tricky because UITextView supports having different parts of the text with different writing directions. In my case, I used [someTextView textRangeFromPosition:[someTextView beginningOfDocument] toPosition:[someTextView endOfDocument]] to select the full text range of the UITextView. You can adjust that part if your needs are different.

You may also want to check whether the text in your UITextView is LTR to RTL. You can do that with this:

if ([someTextView baseWritingDirectionForPosition:[someTextView beginningOfDocument] inDirection:UITextStorageDirectionForward] == UITextWritingDirectionLeftToRight) {
// do something...
}

Note that I specified the start of the text using [someTextView beginningOfDocument] and searched forward using UITextStorageDirectionForward. Your needs might differ.

If you subclass UITextView replace all these code samples with "self" and not "someTextView", of course.

I recommend reading about the UITextInput protocol, to which UITextView conforms, at http://developer.apple.com/library/ios/#documentation/uikit/reference/UITextInput_Protocol/Reference/Reference.html.

Warning about using the textAlignment property in iOS 5.1 or earlier: if you use it with this approach together with setting the base writing direction, you will have issues because RTL text when aligned left in a UITextView actually aligns to the right visually. Setting text with an RTL writing direction to align right will align it to the left of the UITextView.

why (arabic with english) text refuses to align right?

Unicode has two marker characters (LTR: 0x200E, RTL:200F). These are invisible, but control the direction, I just need to add this \u{200E} to force the wrapping direction.

 \u{200E} \(word1) found your review on \(word2) useful.

EDIT:
see full tutorial here, for more info.

Change the UITextView Text Direction

You question have really interested me. So in a matter of hour I've came up with solution. It is far from perfect, but you can use it and fix remaining bugs.
This is a simple view controller with text view. You can add text typing it or you can set the value using

-(void) setText:(NSString*) txt;

So here is the code:

ReverseTextVC.h

@interface ReverseTextVC : UIViewController <UITextViewDelegate> {
NSMutableArray* _lines;
UITextView* _tv;
}

/**
Returns reversed text.
The lines is also updated. This array contains all lines. You should pass this array again if you want to append the text.
*/
+(NSString*) reverseText:(NSString*) text withFont:(UIFont*) font carretPosition:(NSRange*) cpos Lines:(NSMutableArray*) lines Bounds:(CGRect) bounds;

-(void) setText:(NSString*) txt;

@end

ReverseTextVC.m

@implementation ReverseTextVC

-(id) init {
if( self = [super init] ) {
_tv = [[UITextView alloc] initWithFrame: CGRectMake(0, 0, 320, 480)];
_tv.textAlignment = UITextAlignmentRight;
_tv.delegate = self;
[self.view addSubview: _tv];
[_tv release];

_lines = [[NSMutableArray alloc] initWithCapacity: 10];
[_lines addObject: [NSMutableString stringWithCapacity: 255]];
}

return self;
}

-(void) dealloc {
[_lines release];

[super dealloc];
}

-(void) loadView {
UIView* v = [[UIView alloc] initWithFrame: CGRectMake(0, 20, 320, 480)];
self.view = v;
[v release];
}

-(void) setText:(NSString*) txt {
NSString* result = nil;
NSRange rng;
NSArray* words = [txt componentsSeparatedByString: @" "];
//we should do it iteratively (cause it's the simplest way =) )
for(NSString* word in words) {
word = [NSString stringWithFormat: @"%@ ", word];
for(int i=0; i<[word length]; ++i) {
NSRange r; r.length = 1; r.location = i;
result = [ReverseTextVC reverseText: [word substringWithRange: r]
withFont: _tv.font
carretPosition: &rng
Lines: _lines
Bounds: _tv.bounds];
}
}

_tv.text = result;
}

#pragma mark -
#pragma mark UITextViewDelegate

-(BOOL) textView:(UITextView*) textView shouldChangeTextInRange:(NSRange) range replacementText:(NSString*) text {
NSRange rng;

textView.text = [ReverseTextVC reverseText: text
withFont: textView.font
carretPosition: &rng
Lines: _lines
Bounds: textView.bounds];

textView.selectedRange = rng;

return NO;
}

#pragma mark -
#pragma mark Static

+(NSString*) reverseText:(NSString*) text withFont:(UIFont*) font carretPosition:(NSRange*) cpos Lines:(NSMutableArray*) lines Bounds:(CGRect) bounds {
cpos->length = 0;
cpos->location = 0;
if( [text length] ) {
if( ![text isEqualToString: @"\n"] ) {
[(NSMutableString*)[lines lastObject] insertString: text
atIndex: 0];
} else {
[lines addObject: [NSMutableString stringWithCapacity: 255]];
}
} else {
//backspace
//TODO:
NSRange del_rng;
del_rng.length = 1;
del_rng.location = 0;
if( [(NSMutableString*)[lines lastObject] length] ) {
[(NSMutableString*)[lines lastObject] deleteCharactersInRange: del_rng];
}
if( ![(NSMutableString*)[lines lastObject] length] ) {
[lines removeLastObject];
}
}

CGSize sz = [(NSString*)[lines lastObject] sizeWithFont: font];
if( sz.width >= bounds.size.width-15 ) {
NSMutableArray* words = [NSMutableArray arrayWithArray: [(NSString*)[lines lastObject] componentsSeparatedByString: @" "]];
NSString* first_word = [words objectAtIndex: 0];
[words removeObjectAtIndex: 0];
[(NSMutableString*)[lines lastObject] setString: [words componentsJoinedByString: @" "]];
[lines addObject: [NSMutableString stringWithString: first_word]];
}

NSMutableString* txt = [NSMutableString stringWithCapacity: 100];
for(int i=0; i<[lines count]; ++i) {
NSString* line = [lines objectAtIndex: i];
if( i<([lines count]-1) ) {
[txt appendFormat: @"%@\n", line];
cpos->location += [line length]+1;
} else {
[txt appendFormat: @"%@", line];
}
}

return txt;
}

@end

Hope it helps you =)

Non-Editable UITextView Left-Aligns RTL (Arabic, Hebrew, etc) Text

Solved it! Turns out it's very simple: just set the textAlignment to UITextAlignmentRight.

UITextView works differently when editable and not, especially when it comes to RTL text. If the base writing direction is RTL in an editable text view, you must align the text left, not right, in order for the text to actually align right (the RTL writing direction flips the defaults!)

So, when you have a UITextView, you may want to first check the editable property and then use the writing direction of the first character (this is how iOS determines whether the text is aligned left or right) to set the textAlignment property.

For example:

// check if the text view is both not editable and has an RTL writing direction
if (!someTextView.editable && [someTextView baseWritingDirectionForPosition:[someTextView beginningOfDocument] inDirection:UITextStorageDirectionForward] == UITextWritingDirectionRightToLeft) {
// if yes, set text alignment right
someTextView.textAlignment = UITextAlignmentRight;
} else {
// for all other cases, set text alignment left
someTextView.textAlignment = UITextAlignmentLeft;
}
}

UPDATE FOR iOS 6:

In iOS 6, a UITextView's textAlignment property actually corresponds to its appearance on the screen. For iOS 6, just set the textAlignment to the direction you want to see it. The above code works as described for iOS 5.1 and earlier.

I hope this helps anyone else dealing with this issue!

Links not working in UITextView Attributed String when language is Arabic

I got the issue.
I have been overriding the

func point(inside point: CGPoint, with event: UIEvent?) -> Bool

method to ignore the taps anywhere but not the links in a textview.

I was using a UITextLayoutDirection as left inside this method. I had to change it according to the alignment for different languages. That is for Right to Left languages, I will use the UITextLayoutDirection.Right.

Thanks



Related Topics



Leave a reply



Submit