I am working in iPhone application, Using UITextView to show multiple text inside it, when the user tab the screen, automatically scroll UITextView content from bottom to top (scrolling level slow) and its working fine, i want to increase scroll speed like 1,2,3,4,5,6...10, How to do this? Please help me.
Thanks in advance
I tried this:
- (void)viewDidLoad
{
[super viewDidLoad];
ScriptDetails = [[UITextView alloc]initWithFrame:CGRectMake(0,9,480,285)];
ScriptDetails.text=Script;
ScriptDetails.textAlignment=UITextAlignmentLeft;
ScriptDetails.editable=NO;
ScriptDetails.delegate=self;
ScriptDetails.font=[UIFont fontWithName:str1 size:f];
ScriptDetails.backgroundColor=tColor1;
ScriptDetails.textColor=tColor;
[self.view addSubview:ScriptDetails];
UITapGestureRecognizer *singleTap = [[[UITapGestureRecognizer alloc] initWithTarget: self action:#selector(TouchToPlay)] autorelease];
singleTap.delegate=self;
singleTap.numberOfTapsRequired = 1;
[ScriptDetails addGestureRecognizer:singleTap];
}
-(void)TouchToPlay
{
NSLog(#"single");
timer = [NSTimer scheduledTimerWithTimeInterval:(35.0/1000.0)
target:self
selector:#selector(autoscrollTimerFired:)
userInfo:nil
repeats:YES];
}
- (void)autoscrollTimerFired:(NSTimer*)timer
{
CGPoint scrollPoint = ScriptDetails.contentOffset;
scrollPoint = CGPointMake(scrollPoint.x, scrollPoint.y + 1);
[ScriptDetails setContentOffset:scrollPoint animated:NO];
}
The other way is to put the variable in - (void)autoscrollTimerFired:(NSTimer*)timer method
in scrollPoint = CGPointMake(scrollPoint.x, scrollPoint.y + 1); line instead of just 1 put there some iVar instead and provide some mechanism for like say one + and - button to increase and decrease the speed.
If its just about scrolling fast, you can minimize the time at which the timer function is called. And for scrolling slow, you can increase the time.
Let me know if you are looking for something else.
Related
For the past four hours, I have tried many Stack Overlow solutions but none have helped solve my problem.
Here it is,
I have a UIScrollView
Within that ScrollView there is one custom UILabel and 8 custom UIImageViews
I want to detect a long press
Something like this works
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(longPressDidFire:)];
longPress.minimumPressDuration = 0.5;
[scroll addGestureRecognizer:longPress]; //scroll defined elsewhere
However, if I replace the scroll with any subviews of scroll, the long press event never fires.
How do I detect a long press of a subview of a scroll view?
This is quite a messy hack, however, since I can detect long presses of a scroll view, is there any way where I can detect the
position of the press so that I can see which specific subview is
being pressed.
Also, (insert subview here).userInteractionEnabled = YES, I set this property for all my subviews of the scroll view, so this should not be a problem.
I have also tried using touchesBegan and touchesEnded method as suggested elsewhere in Stack Overflow.
Also, for the image views, I do set a new UILongPressGestureRecognizer for every custom image view, using a for loop, as I am aware of the 1 view per gesture recognizer rule.
From A First Time iOS Developer,
Graham
P.S. I'd really prefer if I could find a solution for 1. rather than the messy 2.
More Code As Requested:
In the Init of the view Controller
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(longPressDidFire:)];
longPress.minimumPressDuration = 0.5;
[self.titleLabel addGestureRecognizer:longPress]; //titleLabel property initialized elsewhere
[mainView addSubview:self.titleLabel];
In a "load images" method
for (NSData * dataImg in results) {
//Does some work turning data into an image, into an image view called img
img.delegate = self;
img.userInteractionEnabled = YES;
UILongPressGestureRecognizer *aLongPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(longPressDidFire:)];
aLongPress.minimumPressDuration = 0.5;
[img addGestureRecognizer:aLongPress];
[imgContainer addSubview:img];
}
Even More Code + Notes
self.view (UIView)
->scroll (UIScrollView)
->->mainView (UIView)
->->->titleLabel (UILabel)
->->->imgContainer (UIView)
->->->->images (UIImageViews)
[self.view addSubview:scroll];
[scroll addSubview:mainView];
[mainView addSubview:self.titleLabel];
[mainView addSubview:imgContainer];
[imgContainer addSubview:img]; //done 8x via for loop
Thanks to #RegularExpression's answer, I now am aware that the mainView is getting pressed, but not its subviews, so I need to find a way to display the mainView's subviews above it. :)
Another update, titleLabel works. ImageViews still don't work though. :(
I know this is a bit late and an answer has been chosen, but in case someone else wants a nice simple solution if you've got iOS7.
Inside your delegate of the UILongPressGestureRecognizer implement the gestureRecognizer:shouldRequireFailureOfGestureRecognizer:otherGestureRecognizer selector
Check if otherGestureRecognizer is a UIPanGestureRecognizer and return YES, otherwise return NO
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRequireFailureOfGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
if ([otherGestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]]) {
return YES;
}
return NO;
}
The scroll view will actually produce a UIScrollViewPanGestureRecognizer, which is part of the private API, but it's a subclass of UIPanGestureRecognizer so the above works fine.
To support iOS6 or below, then you'll need to loop through the gestureRecognizers of the UIScrollView, detect which one is a UIPanGestureRecognizer and perform the requireGestureRecognizerToFail selector on your UILongPressGestureRecogizer with that.
your code seems to be fine,it should work i think.i used below code and its working fine for me.
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(handleLongPress:)];
longPress.delegate = (id)self;
longPress.minimumPressDuration=0.05;
imageView.userInteractionEnabled = YES;
[imageView addGestureRecognizer:longPress];
and its method,
- (IBAction)handleLongPress:(UILongPressGestureRecognizer *)sender {
NSLog(#"detected");
if (sender.state == UIGestureRecognizerStateEnded){
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"Alert" message:#"YES" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles: nil];
[alert show];
}
}
Here i took imageView as subview of scrollview as u said
Since your UIScrollView is the common parent, that's probably where your gesture recognizer needs to be. You can determine which subview is being pressed by looking at the location of the point supplied in your action. So, the individual subviews do not need gesture recognizers.
So, you would do something like this:
- (void)longPressDidFire:(UILongPressGestureRecognizer *)sender
{
if (sender.state == UIGestureRecognizerStateEnded)
CGPoint point = [sender locationInView:scroll];
UIView *tappedView = [scroll hitTest:point withEvent:nil];
So, then you have the view that was long-pressed.
Other things that could cause the action not to fire would be a delegate problem or if the scroll is contained by another view that is intercepting the touch.
HTH
Instead of
[scroll addGestureRecognizer:longPress];
Add the gesture on your subviews, right after you declare them and before you add them to scrollview
[subview addGestureRecognizer:longPress];
Woohoo it works!
The problem was:
imgContainer was a UIView with an empty frame with several UIImageViews as subviews
I was under the impression that as I added a subview to imgContainer, imgContainer would expand.
This is not true.
I had to set imgContainer's frame to the same content frame as the scroll view and then everything became ok.
I hope this answer helps any other future iOS firs timers like me.
I'm fairly new to Objective-C development.
In my first app built from scratch, I'd like to draw a circle that increases its size as time runs.
The problem is that I've been able to move the circle through the screen, but can't seem to update its properties so it gets bigger or smalles.
Thing goes like this:
CCircle class
#interface CCircle : CShapes
#property float radius;
#property float startAngleRadians;
#property float endAngleRadians;
In the first view controller (ShapesViewController.m):
- (void) viewDidLoad
{
(...)
CCircle* circle = [[CCircle alloc] initWithFrame:frame];
circle.radius = 40;
circle.startAngleRadians = M_PI;
circle.endAngleRadians = 2*M_PI;
circle.tag = 1;
[self.view addSubView:circle];
//I also schedule an update method, so that it is called every 1 seconds.
[NSTimer scheduledTimerWithTmieInterval:1.0 target:self selector:#selector(updateCircle) userInfo:nil repeats:YES];
}
Also in ShapesViewController.m, the update method:
- (void) updateCircle
{
CCircle *circle = [self.view viewWithTag:1];
//Now here: if I do this: the circle will "move" through the screen
CGRect frame = circle.frame;
frame.origin.x += 5;
[circle setFrame:frame];
//However, if I try to change the circle properties, I don't know what to do so
//that affects the circle. In this case, the circle will move through the screen,
//but I keep seeing always the same size(radius).
circle.radius += 5;
//I've tried the following (of course, not all at the same time):
//[self.vew addSubview:circle];
//[self.view sendSubviewToBack:circle];
//[self.view sendSubviewToFront:circle];
//[self.view setNeedsDisplay];
//[self.view setNeedsLayout];
}
Any help on what am I doing wrong, and what should I do to achieve what I want?
Thanks!
You updated a property of circle, not self.view, so you need to call setNeedsDisplay on circle.
After drawing the circle, you have to update your view.
[self.view setNeedsDisplay];
I think that'll do it.
How can I programmatically spawn an unlimited number of UIImageViews on to the screen in a random location on a time increment. The random location would be:CGPoint(arc4random() % (481), arc4random() % (321),20,20) I just don't understand how to constantly create new ones with one image variable and a for loop. Or an NSTimer that on every increment adds a new image to the screen.
I know there are some tutorials out there for this, but the only ones I could find used automatic reference counting. It should be simple to create, and a link is fine.
Other questions:
UI is for user-interface, but since i'm not using a storyboard or xib, would there be a better type of imageView to use.
How about something like this, in your view controller class (substituting your own image file name of course):
- (void)viewDidLoad {
[super viewDidLoad];
[NSTimer scheduledTimerWithTimeInterval:.5 target:self selector:#selector(addViews:) userInfo:nil repeats:YES];
}
-(void)addViews: (NSTimer *) aTimer {
UIImageView *iv = [[UIImageView alloc]initWithImage:[UIImage imageNamed:#"New_PICT0011.jpg"]];
CGRect rect = CGRectMake(arc4random() % (481), arc4random() % (321), 20, 20);
[iv setFrame:rect];
[self.view addSubview:iv];
}
You would have to put some kind of counter in there, and when it got to the total number of views you wanted, call [aTimer invalidate];
I have two little problems with my UIScrollView.
I managed to create scroll view, which is similar to the picker view except that it's horizontal.
The problem n.1 is - How do I get the number which the user tapped?
The problem n.2 is - How do I make the scrollview to go round and round - never-ending?
A question - Is it possible to make some "selection indicator"?
Here is my code:
numberArray = [NSArray arrayWithObjects:#"1", #"2", #"3", #"4", #"5",
#"6", #"7", #"8", #"9", #"10", #"11", #"12", #"13", #"14", #"15",
#"16", #"17", #"18", #"19", #"20", #"21", #"22", #"23", #"24", #"25",
#"26", #"27", #"28", #"29", #"30", #"31", #"32", #"33", #"34", #"35",
#"36", #"37", #"38", #"39", #"40", #"41", #"42", #"43", #"44", #"45",
#"46", #"47", #"48", #"49", #"50", #"51", #"52", #"53", #"54", #"55",
#"56", #"57", #"58", #"59", #"60", #"61", #"62", #"63", #"64", #"65",
#"66", #"67", #"68", #"69", #"70", #"71", #"72", #"73", #"74", #"75",
#"76", #"77", #"78", #"79", #"80", #"81", #"82", #"83", #"84", #"85",
#"86", #"87", #"88", #"89", #"90", #"91", #"92", #"93", #"94", #"95",
#"96", #"97", #"98", #"99", #"100", nil];
masterDividerView = [[UIView alloc] initWithFrame:CGRectMake(0, 480, 320, 44)];
morePeople = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 320, 53)];
morePeople.backgroundColor = [UIColor scrollViewTexturedBackgroundColor];
morePeople.delegate = self;
[morePeople setBackgroundColor:[UIColor whiteColor]];
[morePeople setCanCancelContentTouches:NO];
morePeople.showsHorizontalScrollIndicator = NO;
morePeople.showsVerticalScrollIndicator = NO;
morePeople.clipsToBounds = NO;
morePeople.scrollEnabled = YES;
morePeople.pagingEnabled = NO;
NSUInteger nimages = 0;
NSInteger tot=0;
CGFloat cx = 0;
for (; ; nimages++) {
NSString *label = [numberArray objectAtIndex:nimages];
if (tot==99) {
break;
}
if (99==nimages) {
nimages=0;
}
UILabel *labelView = [[UILabel alloc] init];
labelView.text = label;
labelView.lineBreakMode = UILineBreakModeWordWrap;
labelView.numberOfLines = 0;
[labelView sizeToFit];
labelView.backgroundColor = [UIColor scrollViewTexturedBackgroundColor];
CGRect rect = labelView.frame;
rect.size.height = 53;
rect.size.width = 40;
rect.origin.x = cx;
rect.origin.y = 0;
labelView.frame = rect;
[morePeople addSubview:labelView];
cx += labelView.frame.size.width+5;
tot++;
}
self.pageControl.numberOfPages = nimages;
[morePeople setContentSize:CGSizeMake(cx, [morePeople bounds].size.height)];
[masterDividerView addSubview:morePeople];
[self.view addSubview:masterDividerView];
If anybody knows a good solution to this, I would be very happy!!!! :))
Your question is too wide to make a detailed answer, but yes, everything of what you're talking about can be solved in a quite easy way.
The problem n.1 is - How do I get the number which the user tapped?
If you mean to know what element is chosen by your UIScrollView at the moment, then it's not a problem: UIScrollView always knows its position (contentOffset), which gives you the easy possibility to define, which object is chosen (which object you're working with) now.
If you mean to know when the user tapped by his finger one of the elements of your "picker view" (UIScrollView), then I would say that the answer to this depends on how you actually represent your data (like if you see one or several elements of your scrollView at a time on your screen). But in any case you can easily solve this by using UITapGestureRecognizer. Smth like:
// add gesture recognizers to the scroll view
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleSingleTap:)];
[singleTap setNumberOfTapsRequired:1];
[self.yourScrollView addGestureRecognizer:singleTap];
[singleTap release];
And then to scroll it programmatically in your selector you do smth like:
- (void)handleSingleTap:(UIGestureRecognizer *)gestureRecognizer
{
CGPoint pointOfTouch = [gestureRecognizer locationInView:self.view];
if ( (pointOfTouch.x > self.rightArrowMin) && (pointOfTouch.x < self.rightArrowMax) ) {
[scrollView setContentOffset:CGPointMake(lastOffset + self.lengthOfLabel, 0) animated:YES];
} else if ( (pointOfTouch.x > self.leftArrowMin) && (pointOfTouch.x < self.leftArrowMax) ) {
[scrollView setContentOffset:CGPointMake(lastOffset - self.lengthOfLabel, 0) animated:YES];
}
}
The problem n.2 is - How do I make the scrollview to go round and round - never-ending?
It can be solved if you know the algorithm of calculating the next/previous or random element in the sequence of elements of your scrollView.
Basically, I solved this same thing for myself in one of my projects (free app "IJCAI11" in the appStore, there you can see at the work of a datePicker in the details of any chosen conference's day: there is applied the algorithm of infinite scrolling view, the limits I applied later only from design point of view).
The scheme I use there is simple, though perhaps a bit weird (before reading ahead, note that in my case I see only one element of scrollView on the screen, when the scrollView is in nonscrolling state):
I create the UIScrollView with 3 (in case you see more than 1 element at a time this can be like 5, 7, ..., 2N+1 according to your very case) labels;
Make the second (central) label active.
Assign proper value to all 3 (2N+1) labels. On this step your second (central) label will contain data of (will show) the default value.
When user scrolls one step left/right (to the position M_pos), you do it in a standard way, since your neighboring to central labels contain correct data (M).
Then you take this new active value (M) and apply it for your central label (this is gonna be behind the scene, therefore the user wont see this on the screen), then you recalculate ALL the other labels properly ( ..., M-1, M, M+1, ...), including your M_pos position(!).
With "animated:NO" mode you shift your scrollView to your central position. In this case user doesn't see anything, when in fact his scrollView was moved from position M_pos to the central position. All neighboring labels are already recalculated and you are ready to repeat the point 4 any number of times you wish, making a strong feeling for user, that he works with the scrollView with a huge number of elements (whereas in practice your just work with 3 (2N+1) labels, changing their content after every movement).
A question - Is it possible to make some "selection indicator"?
If I understand this question correctly, then just consider the View/Subview thing and in particular the function addSubview of View class ;)
Hope this helps!
I'm not sure if I understood your question right, but did you already think of using a NSTimer to repeat events with a certain speed or during a certain period of time? (Pointing at your "round and round thing".)
I have a view which is similar to the notes app - i.e. typing on a lined piece of paper. To make the text and the paper scroll simultaneously, I have disabled the UITextView's scrolling, and instead placed both my UITextView and my UIImageView inside a UIScrollView.
The only problem with this is that, when the user types, the text disappears below the keyboard, because obviously the UIScrollView does not know to scroll to the cursor position.
Is there any simple way I can retrieve the cursor position and tell the UIScrollView to scroll there?
---EDIT---
Starting from something similar here (where someone was trying to do something similar with a UITableView), I have managed to make a growing, editable UITextView with a fixed background that almost scrolls perfectly. The only issues now are:
There is a slight judder as the text moves up if the user types particularly fast.
If the user hides the keyboard, selects text at the bottom of the screen, and then shows the keyboard again, they have to type a couple of letters before the text becomes visible again - it doesn't scroll up immediately.
When the user hides the keyboard, the animation as the scroll view's frame fills the screen doesn't feel quite right somehow.
Here is the code - I'd be really grateful if anyone can refine it further...
#import "NoteEditViewController.h"
#import "RLWideLabelTableCell.h"
#implementation NoteEditViewController
#synthesize keyboardSize;
#synthesize keyboardHideDuration;
#synthesize scrollView;
#synthesize noteTextView;
//
// Dealloc and all that stuff
//
- (void)loadView
{
[super loadView];
UIScrollView *aScrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds];
self.scrollView = aScrollView; [aScrollView release];
self.scrollView.contentSize = CGSizeMake(self.view.frame.size.width, noteTextView.frame.size.height);
[self.view addSubview:scrollView];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Get notified when keyboard is shown. Don't need notification when hidden because we are
// using textViewDidEndEditing so we can start animating before the keyboard disappears.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification object:nil];
// Add the Done button so we can test dismissal of the keyboard
UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone
target:self
action:#selector(doneButton:)];
self.navigationItem.rightBarButtonItem = doneButton; [doneButton release];
// Add the background image that will scroll with the text
CGRect noteImageFrame = CGRectMake(self.view.bounds.origin.x,
noteTitleImageFrame.size.height,
self.view.bounds.size.width, 500);
UIView *backgroundPattern = [[UIView alloc] initWithFrame:noteImageFrame];
backgroundPattern.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"Notepaper-iPhone-Line"]];
[self.scrollView addSubview:backgroundPattern];
[self.view sendSubviewToBack:backgroundPattern];
[backgroundPattern release];
// Add the textView
CGRect textViewFrame = CGRectMake(noteImageFrame.origin.x+27,
noteImageFrame.origin.y-3,
noteImageFrame.size.width-35,
noteImageFrame.size.height);
RLTextView *textView = [[RLTextView alloc] initWithFrame:textViewFrame];
self.noteTextView = textView; [textView release];
self.noteTextView.font = [UIFont fontWithName:#"Cochin" size:21];
self.noteTextView.backgroundColor = [UIColor clearColor];
self.noteTextView.delegate = self;
self.noteTextView.scrollEnabled = NO;
[self.scrollView addSubview:self.noteTextView];
}
- (void)doneButton:(id)sender
{
[self.view endEditing:TRUE];
}
// When the keyboard is shown, the UIScrollView's frame shrinks so that it fits in the
// remaining space
- (void)keyboardWasShown:(NSNotification*)aNotification
{
NSDictionary* info = [aNotification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
float kbHideDuration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] floatValue];
self.keyboardHideDuration = kbHideDuration;
self.keyboardSize = kbSize;
self.scrollView.frame = CGRectMake(self.view.bounds.origin.x,
self.view.bounds.origin.y,
self.view.bounds.size.width,
self.view.bounds.size.height - kbSize.height);
}
// When the user presses 'done' the UIScrollView expands to the size of its superview
// again, as the keyboard disappears.
- (void)textViewDidEndEditing:(UITextView *)textView
{
[UIScrollView animateWithDuration:keyboardHideDuration animations:^{self.scrollView.frame = self.view.bounds;}];
}
// This method needs to get called whenever there is a change of cursor position in the text box
// That means both textViewDidChange: and textViewDidChangeSelection:
- (void)scrollToCursor
{
// if there is a selection cursor…
if(noteTextView.selectedRange.location != NSNotFound) {
NSLog(#"selectedRange: %d %d", noteTextView.selectedRange.location, noteTextView.selectedRange.length);
// work out how big the text view would be if the text only went up to the cursor
NSRange range;
range.location = noteTextView.selectedRange.location;
range.length = noteTextView.text.length - range.location;
NSString *string = [noteTextView.text stringByReplacingCharactersInRange:range withString:#""];
CGSize size = [string sizeWithFont:noteTextView.font constrainedToSize:noteTextView.bounds.size lineBreakMode:UILineBreakModeWordWrap];
// work out where that position would be relative to the textView's frame
CGRect viewRect = noteTextView.frame;
int scrollHeight = viewRect.origin.y + size.height;
CGRect finalRect = CGRectMake(1, scrollHeight, 1, 1);
// scroll to it
[self.scrollView scrollRectToVisible:finalRect animated:YES];
}
}
// Whenever the text changes, the textView's size is updated (so it grows as more text
// is added), and it also scrolls to the cursor.
- (void)textViewDidChange:(UITextView *)textView
{
noteTextView.frame = CGRectMake(noteTextView.frame.origin.x,
noteTextView.frame.origin.y,
noteTextView.frame.size.width,
noteTextView.contentSize.height);
self.scrollView.contentSize = CGSizeMake(self.scrollView.contentSize.width,
noteTextView.frame.size.height+200);
[self scrollToCursor];
}
// The textView scrolls to the cursor whenever the user changes the selection point.
- (void)textViewDidChangeSelection:(UITextView *)aTextView
{
[self scrollToCursor];
}
// PROBLEM - the textView does not scroll until the user starts typing - just selecting
// it is not enough.
- (void)textViewDidBeginEditing:(UITextView *)textView
{
[self scrollToCursor];
}
Cool that you found my post about it, glad it was helpful!
I believe you may not be seeing the bottom line because of this line:
CGRect finalRect = CGRectMake(1, scrollHeight, 1, 1);
You're creating a 1x1 point box. A single line of text might be something like 20 or 30 points tall (depending on font size). So if you're scrolling this point to visible, it may only be showing the very top pixel of the bottom line - making the bottom line effectively invisible! If you make finalRect a little taller so it covers the whole line, it might work better:
CGRect finalRect = CGRectMake(1, scrollHeight, 1, 30);
Also, you may be calling your scrollRectToVisible code multiple times at once, which can cause "judders". In my code, I only run scrollRectToVisible from textViewDidChangeSelection, and resize the UITextView (if needed) in textViewDidChange. UIScrollView (and by inheritance UITableView) has built-in support to scroll the actively selected element to be visible, which in my testing worked well when simply resizing the UITextView while typing (but not when selecting a specific point inside with a touch).
There is no easy way to find the screen coordinates for any text or cursor in a UITextView.
What you should do is registering for UIKeyboardWillShowNotification and UIKeyboardWillShowNotification. And in the callbacks you adjust the size or contentInsets of the UIScrollView to adjust for the size of the keyboard.
The size of the keyboard, and even the animation duration is provided in the notifications userInfo, so you can do it in a nice animated fashion.
You find more information and sample code here: http://developer.apple.com/library/ios/#documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/KeyboardManagement/KeyboardManagement.html
Not strictly an answer to your question, but here's a different approach to the notes lined background trick: http://www.cocoanetics.com/2010/03/stuff-you-learn-from-reverse-engineering-notes-app/
I've used it and it works well.