How to find position or get rect of any word in textview and place buttons over that?
Asked Answered
M

4

15

I am working on a story app.Where We need to provide quizes. Now I am having a story and there are some blanks or hidden words over that story. Whenever I click over that hidden word,I will get the 4 options to answer that. I tried by placing button over the words,But that would be only when I am using some static position. I just want to know how can I get the frame of that word,which I need to hide ,so that I can place some button over that and can hide this.

You can see the image below..enter image description here All answers would be appreciated

Solution:- This will work after iOS 5 only not below that !

- (CGRect)frameOfTextRange:(NSRange)range inTextView:(UITextView *)textView
{
    UITextPosition *beginning = textView.beginningOfDocument; 
    UITextPosition *start = [textView positionFromPosition:beginning offset:range.location];
    UITextPosition *end = [textView positionFromPosition:start offset:range.length];
    UITextRange *textRange = [textView textRangeFromPosition:start toPosition:end];
    CGRect rect = [textView firstRectForRange:textRange]; 
    return [textView convertRect:rect fromView:textView.textInputView];



}

Thanks

See one more image for errors: enter image description here

Monseigneur answered 25/4, 2012 at 10:18 Comment(0)
H
19

UITextView adopts the UITextInput protocol. That protocol has the method -firstRectForRange: which will tell you the rectangle covering a range of characters. If the range of characters spans multiple lines, you have to call it repeatedly. The first time it will give you the first rect and tell you what range that covers. Then, you adjust the range you're asking about to be the remaining characters you're interested in and repeat.

Homograph answered 25/4, 2012 at 11:24 Comment(25)
Can you explain more or any examples as how to use this or some tutorial ,As i dont have any idea how to use that...If you can put me in some right direction further...I will appriciate that...Monseigneur
See the answer to this question. I'm not sure if the -convertRect:fromView: call in that answer is appropriate for your case.Homograph
Fine Ken...I will check and let you know...Thanks ManMonseigneur
I tried this method..but it is showing me many errors there, even I had tried the same answer from somewhere that has the errors as well...So could you clarify as well...Monseigneur
Update your question with what you tried and how it failed. Be specific.Homograph
Hi Ken I have updated above ,please do check and let me know what I am missing or doing wrong. ThanksMonseigneur
Strange. What iOS SDK are you targeting? You imported the framework header (e.g. #import <UIKit/UIKit.h>), right? You can try replacing the dot syntax with accessor calls like [textView beginningOfDocument].Homograph
I have tried by removing dot notation....and that gave me warning ,But other lines are showing errors as well....What could be the issue then.. and base ios SDk is 4.2Monseigneur
What warning did it give you? Show it and the line of code to which it refers exactly.Homograph
I have updated my question and I have written the Erro to the corresponding line before.Please check to the right of every line of code above.Please have a look...ThanksMonseigneur
But you said you tried removing the use of dot syntax in favor of calling accessors explicitly and got different warnings. That's not what I see above.Homograph
Hi Ken ,I have uploaded one more image which shows errors and warnings.Sorry for delay,i was out of city...I am waiting for reply...ThanksMonseigneur
I'm not sure what to tell you. UITextView really ought to declare that it responds to those messages. I ask again: are you sure you imported the proper headers?Homograph
I have imported #import <UIKit/UIKit.h> now only..in my .h file...Is there any other header I need to include,Or is there any other framework I need to include....Monseigneur
I found the reason,the reason is that it only works in ios 5 with sdk 4...Thanks though..I have one more question...If I need to get the range of second same word in the textview then how would I go with that..because the above code is i use with textview range it gives me range of first coming word...Monseigneur
For the code you've shown, you supply the range of characters and it gives you a rectangle. If you want the rectangle for a different word, you need to supply a different range of characters which correspond to the word you want. You didn't show how you calculate the range for a desired word, so I can't suggest what to do differently.Homograph
Hi Ken I am using this NSRange myrange=[myTextview.text rangeofText:@"sabby"]; ,This is how I am using,But suppose sabby has 3 occurances,Then how to get the rect and range for the second or third sabby.Monseigneur
I assume you mean -[NSString rangeOfString:]. If so, then simply use one of the other -rangeOfString:... methods which take a range to search within, specifying the remainder of the string after the range you already found. Like myrange = [myTextview.text rangeOfString:@"sabby" options:0 range:NSMakeRange(myrange.location + myrange.length, myTextview.text.length - (myrange.location + myrange.length))];.Homograph
Thank ken even I was reading this thing,I just need to check how to provide this range location or how would this work....Thanks againMonseigneur
You have calculated this thing NSMakeRange(myrange.location + myrange.length, myTextview.text.length - (myrange.location + myrange.length)),which word would this specify,2nd or 3rd and how this calculates...thanksMonseigneur
It finds the next matching word. myrange is assumed to contain the range of the last matching word. Add its location and its length and you get the position immediately following that last match. The NSMakeRange(...) creates a range representing the part of myTextview.text which follows the last match. Then, -rangeOfString:options:range: is used to search only within that range for the next match.Homograph
Thanks Ken,I will practice on this.. lets see how much I dive and get the perfection...Monseigneur
Oh But it is showing me exception...Range or index out of bounds...I think need to calculate it properly...Index is out of bounds..ThanksMonseigneur
Add your code to the question, or maybe start a new question.Homograph
Is there a reason the UITextInput protocol requires so many methods? Do I have to implement them all (or can I delegate some away)?Shortage
R
2
-(void)textViewDidChangeSelection:(UITextView *)textView
 {
  NSRange range = textView.selectedRange;
 if(range.location<textView.text.length)
  {
    NSString * firstHalfString = [txtView.text substringToIndex:range.location];

    NSString *temp = @"s";
    CGSize s1 = [temp sizeWithFont:[UIFont systemFontOfSize:15] 
                          constrainedToSize:CGSizeMake(self.view.bounds.size.width - 40, MAXFLOAT)  // - 40 For cell padding
                              lineBreakMode:UILineBreakModeWordWrap]; // enter you textview font size

    CGSize s = [firstHalfString sizeWithFont:[UIFont systemFontOfSize:15] 
                           constrainedToSize:CGSizeMake(self.view.bounds.size.width - 40, MAXFLOAT)  // - 40 For cell padding
                               lineBreakMode:UILineBreakModeWordWrap]; // enter you textview font size


    //Here is the frame of your word in text view.
    NSLog(@"xcoordinate=%f, ycoordinate =%f, width=%f,height=%f",s.width,s.height,s1.width,s1.height);

     CGRect rectforword = CGRectMake(s.width, s.height, s1.width, s1.height);
    // rectforword is rect of yourword


    }
    else
    {
        // Do what ever you want to do

     }   
}

>>>Edited...

This method is call when you select or tap on the textview text but you can use this method in any of UITextView Delegate Method

Hope, this will help you...enjoy

Rosarosabel answered 25/4, 2012 at 10:53 Comment(6)
Thanks for this...But I have one problem,I have checked this solution before and your method would be called when i touch textview,But I need to place the controls or buttons before,and on select i need to show the list of options..Then how to do that...You can see the image above as wellMonseigneur
you can do it easily using my code..anyway tonight i have some work so will workout it by tomorrow.Rosarosabel
Oh thanks Nit...I will wait for your help...Really appreciateMonseigneur
Hi Nit,are you free now,I am really in need of this solution.Please try to help me out..I am waiting thanksMonseigneur
I am free but your scenario need to workout. Right now i don't have so much time than after i will try and will tell you if will make it..Rosarosabel
You try continue. i can say in any case you need to use above code for such type of scenario.Rosarosabel
S
2

Following on from Ken Thomases' answer, from iOS 6 and onwards the UITextInput protocol includes the following method:

- (NSArray *)selectionRectsForRange:(UITextRange *)range

(See the reference doc).

The result is an array of UITextSelectionRects, which have a bunch of information about selection ranges in text... Depending on how you want to use the rects of text-chunks, the above method might be useful.

(UITextSelectionRect reference).

Note: from my usage with UITextView, the array of UITextSelectionRects returned contains, what might be interpreted as, two additional selection rects. These are the last two selection rects in the array and I assume they correspond to the start and end positions of the selection. These selection rects each have a width of 0 and the containsStart / containsEnd properties are set accordingly.

Siret answered 25/3, 2014 at 14:7 Comment(0)
R
0

In my case adding the "layoutIfNeeded" helped.

    textView.superview?.layoutIfNeeded()
    let beginning = textView.beginningOfDocument
    let start = textView.position(from: beginning, offset: range.location)
    let end = textView.position(from: start!, offset: range.length)
    let textRange = textView.textRange(from: start!, to: end!)
    let frame = textView.firstRect(for: textRange!)
Roundtheclock answered 10/8, 2021 at 8:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.