gpt4 book ai didi

ios - Swift:在 UITableViewCell 的 UITextView 中插入复选框并使用 UITapGestureRecognizer 识别复选框上的点击

转载 作者:搜寻专家 更新时间:2023-10-31 22:54:27 26 4
gpt4 key购买 nike

简介

上下文:

我正在开发我的第一个应用程序,一种笔记应用程序。

基本框架很简单:我有一个 UITableView,里面有单元格,有一些设计元素,还有一个大的 UITextView,用户可以在里面写笔记。

问题:

  • 我想实现复选框功能,类似于 Apple 在其应用“Notes”中的功能。我希望它成为文本的“一部分”,因此可以通过点击键盘上的删除来删除它。

  • 我查看了 SO 上关于将字符插入 UITextView 的帖子,这很有效(请参阅下面的代码),但在涉及实际点击识别时,它们的目标不同。但我不知道如何检查点击是否在我的 NSAttributedString 上。

问题:

1。当用户点击它们时,如何换出组成复选框的字符? 2. 如何让 UITapGestureRecognizer 在我的 TextView 上正常工作? 另请参阅编辑

编辑:

旧编辑问题:(通过 silicon_valleys 回答解决)

  • 我的 UITapGestureRecognizer 没有按预期工作,它似乎没有响应点击。
  • 如何检查我的复选框是否被点击并用复选标记替换字符?
  • 如何仅在用户光标所在行的开头插入复选框?

较小的新问题:

  • 点击识别器现在可以正常工作了。但我找不到方法 1. 将 NSRange 转换为 UITextRange 以便我可以替换字符或 2. 使用 NSRange 在 TextView 中插入字符。

代码:

  • 复选框插入方法toolbarCheckbox(sender: UIBarButtonItem)

    //This method is in my ViewController and adds a checkbox
    @objc func toolbarCheckbox(sender: UIBarButtonItem) {

    let checkboxCharacter: Character = "\u{25EF}"
    let emptyCheckbox = " \(checkboxCharacter) "

    guard case let cell as EventsCell = tableView.cellForRow(at: sender.indexPathID!) else {return}

    var beginningOfLineForSelection = cell.eventText.selectedTextRange.flatMap {
    cell.eventText.selectionRects(for: $0).first as? UITextSelectionRect
    }?.rect.origin ?? .zero
    beginningOfLineForSelection.x = 0

    let layoutManager = cell.eventText.layoutManager
    let firstGlyphOnLine = layoutManager.glyphIndex(
    for: beginningOfLineForSelection,
    in: cell.eventText.textContainer,
    fractionOfDistanceThroughGlyph: nil)

    let newText = NSMutableAttributedString(attributedString: cell.eventText.attributedText)
    newText.insert(NSAttributedString(string: emptyCheckbox, attributes: [NSAttributedStringKey.font : UIFont(name: "Didot", size: 16)!]), at: firstGlyphOnLine)

    cell.eventText.attributedText = newText

    }
  • UITextView 创建(在我的单元格类中)

    let eventText : GrowingTextView = {
    let tv = GrowingTextView(frame: .zero)

    let uncheckedBox = NSMutableAttributedString(string: checkboxCharacter, attributes: [NSAttributedStringKey.font : UIFont(name: "Didot", size: 16)!])
    uncheckedBox.append(NSMutableAttributedString(string: checkedBoxCharacter, attributes: [NSAttributedStringKey.font : UIFont(name: "Didot", size: 16)!]))
    tv.attributedText = uncheckedBox

    tv.allowsEditingTextAttributes = true
    tv.isScrollEnabled = false
    tv.textContainerInset = UIEdgeInsetsMake(1, 1, 0, 1)
    tv.translatesAutoresizingMaskIntoConstraints = false
    tv.backgroundColor = .clear
    return tv
    }()
  • UITapGestureRecognizer Action :

        @objc func checkboxTapDone(sender: UITapGestureRecognizer) {

    guard let cell = tableView.cellForRow(at: sender.indexPathID!) as? EventsCell else { return }
    let layoutManager = cell.eventText.layoutManager

    var location = sender.location(in: cell.eventText)
    location.x -= cell.eventText.textContainerInset.left
    location.y -= cell.eventText.textContainerInset.top

    let textTapped = layoutManager.glyphIndex(for: location, in: cell.eventText.textContainer, fractionOfDistanceThroughGlyph: nil)
    let substring = (cell.eventText.attributedText.string as NSString).substring(with: NSMakeRange(textTapped, 1))

    if substring == uncheckedBox {

    }
    else if substring == checkedBox {

    }
    }

感谢阅读我的帖子。

最佳答案

不可能在 UITextView 的文本中间添加 UIButton 或其他 UIControl。不过,您可以做的是使用 UITextViewattributedString 属性来呈现复选框字符。您可以通过使用带有与复选框(选中和未选中)匹配的字符的自定义字体来执行此操作。您需要将 UITapGestureRecognizer 添加到 UITextView,然后转换触摸点以检测复选框是否被点击,并将复选框字符从选中的复选框更改为未选中反之亦然。您还需要记住,您必须在 UITapGestureRecognizer 上设置一个委托(delegate),以确保它允许同时触摸与移动光标的正常触摸,并且仅在它位于复选框符号。

您可以在键盘上方的工具栏中添加一个按钮,将复选框符号添加到文本中(参见此解决方案:How can I add a toolbar above the keyboard?)。

希望对您有所帮助。

回答您进一步的问题

  • 我的 UITapGestureRecognizer 没有按预期工作,它似乎没有响应点击。

    这是因为您尝试在所有 TextView 上使用单个手势识别器。您应该为每个 UITextView 创建一个新的 UITapGestureRecognizer。现在,当您将其添加到以后的 View 时,它将从以前的 View 中删除(因此它只会检测出列的最后一个单元格上的点击)。

  • 如何检查我的复选框是否被点击并用复选标记替换字符?

    checkboxTapDone(sender:) 中的代码应该处理这个问题。你大部分都在那里,但你创建的范围应该只有 1 个字符,而不是 9 个。然后你需要将 substring 值与选中和未选中字符的值进行比较。然后用相反的字符更新 eventText.attributedText

  • 如何只在用户光标所在行的开头插入复选框?

    以下代码片段可帮助您确定可以插入复选框字符的范围。

var beginningOfLineForSelection = textView.selectedTextRange.flatMap {    
textView.selectionRects(for: $0).first as? UITextSelectionRect
}?.rect.origin ?? .zero
beginningOfLineForSelection.x = 0

let layoutManager = textView.layoutManager
let firstGlyphOnLine = layoutManager.glyphIndex(
for: beginningOfLineForSelection,
in: textView.textContainer,
fractionOfDistanceThroughGlyph: nil
)

let insertCheckboxRange = NSMakeRange(firstGlyphOnLine, 0)

回答较小的新问题

  • 您没有看到 replaceCharacters(in:with:) 方法(将 NSRange 作为第一个参数)的原因是您使用了NSAttributedString(不可变)。您需要先创建 attributedText 属性的可变副本。然后您可以更改文本并在 UITextView 上重新设置它。有关示例,请参见下面的代码片段。
let newText = NSMutableAttributedString(attributedString: textView.attributedText)
newText.replaceCharacters(in: rangeOfCharactersToReplace, with: newCharacters)
textView.attributedText = newText

关于ios - Swift:在 UITableViewCell 的 UITextView 中插入复选框并使用 UITapGestureRecognizer 识别复选框上的点击,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51803423/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com