web-dev-qa-db-ja.com

UILabelの最後に「...続きを読む」を追加

UILabelがあり、場合によってはUILabel自体よりもテキストが長いため、テキストは"bla bla bla..."を追加したい...Read MoreUILabel。の最後のボタンテキスト。

私はいくつかの投稿を読みましたが、たとえば、UILabelに入力する文字数を計算しますが、使用しているフォントでは各文字の幅が異なります。

どうすればそれを行うことができますか?

前もって感謝します!

11
Yossi Tsafar

だから、これは私が続き...ボタンをUITextViewUITextFieldまたはUILabelに追加するためにしたことです:

- (void)addReadMoreStringToUILabel:(UILabel*)label
{
    NSString *readMoreText = @" ...Read More";
    NSInteger lengthForString = label.text.length;
    if (lengthForString >= 30)
    {
        NSInteger lengthForVisibleString = [self fitString:label.text intoLabel:label];
        NSMutableString *mutableString = [[NSMutableString alloc] initWithString:label.text];
        NSString *trimmedString = [mutableString stringByReplacingCharactersInRange:NSMakeRange(lengthForVisibleString, (label.text.length - lengthForVisibleString)) withString:@""];
        NSInteger readMoreLength = readMoreText.length;
        NSString *trimmedForReadMore = [trimmedString stringByReplacingCharactersInRange:NSMakeRange((trimmedString.length - readMoreLength), readMoreLength) withString:@""];
        NSMutableAttributedString *answerAttributed = [[NSMutableAttributedString alloc] initWithString:trimmedForReadMore attributes:@{
                                                                                                                                        NSFontAttributeName : label.font
                                                                                                                                        }];

        NSMutableAttributedString *readMoreAttributed = [[NSMutableAttributedString alloc] initWithString:readMoreText attributes:@{
                                                                                                                                        NSFontAttributeName : Font(TWRegular, 12.),
                                                                                                                                        NSForegroundColorAttributeName : White
                                                                                                                                        }];

        [answerAttributed appendAttributedString:readMoreAttributed];
        label.attributedText = answerAttributed;

        UITagTapGestureRecognizer *readMoreGesture = [[UITagTapGestureRecognizer alloc] initWithTarget:self action:@selector(readMoreDidClickedGesture:)];
        readMoreGesture.tag = 1;
        readMoreGesture.numberOfTapsRequired = 1;
        [label addGestureRecognizer:readMoreGesture];

        label.userInteractionEnabled = YES;
    }
    else {

        NSLog(@"No need for 'Read More'...");

    }
}

here にあるfitString:intoLabelメソッドの使用があります。

UITagTapGestureRecognizerに関しては、tagと呼ばれるUITapGestureRecognizerプロパティを持つ通常のNSIntegerサブクラスです。同じUIViewControllerに複数ある場合、どのRead More...がクリックされたかを特定したいので、そうしました。通常のUITapGestureRecognizerを使用できます。

楽しい!

10
Yossi Tsafar

Swift4(IOS 11.2)

Readmoreラベルの最後にアクションなし

extension UILabel {

    func addTrailing(with trailingText: String, moreText: String, moreTextFont: UIFont, moreTextColor: UIColor) {
        let readMoreText: String = trailingText + moreText

        let lengthForVisibleString: Int = self.visibleTextLength
        let mutableString: String = self.text!
        let trimmedString: String? = (mutableString as NSString).replacingCharacters(in: NSRange(location: lengthForVisibleString, length: ((self.text?.count)! - lengthForVisibleString)), with: "")
        let readMoreLength: Int = (readMoreText.count)
        let trimmedForReadMore: String = (trimmedString! as NSString).replacingCharacters(in: NSRange(location: ((trimmedString?.count ?? 0) - readMoreLength), length: readMoreLength), with: "") + trailingText
        let answerAttributed = NSMutableAttributedString(string: trimmedForReadMore, attributes: [NSAttributedStringKey.font: self.font])
        let readMoreAttributed = NSMutableAttributedString(string: moreText, attributes: [NSAttributedStringKey.font: moreTextFont, NSAttributedStringKey.foregroundColor: moreTextColor])
        answerAttributed.append(readMoreAttributed)
        self.attributedText = answerAttributed
    }

    var visibleTextLength: Int {
        let font: UIFont = self.font
        let mode: NSLineBreakMode = self.lineBreakMode
        let labelWidth: CGFloat = self.frame.size.width
        let labelHeight: CGFloat = self.frame.size.height
        let sizeConstraint = CGSize(width: labelWidth, height: CGFloat.greatestFiniteMagnitude)

        let attributes: [AnyHashable: Any] = [NSAttributedStringKey.font: font]
        let attributedText = NSAttributedString(string: self.text!, attributes: attributes as? [NSAttributedStringKey : Any])
        let boundingRect: CGRect = attributedText.boundingRect(with: sizeConstraint, options: .usesLineFragmentOrigin, context: nil)

        if boundingRect.size.height > labelHeight {
            var index: Int = 0
            var prev: Int = 0
            let characterSet = CharacterSet.whitespacesAndNewlines
            repeat {
                prev = index
                if mode == NSLineBreakMode.byCharWrapping {
                    index += 1
                } else {
                    index = (self.text! as NSString).rangeOfCharacter(from: characterSet, options: [], range: NSRange(location: index + 1, length: self.text!.count - index - 1)).location
                }
            } while index != NSNotFound && index < self.text!.count && (self.text! as NSString).substring(to: index).boundingRect(with: sizeConstraint, options: .usesLineFragmentOrigin, attributes: attributes as? [NSAttributedStringKey : Any], context: nil).size.height <= labelHeight
            return prev
        }
        return self.text!.count
    }
}

Swift 4.2

extension UILabel {

        func addTrailing(with trailingText: String, moreText: String, moreTextFont: UIFont, moreTextColor: UIColor) {
            let readMoreText: String = trailingText + moreText

            let lengthForVisibleString: Int = self.vissibleTextLength
            let mutableString: String = self.text!
            let trimmedString: String? = (mutableString as NSString).replacingCharacters(in: NSRange(location: lengthForVisibleString, length: ((self.text?.count)! - lengthForVisibleString)), with: "")
            let readMoreLength: Int = (readMoreText.count)
            let trimmedForReadMore: String = (trimmedString! as NSString).replacingCharacters(in: NSRange(location: ((trimmedString?.count ?? 0) - readMoreLength), length: readMoreLength), with: "") + trailingText
            let answerAttributed = NSMutableAttributedString(string: trimmedForReadMore, attributes: [NSAttributedString.Key.font: self.font])
            let readMoreAttributed = NSMutableAttributedString(string: moreText, attributes: [NSAttributedString.Key.font: moreTextFont, NSAttributedString.Key.foregroundColor: moreTextColor])
            answerAttributed.append(readMoreAttributed)
            self.attributedText = answerAttributed
        }

        var vissibleTextLength: Int {
            let font: UIFont = self.font
            let mode: NSLineBreakMode = self.lineBreakMode
            let labelWidth: CGFloat = self.frame.size.width
            let labelHeight: CGFloat = self.frame.size.height
            let sizeConstraint = CGSize(width: labelWidth, height: CGFloat.greatestFiniteMagnitude)

            let attributes: [AnyHashable: Any] = [NSAttributedString.Key.font: font]
            let attributedText = NSAttributedString(string: self.text!, attributes: attributes as? [NSAttributedString.Key : Any])
            let boundingRect: CGRect = attributedText.boundingRect(with: sizeConstraint, options: .usesLineFragmentOrigin, context: nil)

            if boundingRect.size.height > labelHeight {
                var index: Int = 0
                var prev: Int = 0
                let characterSet = CharacterSet.whitespacesAndNewlines
                repeat {
                    prev = index
                    if mode == NSLineBreakMode.byCharWrapping {
                        index += 1
                    } else {
                        index = (self.text! as NSString).rangeOfCharacter(from: characterSet, options: [], range: NSRange(location: index + 1, length: self.text!.count - index - 1)).location
                    }
                } while index != NSNotFound && index < self.text!.count && (self.text! as NSString).substring(to: index).boundingRect(with: sizeConstraint, options: .usesLineFragmentOrigin, attributes: attributes as? [NSAttributedString.Key : Any], context: nil).size.height <= labelHeight
                return prev
            }
            return self.text!.count
        }
    }

使用法

let readmoreFont = UIFont(name: "Helvetica-Oblique", size: 11.0)
let readmoreFontColor = UIColor.blue
DispatchQueue.main.async {
    self.yourLabel.addTrailing(with: "... ", moreText: "Readmore", moreTextFont: readmoreFont!, moreTextColor: readmoreFontColor)
}

結果

Readmore label output

注:-Readmoreのアクションは含まれていません

20
ramchandra n

Tttattributedラベルにはこの機能があります

https://github.com/TTTAttributedLabel/TTTAttributedLabel

「truncation」トークンを「read more ...」として設定する必要があります

見る

attributedTruncationToken

var subTitleLabel = TTTAttributedLabel(frame : frame)
    self.addSubview(subTitleLabel)
    var trunc = NSMutableAttributedString(string: "...more")
    trunc.addAttribute(NSFontAttributeName, value: UIFont.systemFontOfSize(12), range: NSMakeRange(0, 7))
    trunc.addAttribute(NSForegroundColorAttributeName, value: UIColor.blueColor(), range: NSMakeRange(0, 7))
    subTitleLabel.attributedTruncationToken = trunc
    subTitleLabel.numberOfLines = 1
    subTitleLabel.autoresizingMask = UIViewAutoresizing.FlexibleHeight | UIViewAutoresizing.FlexibleWidth
7
Avner Barr

これは、Swift 4.2

ユーザーが入力する文字数がわからないため、@ ramchandranの回答のより安全なバージョンを次に示します。

彼の答えでは、ユーザーが入力した文字列の長さが、... Readmoreに使用することに決めたテキストの長さより短い場合、クラッシュします。たとえば、これはあなたがそれを使用する方法です

if yourLabel.text!.count > 1 {

   let readmoreFont = UIFont(name: "Helvetica-Oblique", size: 11.0)
    let readmoreFontColor = UIColor.blue
    DispatchQueue.main.async {
        self.yourLabel.addTrailing(with: "... ", moreText: "Readmore", moreTextFont: readmoreFont!, moreTextColor: readmoreFontColor)
    }
}

上記の例では、... Readmoreの出力は合計12文字です。ユーザーが入力した文字列がyourLabel.text = "12345678"の場合、文字列のテキストは8文字のみになります。以下の行で((trimmedString?.count ?? 0) - readMoreLength)を使用した範囲は否定的な結果を生成するため、クラッシュします。

// “12345678” minus “... Readmore” = negative four (8 - 12 = -4)
let trimmedForReadMore: String = (trimmedString! as NSString).replacingCharacters(in: NSRange(location: ((trimmedString?.count ?? 0) - readMoreLength), length: readMoreLength), with: "") + trailingText

入力した文字列が... Readmoreとして使用することを決定した文字数以下である場合、それが返され、クラッシュの原因となる行に到達しないことを確認する安全チェックを追加しました:

// trimmedString is the string the user entered
guard let safeTrimmedString = trimmedString else { return }
if safeTrimmedString.count <= readMoreLength { return }

addTrailing関数の中央にあります

extension UILabel{    

    func addTrailing(with trailingText: String, moreText: String, moreTextFont: UIFont, moreTextColor: UIColor) {

        let readMoreText: String = trailingText + moreText

        if self.visibleTextLength == 0 { return }

        let lengthForVisibleString: Int = self.visibleTextLength

        if let myText = self.text {

            let mutableString: String = myText

            let trimmedString: String? = (mutableString as NSString).replacingCharacters(in: NSRange(location: lengthForVisibleString, length: myText.count - lengthForVisibleString), with: "")

            let readMoreLength: Int = (readMoreText.count)

            guard let safeTrimmedString = trimmedString else { return }

            if safeTrimmedString.count <= readMoreLength { return }

            print("this number \(safeTrimmedString.count) should never be less\n")
            print("then this number \(readMoreLength)")

            // "safeTrimmedString.count - readMoreLength" should never be less then the readMoreLength because it'll be a negative value and will crash
            let trimmedForReadMore: String = (safeTrimmedString as NSString).replacingCharacters(in: NSRange(location: safeTrimmedString.count - readMoreLength, length: readMoreLength), with: "") + trailingText

            let answerAttributed = NSMutableAttributedString(string: trimmedForReadMore, attributes: [NSAttributedString.Key.font: self.font])
            let readMoreAttributed = NSMutableAttributedString(string: moreText, attributes: [NSAttributedString.Key.font: moreTextFont, NSAttributedString.Key.foregroundColor: moreTextColor])
            answerAttributed.append(readMoreAttributed)
            self.attributedText = answerAttributed
        }
    }

    var visibleTextLength: Int {

        let font: UIFont = self.font
        let mode: NSLineBreakMode = self.lineBreakMode
        let labelWidth: CGFloat = self.frame.size.width
        let labelHeight: CGFloat = self.frame.size.height
        let sizeConstraint = CGSize(width: labelWidth, height: CGFloat.greatestFiniteMagnitude)

        if let myText = self.text {

            let attributes: [AnyHashable: Any] = [NSAttributedString.Key.font: font]
            let attributedText = NSAttributedString(string: myText, attributes: attributes as? [NSAttributedString.Key : Any])
            let boundingRect: CGRect = attributedText.boundingRect(with: sizeConstraint, options: .usesLineFragmentOrigin, context: nil)

            if boundingRect.size.height > labelHeight {
                var index: Int = 0
                var prev: Int = 0
                let characterSet = CharacterSet.whitespacesAndNewlines
                repeat {
                    prev = index
                    if mode == NSLineBreakMode.byCharWrapping {
                        index += 1
                    } else {
                        index = (myText as NSString).rangeOfCharacter(from: characterSet, options: [], range: NSRange(location: index + 1, length: myText.count - index - 1)).location
                    }
                } while index != NSNotFound && index < myText.count && (myText as NSString).substring(to: index).boundingRect(with: sizeConstraint, options: .usesLineFragmentOrigin, attributes: attributes as? [NSAttributedString.Key : Any], context: nil).size.height <= labelHeight
                return prev
            }
        }

        if self.text == nil {
            return 0
        } else {
            return self.text!.count
        }
    }
}
3
Lance Samaria

私の解決策は、右下とUIButtonの下にUILabel(名前はもっと読む)を作成することです。その後、UILabelが切り捨てられているか、UIButtonを表示または非表示にしないかを確認します。

CGSize sizeOfText = [self.label.text boundingRectWithSize: CGSizeMake(self.label.intrinsicContentSize.width, CGFLOAT_MAX)
                                                 options: (NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)
                                              attributes: [NSDictionary dictionaryWithObject:self.label.font forKey:NSFontAttributeName] context: nil].size;

if (self.label.intrinsicContentSize.height < ceilf(sizeOfText.height)) {
    // label is truncated
    self.readmoreButton.hidden = NO; // show Read more button
}else{
    self.readmoreButton.hidden = YES;
}

=== Swift 3バージョン

let textheight = self.label.text?.height(withConstrainedWidth: self.label.frame.width, font: self.label.font)
    if self.label.intrinsicContentSize.height < textheight! {
        self.readmoreButton.isHidden = false
    }else{
        self.readmoreButton.isHidden = true
    }

この拡張機能を追加します。

extension String {

func height(withConstrainedWidth width: CGFloat, font: UIFont) -> CGFloat {
    let constraintRect = CGSize(width: width, height: .greatestFiniteMagnitude)
    let boundingBox = self.boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil)

    return boundingBox.height
}

}

この助けを願っています

2
Phan Van Linh

3番目のライブラリを試すことができます ExpandableLable

UILabelのカスタムクラスをExpandableLabelに設定し、目的の行数と折りたたみテキストを設定します。

expandableLabel.numberOfLines = 5
expandableLabel.collapsedAttributedLink = NSAttributedString(string: "more")
expandableLabel.Ellipsis = NSAttributedString(string: "...")
// update label expand or collapse state
expandableLabel.collapsed = true

リンクがタッチされた場合に通知を受けるには、delegateを設定する必要があります。

2
Phillip

Swift 4およびSwift 5。同じものを実装する必要があります。答えはすでに与えられていますが、私によるとTTTAttributedLabelコンテンツをより適切に制御できますアドレス、リンク、日付などを簡単に見つけることができますリンクの色を変更することもできますTTTAttributedLabelライブラリリンクは上記の回答で既に提供されています。

let kCharacterBeforReadMore =  20
let kReadMoreText           =  "...ReadMore"
let kReadLessText           =  "...ReadLess"

@IBOutlet weak var labelText: TTTAttributedLabel! // setYouLabel Class to TTTAttributedLabel in StoryBoard
var strFull = ""

 override func viewDidLoad() {
      super.viewDidLoad()
      strFull = "I need to implement the same. As answers are already given but according to me TTTAttributedLabel is the best way to do it. I gives I need to implement the same. As answers are already given but according to me TTTAttributedLabel is the best way to do it. I gives you"
      labelText.showTextOnTTTAttributeLable(str: strFull, readMoreText: kReadMoreText, readLessText: kReadLessText, font: UIFont.init(name: "Helvetica-Bold", size: 24.0)!, charatersBeforeReadMore: kCharacterBeforReadMore, activeLinkColor: UIColor.blue, isReadMoreTapped: false, isReadLessTapped: false)
      labelText.delegate = self
   }
      func readMore(readMore: Bool) {
        labelText.showTextOnTTTAttributeLable(str: strFull, readMoreText: kReadMoreText, readLessText: kReadLessText, font: nil, charatersBeforeReadMore: kCharacterBeforReadMore, activeLinkColor: UIColor.blue, isReadMoreTapped: readMore, isReadLessTapped: false)
      }
      func readLess(readLess: Bool) {
        labelText.showTextOnTTTAttributeLable(str: strFull, readMoreText: kReadMoreText, readLessText: kReadLessText, font: nil, charatersBeforeReadMore: kCharacterBeforReadMore, activeLinkColor: UIColor.blue, isReadMoreTapped: readLess, isReadLessTapped: true)
      }
}

ここでは、TTTAttributedLabelの拡張機能を作成し、ReadMoreおよびReadLessロジックをここに配置しました。に応じて変更できます。

 extension TTTAttributedLabel {
      func showTextOnTTTAttributeLable(str: String, readMoreText: String, readLessText: String, font: UIFont?, charatersBeforeReadMore: Int, activeLinkColor: UIColor, isReadMoreTapped: Bool, isReadLessTapped: Bool) {

        let text = str + readLessText
        let attributedFullText = NSMutableAttributedString.init(string: text)
        let rangeLess = NSString(string: text).range(of: readLessText, options: String.CompareOptions.caseInsensitive)
//Swift 5
       // attributedFullText.addAttributes([NSAttributedStringKey.foregroundColor : UIColor.blue], range: rangeLess)
        attributedFullText.addAttributes([NSAttributedString.Key.foregroundColor : UIColor.blue], range: rangeLess)

        var subStringWithReadMore = ""
        if text.count > charatersBeforeReadMore {
          let start = String.Index(encodedOffset: 0)
          let end = String.Index(encodedOffset: charatersBeforeReadMore)
          subStringWithReadMore = String(text[start..<end]) + readMoreText
        }

        let attributedLessText = NSMutableAttributedString.init(string: subStringWithReadMore)
        let nsRange = NSString(string: subStringWithReadMore).range(of: readMoreText, options: String.CompareOptions.caseInsensitive)
        //Swift 5
       // attributedLessText.addAttributes([NSAttributedStringKey.foregroundColor : UIColor.blue], range: nsRange)
        attributedLessText.addAttributes([NSAttributedString.Key.foregroundColor : UIColor.blue], range: nsRange)
      //  if let _ = font {// set font to attributes
      //   self.font = font
      //  }
        self.attributedText = attributedLessText
        self.activeLinkAttributes = [NSAttributedString.Key.foregroundColor : UIColor.blue]
        //Swift 5
       // self.linkAttributes = [NSAttributedStringKey.foregroundColor : UIColor.blue]
        self.linkAttributes = [NSAttributedString.Key.foregroundColor : UIColor.blue]
        self.addLink(toTransitInformation: ["ReadMore":"1"], with: nsRange)

        if isReadMoreTapped {
          self.numberOfLines = 0
          self.attributedText = attributedFullText
          self.addLink(toTransitInformation: ["ReadLess": "1"], with: rangeLess)
        }
        if isReadLessTapped {
          self.numberOfLines = 3
          self.attributedText = attributedLessText
        }
      }
    }

TTTAttributedLabelのdidSelectLinkWithTransitInformationデリゲートを実装する必要があります。ここで、渡したコンポーネントを取得できます

extension ViewController: TTTAttributedLabelDelegate {
  func attributedLabel(_ label: TTTAttributedLabel!, didSelectLinkWithTransitInformation components: [AnyHashable : Any]!) {
    if let _ = components as? [String: String] {
      if let value = components["ReadMore"] as? String, value == "1" {
        self.readMore(readMore: true)
      }
      if let value = components["ReadLess"] as? String, value == "1" {
        self.readLess(readLess: true)
      }
    }
  }
}

結果-ReadMoreをタップする前に

enter image description here

結果-ReadMoreをタップした後

enter image description here

1
Gurjinder Singh
class DynamicLabel: UILabel{

    var fullText: String?
    var truncatedLength = 100
    var isTruncated = true

    func collapse(){
        let index = fullText!.index(fullText!.startIndex, offsetBy: truncatedLength)
        self.text = fullText![...index].description + "... More"
        isTruncated = true
    }

    func expand(){
        self.text = fullText
        isTruncated = false
    }

}

これらすべての厄介な実装を通過するための簡単なトリックです。アイデアは単純です。行を折りたたんだり展開したりせず、ラベルを0に設定するだけです。その後、元のテキストをfullText変数に保存します。折りたたまれた形式を表示する場合は、部分文字列を取得してカスタムの省略記号を追加します。

注:これには、タップイベントハンドラは含まれません。コントローラに自分で追加できます。

0
Dang Duy Nam

メソッド -boundingRectWithSize:options:attributes:context: を使用し、フォントをNSFontAttributeNameNSAttributedStringキーとして渡すと、必要な正しいrectが得られます。

それから、ラベルの境界からオフセットを引いた値よりも大きいかどうかを確認する必要があります。はいの場合のみ、テキストをトリミングしてRead More 最後に。

0
hris.to

ラベルのアクションでは、CollectionViewまたはTableViewを使用している場合、デリゲートメソッドを使用してアクションを実行できます。

func showMore(cell: CustomCell) {
    guard let indexPath = self.tableView.indexPath(for: cell) else {
        return
    }
    let cell = tableView.cellForRow(at: indexPath) as! CustomCell
    tableView.beginUpdates()
    cell.label.text = "your complete text"
    tableView.endUpdates()
}

これにより、ラベルが更新され、必要に応じてフルテキストが表示されます。ランスサマリアの回答を使用して、セルのアクションを追加します。

0
Ctan Li

このメソッドは、上向き矢印画像を使用したshowlessおよびshowAllに役立ちます。ラベルにタップジェスチャを追加します

  viewcontroller.h

  @property (nonatomic,assign) BOOL isReadable; 

  viewcontrollr.m

  #pragma mark :- Tap Gesture View All
  -(void)readMoreDidClickedGesture :(UITapGestureRecognizer 
    *)objTapGesture{

     UILabel * lblDesc = (UILabel *)[objTapGesture view];
     NSLog(@"%@",lblDesc.text);
     if (self.isReadable == false) {
     [self setIsReadable:YES];
     lblDesc.text = readmoreText;
     readMoreHeight = [self getLabelHeight:lblDesc];
     }
     else{
      readMoreHeight = 30.0;
      [self setIsReadable:NO];
      }  
  }



 - (void)addReadMoreStringToUILabel:(UILabel*)label isReaded:(BOOL)isReaded
 {

  NSString *readMoreText = (isReaded == false) ? @"...Show All  " : 
   @"Show Less  ";
  NSInteger lengthForString = label.text.length;
  if (lengthForString >= 30)
  {
    NSInteger lengthForVisibleString = [self getLabelHeight:label];//[self fitString:label.text intoLabel:label];
    NSMutableString *mutableString = [[NSMutableString alloc] initWithString:label.text];
    readmoreText = mutableString;
    NSString *trimmedString = [mutableString stringByReplacingCharactersInRange:NSMakeRange(lengthForVisibleString, (label.text.length - lengthForVisibleString)) withString:@""];
    NSInteger readMoreLength = readMoreText.length;
    NSString *trimmedForReadMore = [trimmedString stringByReplacingCharactersInRange:NSMakeRange((trimmedString.length - readMoreLength), readMoreLength) withString:@""];
    NSMutableAttributedString *answerAttributed = [[NSMutableAttributedString alloc] initWithString:trimmedForReadMore attributes:@{
                                                                                                                                    NSFontAttributeName : label.font
                                                                                                                                    }];


    NSMutableAttributedString *readMoreAttributed = [[NSMutableAttributedString alloc] initWithString:readMoreText attributes:@{
                                                                                                                                NSFontAttributeName :label.font,                              NSForegroundColorAttributeName :[UIColor orangeColor]
                                                                                                                                }];
    if (isReaded == false){
        [readMoreAttributed addAttribute:NSUnderlineStyleAttributeName
                             value:@(NSUnderlineStyleSingle)
                             range:NSMakeRange(3, 8)];

        NSTextAttachment *textAttachment = [[NSTextAttachment alloc] init];
        UIImageView *imgDown = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 25, 25)];
        imgDown.image = [UIImage imageNamed:@"searchFilterArrow1"];
        imgDown.image = [imgDown.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
        [imgDown setTintColor:[UIColor orangeColor]];

        textAttachment.image = imgDown.image;

        NSAttributedString *attrStringWithImage = [NSAttributedString attributedStringWithAttachment:textAttachment];

        [readMoreAttributed replaceCharactersInRange:NSMakeRange(12, 1) withAttributedString:attrStringWithImage];
    }
    else{
        [readMoreAttributed addAttribute:NSUnderlineStyleAttributeName
                                   value:@(NSUnderlineStyleSingle)
                                   range:NSMakeRange(1, 9)];
        NSTextAttachment *textAttachment = [[NSTextAttachment alloc] init];
        UIImageView *imgup = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 25, 25)];
        imgup.image = [UIImage imageNamed:@"searchFilterArrow2"];
        imgup.image = [imgup.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
        [imgup setTintColor:[UIColor orangeColor]];

        textAttachment.image = imgup.image;

        NSAttributedString *attrStringWithImage = [NSAttributedString attributedStringWithAttachment:textAttachment];

        [readMoreAttributed replaceCharactersInRange:NSMakeRange(11, 1) withAttributedString:attrStringWithImage];
    }

    [answerAttributed appendAttributedString:readMoreAttributed];
    label.attributedText = answerAttributed;

    UITapGestureRecognizer *readMoreGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(readMoreDidClickedGesture:)];
    readMoreGesture.numberOfTapsRequired = 1;
    [label addGestureRecognizer:readMoreGesture];

    label.userInteractionEnabled = YES;
}
else {

    NSLog(@"No need for 'Read More'...");

}
}
0
Maulik Patel

UILabelのタッチアクションがないことを知っていますか。テキスト全体がUILabelの場合、[...続きを読む]をタップすることはできません。

注:私の解決策は、UILabelの背景ボタンを明確に追加することです。

0
Jamil

アクション用

 let tap = UITapGestureRecognizer(target: self, action: #selector(self.tapFunction))
 Urlabel.isUserInteractionEnabled = true
 Urlabel.addGestureRecognizer(tap)

 @objc
    func tapFunction(sender:UITapGestureRecognizer) {


    }
0
Red Heart
func updateData(_ label: UILabel) {
    self.headerLabel.text = detailViewModel.firstTitle
    self.detailLabel.text = detailViewModel.firstContent

    headerTitle = detailViewModel.firstTitle
    detailTitle = detailViewModel.firstContent

    DispatchQueue.main.async {
        let readMoreText = "...View More"
        let stringColor: UIColor = UIColor.blue
        let attributes = [NSForegroundColorAttributeName: stringColor]

        let numberOfLines = self.detailLabel.numberOfVisibleLines

        if numberOfLines > 2 {

            let lengthForVisibleString: Int = self.fit( self.detailLabel.text, into: self.detailLabel)
            let mutableString = self.detailLabel.text ?? ""
            let trimmedString = (mutableString as NSString).replacingCharacters(in: NSRange(location: lengthForVisibleString, length: (self.detailLabel?.text?.count ?? 0) - lengthForVisibleString), with: "")
            let readMoreLength: Int = readMoreText.count
            let trimmedForReadMore = (trimmedString as NSString).replacingCharacters(in: NSRange(location: trimmedString.count - readMoreLength, length: readMoreLength), with: "")
            let answerAttributed = NSMutableAttributedString(string: trimmedForReadMore, attributes: [NSFontAttributeName: self.detailLabel.font])

            let readMoreAttributed = NSMutableAttributedString(string: readMoreText, attributes: attributes)
            answerAttributed.append(readMoreAttributed)
            self.detailLabel.attributedText = answerAttributed


            let readMoreGesture = UITapGestureRecognizer(target: self, action:#selector(FundDetailsTableViewCell.showViewMore(_:)))
            readMoreGesture.numberOfTapsRequired = 1
            self.detailLabel.addGestureRecognizer(readMoreGesture)
            self.detailLabel.isUserInteractionEnabled = true
        }
    }
}

func fit(_ string: String?, into label: UILabel?) -> Int {
    guard let stringObjc = string as NSString? else {
        return 0
    }
    let font: UIFont = label?.font ?? UIFont.systemFont(ofSize: 14.0)
    let mode: NSLineBreakMode? = label?.lineBreakMode
    let labelWidth: CGFloat? = label?.frame.size.width
    let labelHeight: CGFloat? = label?.frame.size.height
    let sizeConstraint = CGSize(width: labelWidth ?? 0.0, height: CGFloat.greatestFiniteMagnitude)
    let attributes = [NSFontAttributeName: font]

    let device = UIDevice.current
    let iosVersion = Double(device.systemVersion) ?? 0

    if iosVersion > 7 {
        let attributedText = NSAttributedString(string: string ?? "", attributes: attributes)
        let boundingRect: CGRect = attributedText.boundingRect(with: sizeConstraint, options: .usesLineFragmentOrigin, context: nil)
        do {
            if boundingRect.size.height > (labelHeight ?? 0.0) {
                var index: Int = 0
                var prev: Int
                let characterSet = CharacterSet.whitespacesAndNewlines
                repeat {
                    prev = index
                    if mode == .byCharWrapping {
                        index += 1
                    } else {
                        index = Int((string as NSString?)?.rangeOfCharacter(from: characterSet, options: [], range: NSRange(location: index + 1, length: (string?.count ?? 0) - index - 1)).location ?? 0)
                    }
                } while index != NSNotFound && index < (string?.count ?? 0)
                    && (stringObjc.substring(to: index).boundingRect(with: sizeConstraint, options: .usesLineFragmentOrigin, attributes: attributes, context: nil).size.height) <= labelHeight!
                return prev;
            }
        }
    } else {
        if stringObjc.size(attributes: attributes).height > labelHeight! {
            var index: Int = 0
            var prev: Int
            let characterSet = CharacterSet.whitespacesAndNewlines
            repeat {
                prev = index
                if mode == .byCharWrapping {
                    index += 1
                } else {
                    index = stringObjc.rangeOfCharacter(from: characterSet, options: NSString.CompareOptions.caseInsensitive, range: NSRange(location: index + 1, length: stringObjc.length - index - 1)).location
                }

            } while index != NSNotFound && index < (string?.count)! && (stringObjc.substring(to: index) as NSString).size(attributes: attributes).height <= labelHeight!
            return prev

        }
    }
    return (string?.count)!
}

func showViewMore(_ sender: UITapGestureRecognizer) {

}

extension UILabel {
    var numberOfVisibleLines: Int {
        let textSize = CGSize(width: CGFloat(self.frame.size.width), height: CGFloat(MAXFLOAT))
        let rHeight: Int = lroundf(Float(self.sizeThatFits(textSize).height))
        let charSize: Int = lroundf(Float(self.font.pointSize))
        return rHeight / charSize
    }
}
0
Ashok Mango