NSMutableAttributedString в UITextView не кликабельно

У меня есть UITextView, а для строки задан текст с атрибутами, в котором говорится «Подробнее». Я также добавил жест для UITextView. Жест работает, когда щелчок выполняется в любом другом месте, но не при нажатии на «Подробнее».

Мне нужен щелчок, чтобы ответить на щелчок «Подробнее».

Ниже показано, как я реализовал:

//link text
 NSDictionary *linkAttributes = @{ NSForegroundColorAttributeName : [UIColor colorWithRed:0.05 green:0.4 blue:0.65 alpha:1.0],
                                                  NSFontAttributeName : [UIFont fontWithName:@"Roboto-Regular" size:10.0],
                                                  NSUnderlineStyleAttributeName : @(NSUnderlineStyleSingle) };

[attributedString setAttributes:linkAttributes range:linkRange];

self.classDesc.userInteractionEnabled = YES;
[self.classDesc addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleExpand:)]];
self.classDesc.selectable = YES;
 // Assign attributedText to UILabel
 self.classDesc.attributedText = attributedString;

Ниже показан прослушиватель жестов:

- (void)handleExpand:(UITapGestureRecognizer *)tapGesture
{
    self.classDesc.text = selectedClasses.classDescription;
    [self textViewDidChange:self.classDesc];

       CGSize sizeThatFitsTextView = [self.classDesc sizeThatFits:CGSizeMake(self.classDesc.frame.size.width, MAXFLOAT)];
    self.descHeight.constant = sizeThatFitsTextView.height ;


}

Любая помощь приветствуется.


person TharakaNirmana    schedule 09.03.2016    source источник
comment
Он будет переопределен событием щелчка UITextView.   -  person techloverr    schedule 09.03.2016


Ответы (3)


Вы можете использовать UILabel для этого. Вот как это сделать,

Сначала создайте класс категории для UITapGestureRecognizer и добавьте метод ниже,

/**
 Returns YES if the tap gesture was within the specified range of the attributed text of the label.
 */
- (BOOL)didTapAttributedTextInLabel:(UILabel *)label inRange:(NSRange)targetRange {
    NSParameterAssert(label != nil);

    CGSize labelSize = label.bounds.size;
    // create instances of NSLayoutManager, NSTextContainer and NSTextStorage
    NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
    NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:CGSizeZero];
    NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:label.attributedText];

    // configure layoutManager and textStorage
    [layoutManager addTextContainer:textContainer];
    [textStorage addLayoutManager:layoutManager];

    // configure textContainer for the label
    textContainer.lineFragmentPadding = 0.0;
    textContainer.lineBreakMode = label.lineBreakMode;
    textContainer.maximumNumberOfLines = label.numberOfLines;
    textContainer.size = labelSize;

    // find the tapped character location and compare it to the specified range
    CGPoint locationOfTouchInLabel = [self locationInView:label];
    CGRect textBoundingBox = [layoutManager usedRectForTextContainer:textContainer];
    CGPoint textContainerOffset = CGPointMake((labelSize.width - textBoundingBox.size.width) * 0.5 - textBoundingBox.origin.x,
                                              (labelSize.height - textBoundingBox.size.height) * 0.5 - textBoundingBox.origin.y);
    CGPoint locationOfTouchInTextContainer = CGPointMake(locationOfTouchInLabel.x - textContainerOffset.x,
                                                         locationOfTouchInLabel.y - textContainerOffset.y);
    NSInteger indexOfCharacter = [layoutManager characterIndexForPoint:locationOfTouchInTextContainer
                                                       inTextContainer:textContainer
                              fractionOfDistanceBetweenInsertionPoints:nil];
    if (NSLocationInRange(indexOfCharacter, targetRange)) {
        return YES;
    } else {
        return NO;
    }
}

Реализация

//Global variables
NSString *longString = @"very very long string";
NSRange moreRange;
NSRange lessRange;

-(void)setReadLessDescriptionText{
    self.lblDescription.userInteractionEnabled = YES;
    [self.lblDescription addGestureRecognizer:
     [[UITapGestureRecognizer alloc] initWithTarget:self
                                             action:@selector(handleTapMore:)]];

    // create your attributed text and keep an variable of your "link" text range
    NSAttributedString *plainText;
    NSAttributedString *linkText;
    plainText = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"%@ ...", [longString substringWithRange:NSMakeRange(0, 200)]] attributes:nil];//here 200 is  your character limit, it can be any value depending your requirement
    linkText = [[NSMutableAttributedString alloc] initWithString:@"more"
                                                      attributes:@{
                                                                   NSForegroundColorAttributeName:[UIColor blueColor]
                                                                   }];
    NSMutableAttributedString *attrText = [[NSMutableAttributedString alloc] init];
    [attrText appendAttributedString:plainText];
    [attrText appendAttributedString:linkText];

    // Variable -- keep track of the target range so you can compare in the callback
        moreRange = NSMakeRange(plainText.length, linkText.length);

    self.lblDescription.attributedText = attrText;

}

-(void)setReadMoreDescriptionText{
    self.lblDescription.userInteractionEnabled = YES;
    [self.lblDescription addGestureRecognizer:
     [[UITapGestureRecognizer alloc] initWithTarget:self
                                             action:@selector(handleTapLess:)]];

    // create your attributed text and keep an variable of your "link" text range
    NSAttributedString *plainText;
    NSAttributedString *linkText;
    plainText = [[NSMutableAttributedString alloc] initWithString:longString attributes:nil];
    linkText = [[NSMutableAttributedString alloc] initWithString:@" less"
                                                      attributes:@{
                                                                   NSForegroundColorAttributeName:[UIColor blueColor]
                                                                   }];
    NSMutableAttributedString *attrText = [[NSMutableAttributedString alloc] init];
    [attrText appendAttributedString:plainText];
    [attrText appendAttributedString:linkText];

    // Variable -- keep track of the target range so you can compare in the callback
    lessRange = NSMakeRange(plainText.length, linkText.length);

    self.lblDescription.attributedText = attrText;
}

Методы жестов

- (void)handleTapMore:(UITapGestureRecognizer *)tapGesture {
    BOOL didTapLink = [tapGesture didTapAttributedTextInLabel:self.lblDescription
                                                      inRange:moreRange];

    if (didTapLink) {
        [self setReadMoreDescriptionText];
    }
}

- (void)handleTapLess:(UITapGestureRecognizer *)tapGesture {
    BOOL didTapLink = [tapGesture didTapAttributedTextInLabel:self.lblDescription
                                                      inRange:lessRange];

    if (didTapLink) {
        [self setReadLessDescriptionText];
    }
}
person Prasad De Zoysa    schedule 10.03.2016

попробуй это

Реализуйте протокол UITextFieldDelegate. В контроллере представления добавьте текст

@interface YourViewController () <UITextViewDelegate>
In viewDidLoad set yourself as a delegate:

yourUITextView.delegate = self;

// Реализуйте метод делегата ниже:

- (BOOL)textViewShouldBeginEditing:(UITextView *)textView
{ 
   return NO; 
}
person techloverr    schedule 09.03.2016

Ниже были прокомментированы две строки кода, а затем начал работать тач «Подробнее»:

self.classDesc.textContainer.lineFragmentPadding = 0;
self.classDesc.textContainerInset = UIEdgeInsetsZero;
person TharakaNirmana    schedule 10.03.2016