4

My app has a UITextView, with a long, non-editable, scrollable piece of text. When the user rotates the device, I noticed that the position in the moves. So, for instance, say the device is in portrait mode, and the top-left word is "Stackoverflow", after rotation to landscape, that is no longer the top-left word, the text is off by one or sometimes more lines. If I rotate back to portrait, it shifts even more. Just a little bit every time.

Is there a way to maintain the position on rotation, so the user always sees the same word (or at least the line with that word)?

EDIT: I thought the following could work, but I'm not sure how to code the first part:

  1. get the range of the first visible word
  2. rotate
  3. scroll to the saved range using scrollRangeToVisible:
koen
  • 5,383
  • 7
  • 50
  • 89

2 Answers2

0

You could try to scroll to the top, whenever rotation happens. However scrolling on the top of a UITextView is not so simple.

I would recommend to check out this thread: How do I force a UITextView to scroll to the top every time I change the text?

Community
  • 1
  • 1
dirtydanee
  • 6,081
  • 2
  • 27
  • 43
  • Sometimes the text is in the middle, so scrolling to the top would move the text even more. – koen Oct 14 '15 at 11:54
  • ok, i see. I think the main problem is that, that the UITextView changes its content area. Therefore the text will have a different layout. – dirtydanee Oct 14 '15 at 11:55
0

I would try something like the following and fiddle with the point and granularity to get a result you can live with. The problem is when the textview resizes the words will wrap different (i.e. the top left most glyph may be placed in the center of the view with new glyphs to its left).

-(void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
{
    CGPoint topLeft = CGPointMake(1.0,1.0);
    UITextPosition *topPosition = [self.textView closestPositionToPoint:topLeft];
    UITextRange *topRange = [self.textView.tokenizer rangeEnclosingPosition:topPosition withGranularity:UITextGranularityWord inDirection:UITextLayoutDirectionRight];
    [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context)
          {
              }
          } completion:^(id<UIViewControllerTransitionCoordinatorContext> context)
          {
              [self.textView scrollToRange:topRange];

          }];
}
David Harris
  • 2,332
  • 1
  • 13
  • 25
beyowulf
  • 15,101
  • 2
  • 34
  • 40
  • I've tried that, but the offset in portrait will scroll to a different position in landscape. I agree the magic should happen in `viewWillTransitionToSize:` – koen Oct 14 '15 at 12:03
  • If you want to do it by scrollRangeToVisible, I would look at the closestPositionToPoint and rangeEnclosingPosition:withGranularity:inDirection methods – beyowulf Oct 14 '15 at 12:17
  • Thank you - I will check that out. But I'm not married to `scrollRangeToVisible:`, I'm open to any solution. – koen Oct 14 '15 at 12:19
  • I haven't been able to get it to work yet - the `topRange` is either `nil` or the first part of the text. I'll keep trying. I also made some corrections in your code. Finally, what is `scrollToRange`, there is no such method for `UITextView`. – koen Oct 15 '15 at 01:35
  • I meant scrollRangeToVisable – beyowulf Oct 15 '15 at 01:44
  • That's what I also thought, but that takes an `NSRange`, not an `UITextRange` as argument. – koen Oct 15 '15 at 01:45
  • 1
    http://stackoverflow.com/questions/21149767/convert-selectedtextrange-uitextrange-to-nsrange – beyowulf Oct 15 '15 at 01:48