Change the UITextView Text Direction

7.8k views Asked by At

my language is not supported by iOS by default, so unicode is not an option so i am using a embedded true type font on a UITextView

it works for the most part, but my issue is like Arabic, and Hebrew my language is written from right to left. So i need to change the direction of the text (Not Text Alignment).

i did some searches, they all talk about NSLocale and stuff, but can it be changed in code? if i can change it to something like Arabic/Hebrew it would work i guess, but it should be done in code, because i dont want change the language of the phone.

so what really are my options for text input? any help would be appreciated.

Thanks.

7

There are 7 answers

2
Max On BEST ANSWER

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 =)

0
Dr.Ax On

I have been facing the same issue. My language is similar to arabic, writing from Right to Left direction. The simplest solution for me was to change the text alignment to right and move the cursor to the left after each character is entered. This works on SWIFT 3.0

func textViewDidChange(_ textView: UITextView) {

    let newPosition = myTextView.beginningOfDocument
    myTextView.selectedTextRange = myTextView.textRange(from: newPosition, to: newPosition)

    print(myTextView.text)


    return

}
1
Faraz Haider On

The Iphone can not display Hebrew and other right-to-left texts correctly. so i think there is no way of u can change direction of the text.

0
pretzels1337 On

For me simply adding the \u202B into the string directly into the .strings file didn't do the trick (The final result would print out literally print out the "202B" portion). However adding the \u202B into the string after it returns from the call to localizedStringForKey does do the trick.

Thus my solution, I inserted the arbitrary string "RLE_SYMBOL" directly into the string in the .strings file, then after the call to localizedStringForKey I replace "RLE_SYMBOL" with "\u202B".

A bit indirect, not the greatest solution but a quick solution.

   mystring = [mystring stringByReplacingOccurrencesOfString:@"RLE_SYMBOL" withString:@"\u202B"];
1
Osama Ahmed On

Hi I think by using UIWebView with html and css you can do the job

0
Ali Nadalizadeh On

You can place a "right-to-left embedding" Unicode character at start of each line in the text view.

Name: RIGHT-TO-LEFT EMBEDDING Unicode : 202B UTF8 : E2 80 AB

Note that this character is invisible (No shapes).

The following piece of code replaces the end-of-line characters with a EOL+RTL_EMBEDDING string :

appDescription.text = [rtlDescriptionString stringByReplacingOccurrencesOfString:@"\n" withString:@"\n‫;["
0
Almog C On

just use the Unicode 202B character for RIGHT-TO-LEFT EMBEDDING.

Example:

uiTextView.text = [NSString stringWithFormat:@"\u202B%@",textString];