Change the UITextView Text Direction
Asked Answered
T

7

13

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.

Tactics answered 5/2, 2011 at 6:29 Comment(2)
I also want to implement same functionality like yours. I want to implement Urdu Keyboard with text direction from Right to Left. So, did you find any way to get custom keyboard characters with RTL text direction (as you mentioned in your comment under the Accepted Answer) ? If Yes then please share the code here. I am also stuck in a situation like yours. Please Help.Pimply
Please follow this link here for a fix for this issue on SWIFTCurrent
D
7

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

Drobman answered 5/2, 2011 at 12:27 Comment(2)
Really useful, I tried to use it with this custom keyboard : github.com/kulpreetchilana/Custom-iOS-Keyboards but I get direction returned to default. Could you help please how to integrate your code with this custom keyboard control or any similar sugesstion, just want to get custom keyboard caracters with RTL text direction. Thanks.Kado
@Drobman : I also want to implement same functionality like hafedh. I want to implement Urdu Keyboard with text direction from Right to Left. So, did you find any way to get custom keyboard characters with RTL text direction (as mentioned by hafedh) ? If Yes then please share the code here. I am also stuck in a similar situation. Please Help.Pimply
H
9

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‫;["
Horseleech answered 28/6, 2011 at 10:30 Comment(0)
D
7

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

Drobman answered 5/2, 2011 at 12:27 Comment(2)
Really useful, I tried to use it with this custom keyboard : github.com/kulpreetchilana/Custom-iOS-Keyboards but I get direction returned to default. Could you help please how to integrate your code with this custom keyboard control or any similar sugesstion, just want to get custom keyboard caracters with RTL text direction. Thanks.Kado
@Drobman : I also want to implement same functionality like hafedh. I want to implement Urdu Keyboard with text direction from Right to Left. So, did you find any way to get custom keyboard characters with RTL text direction (as mentioned by hafedh) ? If Yes then please share the code here. I am also stuck in a similar situation. Please Help.Pimply
C
4

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

Example:

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

Cowpuncher answered 7/2, 2012 at 9:45 Comment(0)
K
0

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

Kurys answered 6/4, 2011 at 19:56 Comment(1)
UIWebView is used only for displaying content.Tactics
A
0

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"];
Auxiliaries answered 16/1, 2013 at 21:7 Comment(0)
C
0

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

}
Current answered 2/1, 2017 at 9:48 Comment(0)
F
-3

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.

Fortress answered 5/2, 2011 at 10:56 Comment(1)
i have had no issues displaying arabic text before, and i assume its the same for hebrew , I cant speak for text input though.Tactics

© 2022 - 2024 — McMap. All rights reserved.