3

I am trying to achieve the same effect as Facebook's new status field: place something next to the last character which cannot be modified or selected by the user (for example, a tag: "with Joh Doe").

What's the best way of achieving it?

Thanks

Nick

Screenshot

1 Answer 1

4

An easier solution would be to simply make the last n characters in the TextView not editable. Then let the TextView handle moving and wrapping the text as needed. I would guess that is what Facebook is doing, just with some attributed text at the end.

In your ViewControllers.h, make sure the viewController conforms to the UITextViewDelegate as follows.

@interface ViewController : UIViewController <UITextViewDelegate>

Then in the viewDidLoad: method, set the delegate for the UITextView to the ViewController. You can also add your fixed text.

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    self.myTextView.delegate = self;
    self.myTextView.text = " posted by Mike";
}

Then, we will use the shouldChangeCharactersInRange: method to prevent the user from editing the text at the end you want to preserve.

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
    BOOL deleteKeyPressed = ([text length] == 0 && range.length > 0);

    if( range.location > (textView.text.length - @" - posted by Mike".length) || (deleteKeyPressed && range.location > (textView.text.length - @" - posted by Mike".length)) )
    {
        return NO;
    }
    return YES;
}

I think this should get you started and make you life easier than finding the end of the last text, then putting another view at the end that may need to wrap if there is not enough room to fit it.

So to prevent the user from selecting the "reserved" text, add the following delegate method to your ViewController's .m:

-(void) textViewDidChangeSelection:(UITextView *)textView
{
    if( textView.selectedRange.location > (textView.text.length - @" - posted by Mike".length) )
    {
        [textView setSelectedRange:NSMakeRange((textView.text.length - @" - posted by Mike".length), 0 )];
    }
}

You'll still need to handle if the user selects all the text, and chooses to "cut" or "paste", but that should just be another special case in shouldChangeTextInRange. I'll let you figure that one out - shouldn't be hard. Certainly a lot easier than trying to dynamically place, size, and wrap a TextView within another TextView.

4
  • Yeah, I love going through and posting an answer and someone posts a few minutes before me while I'm writing up the answer...
    – wottle
    Commented Aug 9, 2014 at 23:07
  • OK, but mine handles deletes. It seems that mine is more complete. We'll let the OP decide which one gets him closer. And mine was posted 20 minutes before yours. Thanks and best of luck.
    – wottle
    Commented Aug 9, 2014 at 23:13
  • Thanks to both of you, however I was wondering if there was another solution to this as I have tried to implement this but from a user experience standpoint, I don't think it's ideal. Is there any other way this can be done?.. Thanks!
    – nzapponi
    Commented Aug 10, 2014 at 10:09
  • What is not ideal about it? This would behave in the same fashion as the Facebook app that you mention. It provides you with a set of fixed text at the end of the type-able area? If you want something different than what you asked for, you'll have to be more specific as to your needs.
    – wottle
    Commented Aug 10, 2014 at 14:31

Not the answer you're looking for? Browse other questions tagged or ask your own question.