Search code examples
iosuitextviewiphoneuitextviewdelegate

Change the UITextView Text Direction


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.


Solution

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