user2893370
user2893370

Reputation: 711

Highlight Searching Text in iOS

I have a gridview containing the TextView. There is also a search bar. When I type anything to search the search text should be highlighted in the TextView same as in Xcode or browser.

How can I implement this functionality?

Upvotes: 3

Views: 4020

Answers (3)

Julfikar
Julfikar

Reputation: 1423

@nsz's answer is correct. But it may not be efficient. Because you can't assume that how the user is going to search text. Example: if original text is "iPhone has released new 8s" and the search text is "iphone 8", in this case @nsz's answer won't work. To work with this kind of situation you have to split the keywords and find the word distance since '8' and '8s' is not same. To find word distance, you can use Levenshtein's algorithm.Below is the implementation:

-(float)LevenshteinAlgo:(NSString *)mainString withString:(NSString *)wordToCompare
{
    [mainString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
    [wordToCompare stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];

mainString = [mainString lowercaseString];
wordToCompare = [wordToCompare lowercaseString];

NSInteger k, i, j, cost, * d, distance;

NSInteger n = [mainString length];
NSInteger m = [wordToCompare length];

if( n++ != 0 && m++ != 0 ) {

    d = malloc( sizeof(NSInteger) * m * n );


    for( k = 0; k < n; k++)
        d[k] = k;

    for( k = 0; k < m; k++)
        d[ k * n ] = k;


    for( i = 1; i < n; i++ )
        for( j = 1; j < m; j++ ) {


            if( [mainString characterAtIndex: i-1] ==
               [wordToCompare characterAtIndex: j-1] )
                cost = 0;
            else
                cost = 1;


            d[ j * n + i ] = [self CstyleMinimum: d [ (j - 1) * n + i ] + 1
                                           andOf: d[ j * n + i - 1 ] +  1
                                           andOf: d[ (j - 1) * n + i - 1 ] + cost ];


            if( i>1 && j>1 && [mainString characterAtIndex: i-1] ==
               [wordToCompare characterAtIndex: j-2] &&
               [mainString characterAtIndex: i-2] ==
               [wordToCompare characterAtIndex: j-1] )
            {
                d[ j * n + i] = [self CstyleMinimum: d[ j * n + i ]
                                              andOf: d[ (j - 2) * n + i - 2 ] + cost ];
            }
        }

    distance = d[ n * m - 1 ];

    free( d );

    return distance;
}
return 0.0;
}

-(NSInteger)CstyleMinimum:(NSInteger)a andOf:(NSInteger)b andOf:(NSInteger)c
{
    NSInteger min = a;
    if ( b < min )
        min = b;

if( c < min )
    min = c;

return min;
}

-(NSInteger)CstyleMinimum:(NSInteger)a andOf:(NSInteger)b
{
    NSInteger min=a;
    if (b < min)
        min=b;

    return min;
}

So the whole process will be like below :

-(NSString*)getSuggestedString:(NSString *)main key:(NSString *)keyword{
NSString *suggested = nil;
NSArray *split = [main componentsSeparatedByString:@" "];
for (NSString *str in split){
    float distance = floorf([self LevenshteinAlgo:str withString:keyword]);

    if(distance == 1 || distance == 2){
        suggested = str;
    }
}
return suggested;
}

-(void)setColorForText:(NSString*) textToFind withColor:(UIColor*) color
{
    NSRange range = [self.mutableString rangeOfString:textToFind options:NSCaseInsensitiveSearch];

    if (range.location == NSNotFound) {
        //TODO: apply algo
        NSString *suggested = [self getSuggestedString:self.mutableString key:textToFind];
        NSRange srange = [self.mutableString rangeOfString:suggested!=nil?suggested:textToFind options:NSCaseInsensitiveSearch];
        if(srange.location != NSNotFound){
            [self addAttribute:NSForegroundColorAttributeName value:color range:srange];
        }
    }else{
        [self addAttribute:NSForegroundColorAttributeName value:color range:range];
    }
}

Use this full code in a NSMutableAttributedString subclass. Paste the code below in your subclass.h file.

@interface NSMutableAttributedString (Color){

}
-(void)setColorForText:(NSString*) textToFind withColor:(UIColor*) color;
@end

Finally use this like below :

NSMutableAttributedString *bold = [[NSMutableAttributedString alloc]initWithString:fulltext];
[bold setColorForText:key withColor:[UIColor redColor]];

I have been using this in my app for quite long time. You can try

Upvotes: 1

nzs
nzs

Reputation: 3252

I've tested the following code, which highlights the specific string in a UITextView:

-(void) highlightText:(NSString *)srcTxt {
    int srcTxtLen = srcTxt.length;
    int idx = 0;
    while (idx<(self.txtView.text.length-srcTxtLen)) {
        NSRange srcRange = NSMakeRange(idx, srcTxtLen);
        if ([[self.txtView.text substringWithRange:srcRange] isEqualToString:srcTxt]) {
            NSMutableAttributedString *tmpAttrTxt = [[NSMutableAttributedString alloc] initWithAttributedString:self.txtView.attributedText];
            [tmpAttrTxt addAttribute:NSBackgroundColorAttributeName value:[UIColor yellowColor] range:srcRange];
            self.txtView.attributedText = tmpAttrTxt;
            idx += srcTxtLen;
        } else {
            idx++;
        }
    }
}

Hope it helps you. Of course it can be optimized and/or customized for your specific needs.

Upvotes: 9

Mehul Parmar
Mehul Parmar

Reputation: 3699

From what I understand from your question, you need the functionality to highlight the text (in the textview, which is in gridview) that matches the text you entered in the search bar. This being the case, you can try the following:

  1. implement the method - (BOOL)searchBar:(UISearchBar *)searchBar shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text for your search bar.

  2. Use attributed text for the text in the grid. (change to attributed text from plain text in xib)

  3. Each time your program enters into the method above, extract the text variable, and accordingly update all your textViews with appropriate attributed strings. For this, you could use something like:

    NSRange highLightAt = NSMakeRange(17,2);  //based on the text in search bar
    
    NSMutableAttributedString * string = [[NSMutableAttributedString alloc] initWithString:@"You searched for me !!!"];
    
    [string addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:highLightAt];
    
    self.textView.attributedText = string;
    

I hope you get the idea.

Upvotes: 0

Related Questions