菜鸟教程小白 发表于 2022-12-11 19:46:22

ios - 如何通过点击 UITextView 中的特定字符来显示圆角灰色背景?


                                            <p><p>我正在尝试使用 UITextView 显示文本。我在显示长文本时添加了“查看更多”。我想在点击它时更改背景颜色。我设置了NSAttributedString的背景,但是不能很好的设置圆角和边距。</p>

<p>谢谢!</p>

<p><strong>我想做的事!</strong></p>

<p>点击添加到 UITextView 的字符时,灰色背景具有足够的边距和圆角。</p>

<p><strong>注意:</strong>已经可以点击一个字符。这个问题是关于敲击时的效果。</p>

<p> <img src="/image/7W0bd.png" alt="&#34;See More&#34; example"/> </p>

<p> <img src="/image/w3Raw.jpg" alt="&#34;Cross lines&#34; example"/> </p>

<p><strong>类似问题</strong></p>

<p> <a href="https://stackoverflow.com/questions/16362407/nsattributedstring-background-color-and-rounded-corners" rel="noreferrer noopener nofollow">NSAttributedString background color and rounded corners</a> </p>

<p> <a href="https://stackoverflow.com/questions/21857408/how-to-set-nsstrings-background-cornerradius-on-ios7" rel="noreferrer noopener nofollow">How to set NSString&#39;s background cornerRadius on iOS7</a> </p></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p>在 UITextView 的文本中添加圆角背景颜色。此<code>answer</code> 将为您的<code>Question</code> 提供一些想法。</p>

<p><strong>逻辑:</strong></p>

<p>在<code>UITextView</code>中,我添加了<code>UITapGestureRecognizer</code>,它通过<code>Character</code>检测用户的点击 Action <code>Character</code>。如果用户点击 <code>subString</code> 中的任意一个字符,将创建新的 <code>UIView</code> 并触发 Timer。当计时器结束时,创建的 UIView 将从 UITextView 中删除。 </p>

<p>在<code>myTextView.position</code>的帮助下,我们可以得到subString的<code>CGRect</code>。那是 <code>Created UIView</code> 的框架。 <code>subString</code>中每个单词的<code>Size (WIDTH)</code>,可以从<code>SizeAtrributes</code>中获取。</p>

<pre><code>@IBOutlet weak var challengeTextVw: UITextView!
let fullText = &#34;We Love Swift and Swift attributed text &#34;
var myString = NSMutableAttributedString ()
let subString = &#34; Swift attributed text &#34;
var subStringSizesArr = ()
var myRange = NSRange()
var myWholeRange = NSRange()
let fontSize : CGFloat = 25
var timerTxt = Timer()
let delay = 3.0


override func viewDidLoad() {
    super.viewDidLoad()

    myString = NSMutableAttributedString(string: fullText)
    myRange = (fullText as! NSString).range(of: subString)
    myWholeRange = (fullText as! NSString).range(of: fullText)
    let substringSeperatorArr = subString.components(separatedBy: &#34; &#34;)

    print(substringSeperatorArr)
    print(substringSeperatorArr.count)
    var strConcat = &#34; &#34;

    for str in 0..&lt;substringSeperatorArr.count
    {

      strConcat = strConcat + substringSeperatorArr + &#34; &#34;
      let textSize = (strConcat as! NSString).size(withAttributes: )
      print(&#34;strConcatstrConcat   &#34;, strConcat)

      if str != 0 &amp;&amp; str != (substringSeperatorArr.count - 2)
      {
             print(&#34;times&#34;)
            subStringSizesArr.append(textSize.width)
      }

    }
    let myCustomAttribute = as
    let fontAtrib =
    myString.addAttributes(myCustomAttribute, range: myRange)
    myString.addAttributes(fontAtrib, range: myWholeRange)

    challengeTextVw.attributedText = myString
    let tap = UITapGestureRecognizer(target: self, action: #selector(myMethodToHandleTap))
    tap.delegate = self

    challengeTextVw.addGestureRecognizer(tap)

    challengeTextVw.isEditable = false
    challengeTextVw.isSelectable = false
}


@objc func myMethodToHandleTap(_ sender: UITapGestureRecognizer) {

    let myTextView = sender.view as! UITextView
    let layoutManager = myTextView.layoutManager

    let numberOfGlyphs = layoutManager.numberOfGlyphs
    var numberOfLines = 0
    var index = 0
    var lineRange:NSRange = NSRange()

    while (index &lt; numberOfGlyphs) {

      layoutManager.lineFragmentRect(forGlyphAt: index, effectiveRange: &amp;lineRange)
      index = NSMaxRange(lineRange);
      numberOfLines = numberOfLines + 1

    }

    print(&#34;noLin&#34;, numberOfLines)

    // location of tap in myTextView coordinates and taking the inset into account
    var location = sender.location(in: myTextView)
    location.x -= myTextView.textContainerInset.left;
    location.y -= myTextView.textContainerInset.top;

    // character index at tap location
    let characterIndex = layoutManager.characterIndex(for: location, in: myTextView.textContainer, fractionOfDistanceBetweenInsertionPoints: nil)

    // if index is valid then do something.
    if characterIndex &lt; myTextView.textStorage.length
    {
      // print the character index
      print(&#34;character index: \(characterIndex)&#34;)

      // print the character at the index
      let myRangee = NSRange(location: characterIndex, length: 1)
      let substring = (myTextView.attributedText.string as NSString).substring(with: myRangee)
      print(&#34;character at index: \(substring)&#34;)

      // check if the tap location has a certain attribute
      let attributeName = NSAttributedStringKey.init(&#34;MyCustomAttributeName&#34;)

      let attributeValue = myTextView.attributedText.attribute(attributeName, at: characterIndex, effectiveRange: nil) as? String

      if let value = attributeValue
      {
            print(&#34;You tapped on \(attributeName) and the value is: \(value)&#34;)
            print(&#34;\n\n ererereerer&#34;)


            timerTxt = Timer.scheduledTimer(timeInterval: delay, target: self, selector: #selector(delayedAction), userInfo: nil, repeats: false)

            myTextView.layoutManager.ensureLayout(for: myTextView.textContainer)

            // text position of the range.location
            let start = myTextView.position(from: myTextView.beginningOfDocument, offset: myRange.location)!
            // text position of the end of the range
            let end = myTextView.position(from: start, offset: myRange.length)!

            // text range of the range
            let tRange = myTextView.textRange(from: start, to: end)

            // here it is!
            let rect = myTextView.firstRect(for: tRange!)   //firstRectForRange(tRange)
            var secondViewWidthIndex = Int()
            for count in 0..&lt;subStringSizesArr.count
            {
                if rect.width &gt; subStringSizesArr
                {
                  secondViewWidthIndex = count
                }
            }

            let backHideVw = UIView()
            backHideVw.frame.origin.x = rect.origin.x
            backHideVw.frame.origin.y = rect.origin.y + 1
            backHideVw.frame.size.height = rect.height
            backHideVw.frame.size.width = rect.width

            backHideVw.backgroundColor = UIColor.brown
            backHideVw.layer.cornerRadius = 2
            backHideVw.tag = 10
            myTextView.addSubview(backHideVw)
            myTextView.sendSubview(toBack: backHideVw)


            if numberOfLines &gt; 1
            {
                let secondView = UIView()
                secondView.frame.origin.x = 0
                secondView.frame.origin.y = backHideVw.frame.origin.y + backHideVw.frame.size.height
                secondView.frame.size.height = backHideVw.frame.size.height
                secondView.frame.size.width = (subStringSizesArr.last! - subStringSizesArr) + 2
                secondView.backgroundColor = UIColor.brown
                secondView.layer.cornerRadius = 2
                secondView.tag = 20
                backHideVw.frame.size.width = subStringSizesArr

                myTextView.addSubview(secondView)
                print(&#34;secondView.framesecondView.frame    &#34;, secondView.frame)

                myTextView.sendSubview(toBack: secondView)
            }

            print(&#34;rectrect    &#34;, rect)

      }

    }

}

@objc func delayedAction()
{

    for subVws in challengeTextVw.subviews
    {
      if (String(describing: subVws).range(of:&#34;UIView&#34;) != nil)
      {
            if (subVws as! UIView).tag == 10 || (subVws as! UIView).tag == 20
            {
                subVws.removeFromSuperview()
            }
      }
    }

}
</code></pre>

<p>通过增加<code>字体大小</code>尝试所有尝试。</p>

<p><strong>尝试 1</strong></p>

<p> <a href="/image/Rpb2w.png" rel="noreferrer noopener nofollow"><img src="/image/Rpb2w.png" alt="enter image description here"/></a> </p>

<p><strong>尝试 2</strong></p>

<p> <a href="/image/kovom.png" rel="noreferrer noopener nofollow"><img src="/image/kovom.png" alt="enter image description here"/></a> </p>

<p><strong>尝试 3</strong></p>

<p> <a href="/image/z5vLl.png" rel="noreferrer noopener nofollow"><img src="/image/z5vLl.png" alt="enter image description here"/></a> </p></p>
                                   
                                                <p style="font-size: 20px;">关于ios - 如何通过点击 UITextView 中的特定字符来显示圆角灰色背景?,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/48877118/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/48877118/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: ios - 如何通过点击 UITextView 中的特定字符来显示圆角灰色背景?