UITextView inside UIScrollView scroll problem - iphone

I'm experiencing something considered a bug in my situation. Probably this is not a bug but a feature ;).
Here's my case:
I load a UIScrollView with my content. A part of my content is loaded asynchrone after the view is already loaded. This works great and without issue.
Some of these controls however are UITextView controls. Once I set the content (text property) of these controls after the viewDidLoad my UIScrollView scrolls down to the last UITextView that was set. I want to prevent this and want the UIScrollView to maintain it's top scrolled position.
In summary:
If I set the Text property in the viewDidLoad method no scroll occurs. If I set the Text property on the UITextView after the viewDidLoad method (because I load the data asynchronous) the UIScrollView will scroll to the last UITextView that was set. I want to prevent this scroll.
How do I achieve this ? I have a feeling this is just a property which is set wrong but I can't seem to find it.
Thanks in advance.
EDIT:
I've tried setting the "scrollEnabled" property to NO before setting the values and to YES after but this didn't have any effect. The ScrollView will still scroll when the text property of the UITextView is set.

I Fixed the issue with a work-around:
I set the scroll view content size to something small, like 320 x 300 or whatever the height of the scrollview frame is, then did my work, then put the content size back to normal.
This prevents the scrolling while the data is loaded and enables it as soon as the loading is finished.

This would not change the scrolling problem but maybe make it "hidden" for the user:
yourTextView.text = #"Eat more bananas!";
yourScrollView.contentOffset = CGPointMake(0.0, 0.0);
Some snippets of your code would help to face the problem more specific.
EDIT:
Or try to add the UITextViews to a UIView, then add the UIView to the UIScrollView. Make sure that the UIScrollView's contentSize is the same as the Size of the UIView.

This worked for me too :p but i had to set the height to something less then 300 (in my case i just used 10).
Basically the idea is to make the text view not part of the visible area of the UIScrollView wile you are changing the text of th UITextView.

Related

UIScrollView setContentSize breaks view with Auto Layout

I am using Auto Layout in my iPhone app and have a UIScrollView. I need to change the content size of my scroll view at several points while my apps running (so setting the content size in viewWillAppear is useless as I have seen this suggested in other places).
When I change it, my subviews jump about, presumably because it breaks the auto layout constraints.
So how can I approach changing my scrollview content size with auto layout enabled?
Thanks.
I was having this same issue, and I know this can't be the final solution, but for now, rather than calling this in viewWillLayoutSubviews, by putting the code inside viewDidLayoutSubviews it allowed me to set the contentSize AFTER the viewController did it's default business :)
Hope that helps.
Test your code in viewWillLayoutSubviews. Apple say:
When a view’s bounds change, the view adjusts the position of its
subviews. Your view controller can override this method to make
changes before the view lays out its subviews. The default
implementation of this method does nothing.
UIViewController Class Reference

How to set UITextView's content inset like Notes App

I am working in an app in which I need to give feature like Notes App in iphone. as shown in first screen shot , initially , notes leaves a tab before the content starts, I also wanted to do the same and for that when I set Left Content inset (of UITextView) by 25 , it shows like in screenshot 2, here you may see the image also gets shifted. I have set image as background. I don't know how to solve this problem.
I also tried by adding image as subview of UITextview but it won't repeat the lines, while scrolling (image of lines) like notes app.
I'm setting the background of Textview by following code.
[textView setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:#"line_image.png"]]];
Please tell me if I am going wrong or any extra effort needed to get desired output.
Thanks
UITextView is UIScrollView subclass so all relevant delegate method are available for you (e.g. scrollViewDidScroll:) - you can adjust your custom background in that method.
There's very nice post on Dr.Touch blog about recreating Notes app interface - you can get general idea about how it is done from it. Basically what is done there is adding custom view that draws background behind the text view and adjust it in text view's delegate methods and also using KVO on its 'contentSize' property.
#Dinesh gave nice solution but it doesn't sound to be generic as I want to use image of lines instead of drawing them. Image has some special effects that can not be achieved by drawing. So to solve it I created a table view below the textview keeping textview's background transparent. Now just added the image of line to my tableview's custom cell and set content offset of UItableview same as of the scrollview (subview of text view ,refering to the answer of #Vladimir ) .
And used the following code to scroll my tableview with scrolling the textview and got the desired output.
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
tableView.contentOffset =scrollView.contentOffset;
}
Keeping my tableview's number of rows at a very large number.
PS: instead of setting the content inset of textview, i set its frame's X position and decreased the width relaively.

Problem with UIScrollView inside another UIView

I have this UIScrollView inside another UIView, not occuping the entire area (all this is initialized via nib file). I added some content to the scroll view, but whenever I scroll it, the UIScrollView content area moves outside the ScrollView frame, over the UIView area not designated for displaying it.
Shouldn't it remain inside its frame even when I scroll it?
It may be that the clipsToBounds property of your UIScrollView is set to NO. Check the setting in IB, or you can set it in code like so:
scrollView.clipsToBounds = YES;
Failing that, double check that your UIScrollView has exactly the bounds you think it does. Is there any autoresizing flag stuff going on that might be changing the scroll view's bounds?
try to set the clipsToBounds to YES, it may be that:
yourViewController.clipsToBounds = YES;
if not... fbreto is right, post your code...
Make sure you have setContentSize. And also set the frame size of the uiviews inside the uiscrollview correctly when you add them.
Here is a sample code of it http://developer.apple.com/library/ios/#samplecode/Scrolling/Introduction/Intro.html

Is there a way to put UITextView's scroll indicator to outside UITextView?

It might be a silly question.
I'm trying to set left/right margins like the attached picture. I succeeded to implement it by adding UITextView to UIScrollView.
However, I could achieve almost everything I want with UITextView alone. For example, with UIScrollView, when I manually change the text of UITextView, it automatically scrolls to bottom regardless of setting its .scrollEnabled to No.
It would be perfect if a scroll indicator of UITextView appears outside UITextView.
In the attached picture, let's say the red box represents the entire UITextView. I tried to change UITextView's scrollIndicatorInsets property, but a scroll indicator can be moved only inward to be visible.
Several apps such as Pages, aWriter, Plaintext achieve this feature.
Could you give any suggestion?
Thank you!
I
You can set the scroller right inset value of the UITextView to negative value and disable the clip subview option to achieve your require. No other scrollview is needed.
Alternatively you could set the Right contentInset property.
UIEdgeInsets insets = textView.scrollIndicatorInsets;
insets.right += 5; //add what ever is your margain
textView.scrollIndicatorInsets = insets;

UIView transitionWithView: clipping my UITextView

I have a UITextView with scrolling disabled, and I am using the page-curl transition to change the text inside. This is the code I'm using:
myView.text = nextString;
[UIView transitionWithView:myView duration:PAGE_CURL_DURATION options:UIViewAnimationOptionTransitionCurlDown animations:nil completion:nil];
Everything works fine, except if the new text string has more lines than the old one, it will be clipped until the animation is complete. It looks as though the contentSize is changing AFTER the animation. I tried adding myView.contentSize = myView.bounds.size; but that didn't change anything. I also turned off "clip subviews" to no avail.
This is what it looks like immediately after the animation:
a moment later the text is no longer clipped.
Any ideas how to prevent clipping?
The easy way is to do what Bjarne said - use the clipsToBounds property. But watch out - this will make the text expand downwards indefinitely. So you will also need to surround your text field with a container view that DOES clip to bounds to set an upper limit.
If that doesn't do the trick, you will have to do some work to manually expand your text view's bounds and reposition it before animating if the new text is larger.
To get the size of a text, check out UIStringDrawing.h in the UIKit framework. Specifically, I'm thinking of using:
- (CGSize)sizeWithFont:(UIFont *)font forWidth:(CGFloat)width lineBreakMode:(UILineBreakMode)lineBreakMode;
together with UILineBreakModeWordWrap.
another alternative to getting the size may be this function in UILabel:
- (CGRect)textRectForBounds:(CGRect)bounds limitedToNumberOfLines:(NSInteger)numberOfLines;
and passing in the bounds of the largest possible text view.
For extra credit, you may also want to consider animating the change in your view's bounds for a smoother transition.
This is rather odd. The contentSize should not clip contents, but only determine scrolling behavior. This however is the only thing changing from pre- to post-animation. And unchecking Clip Subviews always worked for me.
A few options:
I assume your UITextView.frame is large enough to contain the largest of both texts initially? If you set it just before the animation kicks in, you might be too late. In such cases tricks like [self performSelector(continueWithStuff:) withObject:object afterDelay:0.01] do wonders, because you give the UI the time needed to effectuate your changes before the animation will determine the initial state.
But the easiest fix by far will be to add a bunch of newlines to every text. Since you're not scrolling anyway this should not be a problem.
Another angle may be to embed your UITextView in a UIView which you then animate. Reading the docs, the view argument should be "The container view that contains the views involved in the transition." Ignoring this fact may be giving your surprising results.
The easiest way to fix you problem is to set the UITextView's property "clipsToBounds" to NO. This will make your text view available to draw outside of its bounds