hyperlink to section of text in uitextview - ios

I am trying to set up a 'Frequently Asked Questions' section on a UITextView. How do I link a line of text on a UITextView so that when the user clicks on it, the UITextView scrolls to a section of text in the same view. I would also like to underline the text and change the text color to blue.

try TTTAttributedLabel
TTTAttributedLabel allows you to automatically detect links for dates, addresses, links, phone numbers, transit information, or allow you to embed your own.
label.enabledTextCheckingTypes = NSTextCheckingTypeLink; // Automatically detect links when the label text is subsequently changed
label.delegate = self; // Delegate methods are called when the user taps on a link (see `TTTAttributedLabelDelegate` protocol)
label.text = #"Fork me on GitHub! (http://github.com/mattt/TTTAttributedLabel/)"; // Repository URL will be automatically detected and linked
NSRange range = [label.text rangeOfString:#"me"];
[label addLinkToURL:[NSURL URLWithString:#"http://github.com/mattt/"] withRange:range]; // Embedding a custom link in a substring

You need to first fetch the click event of the text "Frequentry asked questions". on the click event you need to make code for scrolling.
- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange
{
//Set your character range here
// if match return TRUE .
// else return FALSE.
}
On successful character range fetch scroll your textView to the questions by using this method.
CGPoint bottomOffset;
bottomOffset = CGPointMake(0,(Y value of the question));
[self.chatOutput setContentOffset:bottomOffset animated:YES];
This method will scroll the uitextview to the position of your question.

NSMutableAttributedString * str = [[NSMutableAttributedString alloc] initWithString:#"Google"];
[str addAttribute: NSLinkAttributeName value: #"http://www.google.com" range: NSMakeRange(0, str.length)];
yourTextField.attributedText = str;

Related

Set text(with emojis, special chars, links) in UILabel, and link should be clickable

In one of my application, there is API called and get data from server. In that there is text - which contains emojis, special characters, URLs, etc.
Not In my UITableViewCell, I have Simple UILabel and set text to label.
Till now everything is working fine.
But now I want that URLs in UILabel should be tappable, so when we click on URL and it should be open in Safari.
Note : As text is coming from server, so I don't know position of URL and there will be multiple URL as well.
What to do for that ? I have searched but didn't find solution.
I needed this kind of linked text for another project last month. I created a custom UITableViewCell with a UITextView object in the cell, subclassed to a custom UITextView subclass. I just made a quick demo project and put it up on git for you now. Feel free to use it.
github.com/fareast555/MPC_LinkedTextView
The basic secret sauce for using text links is the NSLinkAttributeName attribute in the mutable text, and telling the system to handle links.
- (void)updateTextViewWithFullText:(NSString *)fullText linkTriggerText:(NSString *)triggerText linkURLString:(NSString *)urlString
{
//Create a mutable string based on the full text
NSMutableAttributedString *mutableString = [[NSMutableAttributedString alloc]initWithString:fullText attributes:nil];
//Add the link attribute across the range of the target text
[mutableString addAttribute:NSLinkAttributeName value:urlString range:[fullText rangeOfString:triggerText]];
//Add any other font or color bling as needed
[mutableString addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:18 weight:UIFontWeightMedium] range:NSMakeRange(0, [fullText length])];
//Set the mutable text to the textfield
[self setAttributedText: mutableString];
}
#pragma mark - UITextViewDelegate
- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange interaction:(UITextItemInteraction)interaction
{
return YES;
}
- (BOOL)textViewShouldBeginEditing:(UITextView *)textView
{
return NO;
}
And for textviews, you'll find it easier to use auto layout if you turn off scrolling.
#pragma mark - Configure
- (void)_configureTextView
{
self.delegate = self;
[self setEditable:NO];
[self setSelectable:YES];
[self setScrollEnabled:NO];
[self setUserInteractionEnabled:YES];
[self setDataDetectorTypes:UIDataDetectorTypeLink];
self.scrollIndicatorInsets = UIEdgeInsetsZero;
}

How to enter different color String in UITextView use different languages

I want to choose the color and then change the text color of the UITextView currently entered use different languages
But I encountered the following problems
1.Can not find the last entered text
Demo picture
For example, in this case, I have not yet confirmed the entered text, but it has already been executed method
- (BOOL)textView:(UITextView *) textView shouldChangeTextInRange: (NSRange)range replacementText: (NSString *)text
I guess it is the first to create a range of characters, confirm the choice of input words, and then replace it
However, I do not need this input character range, which affects the NSRange parameters I need to change the color of the word
So I changed the color function into the textViewDidChange method, but it caused me to delete crashes
2.Why other languages except English do not execute method
- (void)insertText:(NSString *)text
This is my demo link https://github.com/xueyefengbao/Demo.git
Who can help me solve the problem or modify the features I mentioned in my demo?
Thank you very much :)
After trungduc's suggestion, I changed the code
Still Found some small problems
wrong
correct
Can not enter continuously
Continuous input error
For your questions.
Can not find the last entered text - Seem like you forgot to reset lastRange before deleting. But you don't use it any more so we can ignore it.
Why other languages except English do not execute method It's because in your language, with some case when you enter a character, it doesn't alway add a character to string. Actually, it replaces the last character with another one. It makes lastRange you get from shouldChangeTextInRange is out of range of current text on textView. My solution is before using [attributedString addAttribute:NSForegroundColorAttributeName value:self.currentColor range:self.lastRange];, you should check and correct self.lastRange.
You can try by replacing your methods with the code below.
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
if (text.length == 0) {
self.lastRange = NSMakeRange(0, 0); // Reset lastRange when deleting
return YES;
}
if ([text isEqualToString:#"\n"]) {
[textView resignFirstResponder];
}
BOOL result = [self doesFit:textView string:text range:range];
if (result) {
self.lastRange = NSMakeRange(range.location, text.length);
}
return result;
}
- (void)resetCorrectFontStyle:(UITextView *)textView {
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.lineSpacing = (textView.textContainer.size.height - (textView.font.lineHeight)*23)/23;
paragraphStyle.lineBreakMode = NSLineBreakByCharWrapping;
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc]initWithAttributedString:textView.attributedText];
[attributedString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, textView.attributedText.length)];
// Check if lastRange can't be used with current text, correct location of lastRange
if (_lastRange.length + _lastRange.location > textView.text.length) {
_lastRange = NSMakeRange(_lastRange.location - 1, _lastRange.length);
}
[attributedString addAttribute:NSForegroundColorAttributeName value:self.currentColor range:self.lastRange];
_keyboardTextView.attributedText = attributedString;
}
Hope this helps.

How to get n lines of text from UITextView in iOS

In my application i need to restrict to user enter 7 lines only in UITextView. When he tries enter text in 8 line we need to stop allowing editing and show an alert message. Its working fine by using CGSize of getting UITextView text.
But when user enters text in UITextView as Paste its not allowing if text is more than 7 lines. As per requirement i need to get the 7 lines of Text from entred (Copied & Pasted ) in to UITextView.
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)string
{
NSString *temp = [textView.text stringByReplacingCharactersInRange:range withString:string]
CGSize size = [temp sizeWithFont:textView.font constrainedToSize:CGSizeMake(textView.frame.size.width,999) lineBreakMode:UILineBreakModeWordWrap];
int numLines = size.height / textView.font.lineHeight;
if (numLines <= 8)
{
return true;
}
//Alert
return false;
}
Please help me in this issue.
Thanks in Advance.
You could use the UITextViewTextDidChangeNotification notification to alert you on other changes like text being pasted in. (referenced at the bottom of this page)
Or, there is also this handy category on UITextView that allows it to work with the UITextField UIControl events that can be found here.

iOS - appending string before and after the word

I want to add a string in the highlighted area in the textview, I mean by the highlighted area, where the blue line is located.
So once the user click on the button it adds a string where the "blue line" is located
I used stringByAppendingString but it adds the string after the word exists only
NSRange range = myTextView.selectedRange;
NSString * firstHalfString = [myTextView.text substringToIndex:range.location];
NSString * secondHalfString = [myTextView.text substringFromIndex: range.location];
myTextView.scrollEnabled = NO; // turn off scrolling
NSString * insertingString = [NSString stringWithFormat:#"your string value here"];
myTextView.text = [NSString stringWithFormat: #"%#%#%#",
firstHalfString,
insertingString,
secondHalfString];
range.location += [insertingString length];
myTextView.selectedRange = range;
myTextView.scrollEnabled = YES;
You need to use the selectedRange to find out where the text cursor is. Then use replaceCharactersInRange:withString: or insertString:atIndex: to insert the new text into the original text. Then update the text into the view.
Even though its not clear what you are trying to achieve, it seems that you want the user to start editing the textfield from the position where text starts. In that case , you can refer following:
Hint 1
Set your view controller (or some other appropriate object) as the text field's delegate and implement the textFieldDidBeginEditing: method like this:
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
UITextPosition *beginning = [textField beginningOfDocument];
[textField setSelectedTextRange:[textField textRangeFromPosition:beginning
toPosition:beginning]];
}
Note that setSelectedTextRange: is a protocol method of UITextInput (which UITextField implements), so you won't find it directly in the UITextField documentation.
Hint 2
self.selectedTextRange = [self textRangeFromPosition:newPos toPosition:newPos];
Hint 3
finding-the-cursor-position-in-a-uitextfield/

How to allow NSAttributedString text be typed into a UITextView?

I'm trying to allow different styles of text to be typed into a UITextView, a bit like a text editor using simple attributes such as bold or italics. I understand by using the textView's attributedText property I can apply attributes to certain ranges of text. This is nice, but I would like to be able to type attributed text into the textView, which would be toggled by a button (such as the typing of bold text).
Here's what I've thought of so far:
I've used the -(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text UITextView delegate method to take the text argument, and modify it with attributes by creating an NSAttributedString with the same text. Then create a NSMutableAttributedString, which is a copy of the textView's attributedText. Append the two using appendAttributedString, and then set the textView's attributedText property to the resulting attributedString.
Here's the code:
-(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
if (self.boldPressed) {
UIFont *boldFont = [UIFont boldSystemFontOfSize:self.textView.font.pointSize];
NSDictionary *boldAttr = [NSDictionary dictionaryWithObject:boldFont forKey:NSFontAttributeName];
NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc]initWithString:text attributes:boldAttr];
NSMutableAttributedString *textViewText = [[NSMutableAttributedString alloc]initWithAttributedString:textView.attributedText];
[textViewText appendAttributedString:attributedText];
textView.attributedText = textViewText;
return NO;
}
return YES;
}
Having to reset the textViews attributedText every time a character is typed seems like a bit much for a simple action. Not only that, but it doesn't work properly. Here's what it looks like when the bold attribute is enabled:
There are two problems with this. The most obvious being how every new character is put onto a new line. But what's also strange is that the insertion point is always at the very first index of the text in the textview (only when bold is enabled, yet the bold character is inserted on a new line). So if you're typing with bold enabled, and then turn bold off, typing resumes in front of all existing text.
I'm not sure why these error are happening. I also just don't think that my solution is very efficient, but I can't think of any other way of implementing it.
This is what setTypingAttributes: is for. Set this to your attribute dictionary whenever the user presses one of your attribute buttons and new characters will pick up the requested attributes.
Here are sample codes to do so if you are looking for examples
Swift 3.0
var attributes = textField.typingAttributes
attributes["\(NSForegroundColorAttributeName)"] = UIColor.red
textField.typingAttributes = attributes
Objective-C
NSMutableDictionary* attributes = [textField.typingAttributes mutableCopy];
attributes[NSForegroundColorAttributeName] = [UIColor redColor];
textField.typingAttributes = attributes;

Resources