Scroll bug using UITextView in iOS 8.1 (iPad 2) - ios

The problem which I have is same as: Smooth UITextView auto scroll to bottom of frame
Basically, when I use the auto scroll feature when appending a text to an existing text in UITextView, the scroll works, but it always goes to top then scroll all the way to bottom (which is a problem for big texts, or a chat room)
When I try the solution of this guy, which was :
textview.scrollEnabled= NO;
textview.text = [textview.text stringByAppendingString:createdString];
textview.scrollEnabled= YES;
[textview scrollRangeToVisible:textview.selectedRange];
So, I found a bug where it seems that the 'textview.scrollEnabled' never gets back to YES, so the scroll will simply never work.
I either have that weird scrolling where it gets back to top then to bottom or the other bug where the scrolling enabled never gets back to YES.

This should work for you.
Get rid of the textView.scrollEnabled = NO;.
So your just left with:
textview.text = [textview.text stringByAppendingString:createdString];
[textview scrollRangeToVisible:textview.selectedRange]
and add this to your viewDidLoad:
textview.layoutManager.allowsNonContiguousLayout = NO;

I had similar problem too where scroll works fine in iOS 7 and iOS 9 but not in iOS 8. So, I found solution for scrolling to work in iOS 8 is:
NSString *strValue = [NSString stringWithFormat:#"Your text"];
txtVwObj.text = strValue; // If in your case text needs to give before scroll disable.
txtVwObj.scrollEnabled = NO;
// and set whatever you need for UITextView properties.
// at last add the following code snippet.
txtVwObj.scrollEnabled = YES;
txtVwObj.text = #"";
txtVwObj.text = [txtVwObj.text stringByAppendingString:strValue];
Hope it will help you.

Related

Removing Keyboard Top Bar [duplicate]

I'm trying to update an app for iOS8, which has a chat interface, but the new Quicktype keyboard hides the text view, so I would like to turn it off programmatically or in interface builder.
Is it possible somehow or only the users can turn it off in the device settings?
I know there is a question/answer which solves this problem with a UITextfield, but I need to do it with a UITextView.
You may disable the keyboard suggestions / autocomplete / QuickType for a UITextView which can block the text on smaller screens like the 4S as shown in this example
with the following line:
myTextView.autocorrectionType = UITextAutocorrectionTypeNo;
And further if youd like to do this only on a specific screen such as targeting the 4S
if([[UIDevice currentDevice]userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
CGFloat screenHeight = [UIScreen mainScreen].bounds.size.height;
if (screenHeight == 568) {
// iphone 5 screen
}
else if (screenHeight < 568) {
// smaller than iphone 5 screen thus 4s
}
}
For completeness sake I would like to add that you can also do this in the Interface Builder.
To disable Keyboard Suggestions on UITextField or UITextView — in the Attributes Inspector set Correction to No .
I've created a UITextView category class with the following method:
- (void)disableQuickTypeBar:(BOOL)disable
{
self.autocorrectionType = disable ? UITextAutocorrectionTypeNo : UITextAutocorrectionTypeDefault;
if (self.isFirstResponder) {
[self resignFirstResponder];
[self becomeFirstResponder];
}
}
I wish there was a cleaner approach tho. Also, it assumes the auto-correction mode was Default, which may not be always true for every text view.
In Swift 2:
myUITextField.autocorrectionType = UITextAutocorrectionType.No
In Swift 4.x:
myUTTextField.autocorrectionType = .no
As others have said, you can use:
textView.autocorrectionType = .no
but I've also noticed people struggling with actually making the autocomplete bar swap out, since if the textView is already the firstResponder when you change its autocorrectionType, it won't update the keyboard. Instead of trying to resign and reassign the firstResponder status to the textView to effect the change, you can simply call:
textView.reloadInputViews()
and that should hide the autocomplete bar. See https://developer.apple.com/documentation/uikit/uiresponder/1621110-reloadinputviews

Bounds automatically changes on UIScrollView with content insets

I'm using a UIScrollView as my paging scroll view, pagesScrollView. Inside that, I put individual UIScrollViews which are used exclusively for zooming. Inside each of those, I have one view which is the page item which should be zoomable. All of that is inside a UINavigationController with a translucent navbar.
My pagesScrollView has contentInset.top = 64 and bounds.origin.y = -64 (that seems weird to me, but that's what the system is setting automatically for me), and this works just fine. My screen looks great!
However, after I scroll the pagesScrollView even a tiny bit, as soon as scrollViewWillEndDragging is called, the pagesScrollView begins an animated change from bounds.origin.y = -64 to bounds.origin.y = 0 which causes my page items to be obscured by the navbar.
On the left is what it looks like when it loads, on the right is what it looks like after I drag just a few pixels and then let go, it slides up under the navbar (because the bounds.origin.y goes to 0).
The problem is that I don't have any code that is altering the bounds and I don't have any code in the various scroll delegate methods that do anything. I've added a bunch of scroll delegate methods and just added NSLog()s so I can figure out when/where the change is happening, but it's not happening anywhere in my code.
So, I don't know what code I can show you to help you help me.
EDIT: I built a new project from scratch to remove all other variables.. I put a bare UIViewController into a UINavigationController. I put a UIScrollView into my View the entire size of the view. The following code is the entire project.
It turns out the issue (described below) only appears once PAGING IS ENABLED on the UIScrollView! Wtf? :)
Here is a link to download a basic project with only a few lines of code which demonstrates the problem. Just click in the scrollview and you'll see it shift up as the bounds change. http://inadaydevelopment.com/stackoverflow/WeirdScrollViews.zip
How can I have paging enabled on my scrollview without the bounds freaking out during scrolling and shifting everything under the nav bar?
It's possible to set the navbar to opaque and the problem is avoided, but the ideal is to have standard iOS7 behavior so that after the content view is zoomed, THEN the content is allowed to be under the navbar and should show through the translucency normally.
- (void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
NSArray *colors = #[
[UIColor blueColor],
[UIColor orangeColor],
[UIColor magentaColor],
];
NSArray *zoomerColors = #[
[UIColor greenColor],
[UIColor yellowColor],
[UIColor purpleColor],
];
self.scroller.pagingEnabled = YES;
[self.scroller setContentSize:CGSizeMake(self.scroller.frame.size.width*colors.count, self.scroller.frame.size.height)];
CGRect subviewFrame = CGRectMake(0, 0, 160, 240);
for (int index=0; index < colors.count; index++) {
UIColor *color = [colors objectAtIndex:index];
UIColor *zoomerColor = [zoomerColors objectAtIndex:index];
UIView *subview = [[UIView alloc] initWithFrame:subviewFrame];
subview.backgroundColor = color;
CGRect zoomerFrame = CGRectMake(index*self.scroller.frame.size.width, 0, self.scroller.frame.size.width, self.scroller.frame.size.height);
UIScrollView *zoomer = [[UIScrollView alloc] initWithFrame:zoomerFrame];
[zoomer addSubview:subview];
zoomer.backgroundColor = zoomerColor;
[self.scroller addSubview:zoomer];
}
}
Just switch off Adjust Scroll View Insets
It's an iOS bug. I created the following subclass of UIScrollView to get a log of what happens to y over time and who was pushing it:
#implementation CSScrollView
- (void)setContentOffset:(CGPoint)contentOffset
{
NSLog(#"%0.0f %#", contentOffset.y, [NSThread callStackSymbols]);
NSLog(#"[%#]", self.layer.animationKeys);
[super setContentOffset:contentOffset];
}
#end
(and changed the view class in the storyboard)
When you release your finger, a method called UIScrollView _smoothScrollDisplayLink: starts animating the scroll view to its final position. As per the second log, there's no CAAnimation involved, the scroll view uses its own display link to do its own transition. That custom code appears to make the mistake of animating from y = whatever to y = 0, failing to take the content offset into account.
As a proof-of-concept hack I changed the code to:
#implementation CSScrollView
- (void)setContentOffset:(CGPoint)contentOffset
{
contentOffset.y = -64.0f;
[super setContentOffset:contentOffset];
}
#end
And, unsurprisingly, the problem went away.
You probably don't want to hard code the -64.0f but I'd conclude:
it's an iOS bug;
work around it by rejecting nonsensical values via a subclass of UIScrollView with a suitable custom implementation of - setContentOffset:.
A sensible generic means might be to check the state of self.panGestureRecognizer — that'll allow you to differentiate between scrolls the user is responsible for and other scrolls without relying on any undocumented API or complicated capturing of delegate events. Then if necessary crib the correct contentOffset.y from the current value rather than hardcoding it.
My pagesScrollView has contentInset.top = 64 and bounds.origin.y = -64 (that seems weird to me, but that's what the system is setting automatically for me), and this works just fine. My screen looks great!
It because of iOS 7 sets contentInset.top to 64 on all scrollviews.
Just add this line of code into your view controller and all will work as expected:
-(UIRectEdge)edgesForExtendedLayout {
return UIRectEdgeNone;
}
I checked on your example project.
I have checked you example use below code in viewController.m file
-(void)viewDidLoad
{
if ([[UIDevice currentDevice] systemVersion].floatValue>=7.0) {
self.edgesForExtendedLayout = UIRectEdgeNone;
}
}
It's working fine...
It turns out the issue (described below) only appears once PAGING IS ENABLED on the UIScrollView! Wtf? :)
As you said that, If you enable the scroll paging, the UIScrollView will stop at a paging edge after a dragging or any movement, which is promised by the framework. Bounds.origin.y set by zero means that the first page edge matched the scroll view frame edge, cuz you have 64 contentInsets there. So that's not bug, that is what it is. And since your bar is translucent, remember where is your scroll view's frame edge, it's under the bar. In a word, this is not a bug, I think, but a effect of scroll paging.

dataDetectorTypes sometime hyperlinking the all the text

I have setup my TextView to look for hyperlinks as such:
commentText.dataDetectorTypes = UIDataDetectorTypeLink;
Sometimes, this works great, finding the links in my text and making the appropriate hyperlinks. Sometimes however, it will select all the text in the screen even if there isn't a hyperlink in the text. Has anyone ever encountered this problem or know how to use this properly?
Thanks,
Collin
Once i had the problem, it was when i was using cells and the reuse on the cells was making this bug
So i had to override preparetoreuse like this to reset the settings
- (void)prepareForReuse
{
_bodyTextView.editable = YES;
_bodyTextView.editable = NO;
_bodyTextView.font = fontText;
_bodyTextView.textColor = [UIColor colorWithHexString:MyStyle(#"todayFontColorText")];
}
Hope it kinda help...

UITextView link detection in iOS 7

I have a UITextView which is managed via Interface Builder. As data detection I have "Links" checked. In iOS 6 everything is working fine and links are highlighted and are clickable. In iOS 7 though, all links remain just plain text. The editable and selectable checkboxes are unchecked.
What may be of concern is that the UITextView is a subview of a container view which is again inside a UIScrollView.
It seems that in iOS 7 link detection only works if the UITextView is selectable. So making my UITextView not selectable stopped the the link detection from working.
I also tested this in iOS 6 and I can confirm that in iOS 6 the link detection works fine even with the UITextView not being selectable.
I was having some problems with phone number detection today. It seemed like the UITextView would retain old phone numbers and keep text highlighted after I had set the text to something else.
I found that if I setText:nil before setting the text to the new string, it would reset the textview, and phone numbers would highlight as normal. I'm wondering if this is some kind of bug with UITextView in iOS 7.0
Either way, this did work for me.
When iOS7 first came out this plagued me and I found an answer in this thread (setting the text attribute of the UITextView to nil before setting the actual value did the trick). Then suddenly, the problem (for me it was the entire string being highlighted as a link) cropped back up (assumedly due to an iOS update).
What finally did the trick for me was to stop using the text attribute and set the attributedText. Once I did this, the need for setting fonts/scrolling/selectable/editable/etc. programmatically, disappeared. I defined my UITextView in IB, set the values as I wanted (not scrollable, not editable, selectable, detecting links and phone numbers) and then built an attributed string and set:
myUITextView.attributedString = myAttributedString;
And suddenly everything worked as expected. Hope this helps someone else down the road.
I had the same issue and disabling scrolling on the UITextView activates the link detection on load rather than only working once the user has interacted with the textview. The UITextView also had to be selectable and non-editable.
detailTextView.scrollEnabled = NO;
detailTextView.editable = NO;
detailTextView.selectable = YES;
Being selectable or having scroll enabled isn't necessary on iOS6.
Another thing to check is that userinteraction is enabled on the cell and content view of the cell, otherwise the link won't be clickable.
Check These Lines must be added to use data detector property of textview in UItableView cell.
txtvwMsgText.userInteractionEnabled = YES;
txtvwMsgText.dataDetectorTypes = UIDataDetectorTypeLink;
txtvwMsgText.scrollEnabled = NO;
txtvwMsgText.editable = NO;
txtvwMsgText.selectable = YES;
You should check out NSDataDetector.
You can use this to find and deal with different data (links, phone numbers and more). Have a look on this site:
http://nshipster.com/nsdatadetector/
You can also use the dataDetectorTypes property of UITextView to set what you want to detect in code. May just be a storyboard transition problem for you.
textView.dataDetectorTypes = UIDataDetectorTypeLink;
Be aware, that your textview will only recognize the links if not editable!
Here is a nice tutorial on how to make an editable UITextView with `link detection``
Editable UITextView with link detecion
I've not experienced any problems with that solution since now.
The trick is a GestureRecognizer forwaring touches and enabling/disabling the editing.
You could apply the same thing with the selectable / not selectable issue on iOS7
After few tests, I found solution.
If you want links active and you don't want selection enabled, you need to edit gestureRecognizers.
For example - there are 3 LongPressGestureRecognizers. One for click on link (minimumPressDuration = 0.12), second for zoom in editable mode (minimumPressDuration = 0.5), third for selection (minimumPressDuration = 0.8). This solution removes LongPressGestureRecognizer for selecting and second for zooming in editing mode.
NSArray *textViewGestureRecognizers = self.captionTextView.gestureRecognizers;
NSMutableArray *mutableArrayOfGestureRecognizers = [[NSMutableArray alloc] init];
for (UIGestureRecognizer *gestureRecognizer in textViewGestureRecognizers) {
if (![gestureRecognizer isKindOfClass:[UILongPressGestureRecognizer class]]) {
[mutableArrayOfGestureRecognizers addObject:gestureRecognizer];
} else {
UILongPressGestureRecognizer *longPressGestureRecognizer = (UILongPressGestureRecognizer *)gestureRecognizer;
if (longPressGestureRecognizer.minimumPressDuration < 0.3) {
[mutableArrayOfGestureRecognizers addObject:gestureRecognizer];
}
}
}
self.captionTextView.gestureRecognizers = mutableArrayOfGestureRecognizers;
Tested on iOS 9, but it should work on all versions (iOS 7, 8, 9).
I hope it helps! :)
I've found the trick, this works in iOS 7!
You have to set the UITextView selectable in your xib or programmatically
self.yourTextView.selectable = YES;
and then you have to disable scrolls and enable again after set your text.
self.yourTextView.scrollEnabled = NO;
[self.yourTextView setText:contentString];
self.yourTextView.scrollEnabled = YES;
So using a UITextView keeping it enabled, selectable, not scrollable & links detectable is not as simple as it seems. I encountered this in iOS 8. So my solution was to do something like this in viewDidLoad and then set editable property to NO when textBox editing is done(usually would be a method like doneIsTapped). The trick here is to set editable property to NO after setting text value to textview is completed. This will enable links in the UITextview.
- (void)viewDidLoad
{
[super viewDidLoad];
self.txtViewComment.editable = YES;
self.txtViewComment.selectable = YES;
self.txtViewComment.dataDetectorTypes = UIDataDetectorTypeLink;
self.txtViewComment.scrollEnabled = NO;
}
and
- (IBAction)doneIsTapped:(id)sender
{
self.txtViewComment.text = #"set text what ever you want";
self.txtViewComment.editable = NO;
}
this made the links enabled in textview. Also I would recommend not to use story board at this time(or until apple fixes this problem) and just use code to avoid any unnecessary confusion. Hope this help.
Deactivating UITextViews scrolling ability did the trick for me in a similar setup.
Changing the Tint color to other color actually works.
However if selectable enable the tint will also be the same color.
Make the scrolling property of UITextView to No. it will work...
Self.textView.ScrollingEnable = NO;
None of the above worked for me, instead I did this:
[self.textView setDataDetectorTypes:UIDataDetectorTypeNone];
[self.textView.setTextColor:[UIColor whiteColor]];
[self.textView setDataDetectorTypes:UIDataDetectorTypeNone];
I did this with my textview that was supposed to detect all types, and which had non detected color set to white. You can change the code to represent your proper color and link types to detect.
While this thread is old, I didn’t see an answer that worked for me with Swift, so here goes for Swift 2.2
textView.dataDetectorTypes = UIDataDetectorTypes.Link
textView.selectable = true
This workaround works for me:
textView.selectable = YES;
textView.delegate = self;
- (void) textViewDidChangeSelection:(UITextView *)textView;
{
NSRange range = NSMakeRange(NSNotFound, 0.0);
if ( range.length && !NSEqualRanges(range, textView.selectedRange) ) {
textView.selectedRange = range;
}
}
If you are adding UITextview programmatically just add below lines:
_textView.userInteractionEnabled = YES;
_textView.dataDetectorTypes = UIDataDetectorTypeLink;
_textView.scrollEnabled = NO;
_textView.editable = NO;
This worked for me.

How to prevent the keyboard from showing (not dismissing) on a TextView?

I would like to know how to DISABLE (not how to dismiss) the iOS keyboard in a TextView. I don`t even want the keyboard to show up when the user touches the TextView.
All of the examples I found were to make the keyboard disappear AFTER it appears.
The closest thing I got was to set textView.userInteractionEnabled = NO; but that gets rid of the scrolling as well (I want to keep the scrolling).
Thank you in advance!!
Try to implement the following method in text view's delegate:
- (BOOL)textViewShouldBeginEditing:(UITextView *)textView{
return NO;
}

Resources