UITextView Scrolling / ContainHeight unusual behaviour - iphone

I need to change UITextView Frame height dynamically with respect to content height of it. i.e. so when ever contain height is increased rather than allowing user to scroll i would like to change my UITextView's Frame height so users can read all data.
So here i my code snipper,
-(void)viewDidLoad{
[super viewDidLoad];
_txtView.delegate = self;
previousheight = _txtView.contentSize.height;
NSLog(#"%.2f",previousheight);
}
Here i am getting log value -> 22.
-(void)textViewDidChange:(UITextView *)textView{
NSLog(#"%.2f",textView.contentSize.height);
}
Here i am getting log value -> 36.
===============================================================================
Now another way, if i disable scrolling of UITextView then i am getting perfect/expected result. Only thing is i am not able to enable scrolling afterward.
-(void)viewDidLoad{
[super viewDidLoad];
_txtView.scrollEnabled = FALSE;
previousheight = _txtView.contentSize.height;
NSLog(#"%.2f",previousheight);
}
Here i am getting log value -> 30.
-(void)textViewDidChange:(UITextView *)textView{
NSLog(#"%.2f",textView.contentSize.height);
txtView.scrollEnabled = TRUE;
}
Here i am getting log value -> 30.
But now there are no scrolling, although i have enable scrolling view.
Any help would be appreciated.
Thanks

I have reported this as a bug on iOS 7.0 to Apple yesterday.
I can calculate the text height correctly using 'boundingRectWithSize:...' but if scrolling is disabled the text gets cut off no matter the height.
A solution that sometimes works is:
textView.scrollEnabled = TRUE;
textView.text = #"Lorem ipsum...";
textView.scrollEnabled = FALSE;

Related

UICollectionViewCells with UICollectionViewFlowLayout - strange layout happening

I am currently testing in xcode a UICollectionView with just one horizontal row like a kinda cover flow. Basically I have my own Custom Cell class and xib file for the cell and then on each cell I am adding another UIView with a xib. In case you are wondering why, it is so I can add different UIViews to the cell. Right now I am only adding one.
Edit I have followed the WWDC 2012 video on creating a linelayout of a UICollectionViewCell with one difference. Instead of the cell in the middle getting bigger all the other cells get smaller.
Everything below is new to my question.
-(NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {
NSArray *array = [super layoutAttributesForElementsInRect:rect];
CGRect visibleRect;
visibleRect.origin = self.collectionView.contentOffset;
visibleRect.size = self.collectionView.bounds.size;
for (UICollectionViewLayoutAttributes *attributes in array){
if (CGRectIntersectsRect(attributes.frame, rect)) {
CGFloat distance = CGRectGetMidX(visibleRect) - attributes.center.x;
CGFloat normalizedDistance = distance / ACTIVE_DISTANCE;
if (ABS(distance) < ACTIVE_DISTANCE) {
//THIS WOULD MAKE THE MIDDLE BIGGER
//CGFloat zoom = 1 + ZOOM_FACTOR *(1- ABS(normalizedDistance));
//attributes.transform3D = CATransform3DMakeScale(zoom, zoom, 1.0);
//attributes.zIndex = round(zoom);
} else {
//THIS MAKES ALL THE OTHERS NOT IN THE RECT SMALLER
CGFloat zoom = 1 + ZOOM_FACTOR *(1- ABS(normalizedDistance));
attributes.transform3D = CATransform3DMakeScale(zoom, zoom, 1.0);
attributes.zIndex = round(zoom);
}
}
}
return array;
}
The problem can be seen in the attached image.
Pink = Collection View Size
Brown = Cell size
Green = Cells Content size and an attached xib to the content size.
The problem I THINK I have is with the layout. When the sell is dequeued it is made smaller by the above code. Then when it is reused the CELL gets bigger again but the content view does not.
I have tired to manually set the frame of the content view but that does nothing.
UPDATE 1: This also only happens when I add a xib to the Cells content view. If there is no subview to the content view then there is no problem
UPDate 2: It appears that the subview of the cell, my xib is not resizing. I have tried to manually change its frame size but the only place this helps is in the cells drawrect method which feels like a hack to me.
reused cell not able to redraw itself so give call to
-(void)setFrame:(CGRect)frame {
[super setFrame:frame];
[self setNeedsDisplay]; // force drawRect:
}
from cellForItemAtIndexPath of the UICollectionView.
also have a look at this link
and this question
My answer is very specific and I am not sure it will help anyone.
The problem was that I had a constraint on the bottom of the grey view. After I changed this constraint to a less than or equal too then for some reason it worked.
Now I know this does not explain why it was not happening to every cell but it fixed my problem.
As such Harsh's answer might also be worth looking at if you have landed here after doing a search.
Edit: there also appears to be some bugs in the 6.0 UiCollectionView controller which seem to be fixed in 6.1

How can I get the UITextView to scroll only when it's full of text

I have this UITextView that works great except, I can't get the text inside the UITextView to start scrolling only after the UITextView's size in nearly full, the UITextView is 4 lines tall, but as soon as I reach the 2nd line the 1st line is pushed up, I don't want the view to begin scrolling until I've reached the 5 line. scrollingEnabled = NO keeps it from scrolling at all, so that didn't work.
UITextView *barf_ = [[UITextView alloc] initWithFrame:CGRectMake(20.0, 310.0, 155, 50)];
barf_.contentInset = UIEdgeInsetsMake(0, 0, 0, 0);
//[barf_ scrollRangeToVisible:NSMakeRange([barf_.text length], 0)];
barf_.layer.cornerRadius = 3.0f;
barf_.layer.borderWidth = 0.5f;
barf_.font = [UIFont fontWithName:#"Helvetica" size:13];
I found the answer, as others with similar problems have mention, with a small textView, it automatically adds 32 padding to the bottom.
A simple fix is to add YourTextView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0); inside shouldChangeTextInRange method, that fixed my problem!
Setting the contentInset may help the text to appear more correctly within the UITextView. However, it won't help solve the issue whereby the UITextView has scrolling enabled despite not having more text to view.
Similarly, methods such as sizeWithFont have limitations. As explained in Mike Weller's excellent blog series iOS Development: You're Doing It Wrong, NSString isn't a good object to ask regarding how large a UIView should be. Many UIView subclasses such as UILabel, UIButton, etc. have insets and other considerations that must be accounted for during sizing. UITextLabel is no exception.
Mike Weller's particular entry on this subject is:
You're Doing It Wrong #2: Sizing labels with -[NSString sizeWithFont:...]
iOS 7 promises us more sophisticated text handling in UITextView, with properties such as textContainerInset. But what to do in the meantime?
Well, first we know that UITextView is a subclass of UIScrollView. Therefore, the golden rule that if the contentSize is larger than the view's bounds property, the scroll view will scroll so we can see more content.
Checking out contentSize agains the bounds won't work either because we know that UIScrollView is already calculating whether it should scroll or not based on the text, and it's giving us the wrong answer.
This is where arbitrary adjustment values come to the rescue! For me this value was 17.f. For you - depending on your fonts - it maybe different. We then take control and decide whether we should allow the scroll view to scroll:
static const CGFloat kArbritaryHeight = 17.f;
CGFloat adjustedContentHeight = myTextView.contentSize.height - kArbritaryHeight;
CGFloat boundsHeight = CGRectGetHeight(myTextView.bounds);
BOOL tooMuchContent = adjustedContentHeight > boundsHeight;
if (tooMuchContent)
{
myTextView.scrollEnabled = YES;
}
else
{
myTextView.scrollEnabled = NO;
}
When your UITextView is loaded set scrollEnabled to NO. Then set the text view's delegate to self or some other object and implement the UITextViewDelegate method
- (void)textViewDidChange:(UITextView *)textView
This method will get called anytime the user makes a change to the text inside the view. Inside this method you need to figure out how big your text is and if it goes beyond the bounds of the text view. If so you enable scrolling. Use this method:
- (CGSize)sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size lineBreakMode:(UILineBreakMode)lineBreakMode
This is a UIKit category method on NSString. It returns a CGSize that will tell you the height of whatever text string you call it on. In your case it would be something like
CGSize textSize = [textView.text sizeWithFont:textView.font
constrainedToSize:CGSizeMake(textView.frame.size.width, MAXFLOAT)
lineBreakMode:UILineBreakModeWordWrap];
if (textSize.height > textView.frame.size.height) {
textView.scrollEnabled = YES;
} else {
textView.scrollEnabled = NO;
}
You might use the sizeWithFont:constrainedToSize:lineBreakMode: method to check whether your string will actually render larger than your text view and see if you need to enable scrolling. You will have to call it any time the text in your scrollview is set, however.
ex:
CGSize barfStringSize = [barfString sizeWithFont:[barf_ font]
constrainedToSize:CGSizeMake(barf_.bounds.size.width, MAXFLOAT)
lineBreakMode:UILineBreakModeWordWrap]
[barf_ setScrollEnabled:barfStringSize.height > barf_.bounds.size.height]

Uitextview scroll view position

I am trying to implement UITextView in my iphone app. UITextView's content increases dyamically.
At same time I want to move scroll position also.
I am trying to scrollToVisibleRect method, but not getting any success.
Thanks
If I understand your question properly then you want to scroll your text view at the bottom of text. To do so try this :
- (void) goToBottom
{
NSUInteger length = self.myTextView.text.length;
self.myTextView.selectedRange = NSMakeRange(length, 0);
[myTextView setContentOffset:CGPointMake(length, 0) animated:YES];
}

UIScrollView problem, scrolls just on one side

I'm fairly new to programming, and I have looked for an answer for a very long time. There are some posts about it, but nothing has solved my problem. I have a UIScrollView view that I get from the nib, everything is ok with this, the content length is good and scrolling works, but it just scrolls on the left side, if I try to scroll on the right side it doesn't scroll..
Here is the code,
- (void)viewDidLoad {
[super viewDidLoad];
NSString *descriptionString = _currentBook.description;
CGSize stringSize = [descriptionString sizeWithFont:[UIFont boldSystemFontOfSize:16] constrainedToSize:CGSizeMake(387, 9999) lineBreakMode:UILineBreakModeWordWrap];
_authorLabel.text = _currentBook.author;
_titleLabel.text = _currentBook.title;
_descriptionLabel.text = [NSString stringWithFormat:#"Description: %#",_currentBook.description];
[(UIScrollView *)self.view setContentSize:CGSizeMake(387, stringSize.height +50)];
}
Thanks in advance!
Its hard to understand the problem since we cant see your nib file, but its better practice to put the scrollView on top the view of the view controller, and connect it to an IBOutlet in your view controller.
In order to find the problem I would get rid of the textfields for testing purposes (I think the constrained 9999 might be a problem but I am not sure) and then print and post the frame of the scrollView and the Content size in runtime.I am betting that you will see some issue with the frame of the uiscrollview.
Thanks,
Ok, after copy-pasting and running some tests, I found out the problem.
The problem is in the wording of the question, your problem is not that the "scroll doesn't work on the right side" (As in: you move your finger up and down on the right side of the screen without triggering a scroll), the problem is that the contents, the label itself is going out of bounds, outside of the visible area of the scrollView, and the right-handed side is not visible.
First of all, you should note that the iphone resolution is 320x480 (640x960 for Retina), so you actually have to work with a smaller width (using 387 width will make it go out of bounds).
Second, take in account the x position of the label itself is also affecting the amount of visible text. With this in mind, a more generic code would be:
- (void)viewDidLoad
{
[super viewDidLoad];
// This number represents the total width of the label that will fit centered in
// the scrollView area.
CGFloat visibleWidth = self.view.frame.width - descriptionLabel.frame.origin.x*2;
// Use the number above to get a more accurate size for the string.
NSString *descriptionString = _currentBook.description;
CGSize stringSize = [descriptionString sizeWithFont:[UIFont boldSystemFontOfSize:16] constrainedToSize:CGSizeMake(visibleWidth, 9999) lineBreakMode:UILineBreakModeWordWrap];
// Fill data (why so many underscores?)
_authorLabel.text = _currentBook.author;
_titleLabel.text = _currentBook.title;
_descriptionLabel.text = [NSString stringWithFormat:#"Description: %#", _currentBook.description];
// Also, why didn't you resize the description label? I'm assuming that you forgot this.
// (Make sure that the descriptionLabel number of lines is 0)
CGRect frame = descriptionLabel.frame;
descriptionLabel.frame.size = stringSize;
// Now set the content size, since you're using the scrollView as the main view of the viewController,
// I'll asume that it's using the whole screen, so I'm gonna use the whole width
// of the screen (that's what UIScreen is for).
[(UIScrollView *)self.view setContentSize:CGSizeMake([UIScreen mainScreen].bounds.size.width, stringSize.height +50)];
}
Finally i've found my problem, I've added a uiview programmatically as a subview to some view and then to this View i've added my scroll view as a subview.. And then it would only scroll in the area of my UIView. It was nonsense to do it like this, still a lack of knowledge..
Thank you all for trying to help!

How to entirely disable UITextView's scroll?

I'm developing a simple text editing app for iPad using UITextView. I always had some problems with UIScrollView and UITextView. I think I just expected too much things from these two.
When I set myTextView.text to another a NSString instance, scrolling automatically occurred. I could prevent this scrolling by setting
myTextView.scrollEnabled = NO;
myTextView.text = newText;
myTextView.scrollEnabled = YES;
However, if I changed the selectedRange property of myTextView, scrolling occurred.
Specifically, if selectedRange's range happened on text in the current screen, scrolling didn't occur.
For example, if I select all text by tapping "Select All" property, then scrolling didn't occur. But if I select all text by setting selectedRange to NSMakeRange(0, [myTextView.text length]), then scrolling to the END (the last caret position) occured.
To solve the problems,
1) I saved the original content offset of myTextView.
CGPoint originalOffset = myTextView.contentOffset;
// change myTextView.selectedRange here
myTextView.selectedRange = originalOffset
But nothing happend.
2) I called above codes after a few seconds using NSTimer, and scroll correctly returned to the original position(offset). However, scrolling to the end first occurred and then to the top..
Is there a way to entirely prevent UITextView's scrolling for a moment?
You can disable almost all scrolling by putting the following method into your UITextView subclass:
- (void)scrollRectToVisible:(CGRect)rect animated:(BOOL)animated {
// do nothing
}
The reason I say "almost" all scrolling is that even with the above, it still accepts user scrolls. Though you could disable those by setting self.scrollEnabled to NO.
If you want to only disable some scrolls, then make an ivar, lets call it acceptScrolls, to determine whether you want to allow scrolling or not. Then your scrollRectToVisible method can look like this:
- (void)scrollRectToVisible:(CGRect)rect animated:(BOOL)animated {
if (self.acceptScrolls)
[super scrollRectToVisible: rect animated: animated];
}