我创建了一个包含UILongPressGestureRecognizer的自定义Label类,我在TableViewController中的tableview单元格中调用它。长按手势识别器工作(属性sting中的两个可点击区域),但如果滚动手势在我的CustomLabel的UILongPressGestureRecognizer区域之一开始,则包含标签的tableView不再滚动(平移)。我已尝试"M24"
以及下面的各种回复,但无济于事。任何建议将不胜感激。我花了一个星期来解决这个问题。我的代码如下。
这是CustomLabel类:
cancelsTouchesInView = false
这是cellClass:
class CustomLabel: UILabel {
let layoutManager = NSLayoutManager()
let textContainer = NSTextContainer(size: CGSize.zero)
var textStorage = NSTextStorage() {
didSet {
textStorage.addLayoutManager(layoutManager)
}
}
var onCharacterTapped: ((_ label: UILabel, _ characterIndex: Int, _ state: Bool) -> Void)?
let tapGesture = UILongPressGestureRecognizer()
override var attributedText: NSAttributedString? {
didSet {
if let attributedText = attributedText {
if attributedText.string != textStorage.string {
textStorage = NSTextStorage(attributedString: attributedText)
DispatchQueue.main.async {
let characterDelay = TimeInterval(0.01 + Float(arc4random()) / Float(UInt32.max)) / 100
for (index, char) in attributedText.string.characters.enumerated() {
DispatchQueue.main.asyncAfter(deadline: .now() + characterDelay * Double(index)) {
print("character ch is: \(char) at index: \(index)")
super.attributedText = attributedText.attributedSubstring(from: NSRange(location: 0, length: index+1))
}
}
}
}
} else {
textStorage = NSTextStorage()
}
}
}
override var lineBreakMode: NSLineBreakMode {
didSet {
textContainer.lineBreakMode = lineBreakMode
}
}
override var numberOfLines: Int {
didSet {
textContainer.maximumNumberOfLines = numberOfLines
}
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setUp()
}
override init(frame: CGRect) {
super.init(frame: frame)
setUp()
}
func setUp() {
isUserInteractionEnabled = true
layoutManager.addTextContainer(textContainer)
textContainer.lineFragmentPadding = 0
textContainer.lineBreakMode = lineBreakMode
textContainer.maximumNumberOfLines = numberOfLines
tapGesture.addTarget(self, action: #selector(CustomLabel.labelTapped(_:)))
tapGesture.minimumPressDuration = 0
tapGesture.cancelsTouchesInView = false
//tapGesture.delegate = self.superview
addGestureRecognizer(tapGesture)
}
override func layoutSubviews() {
super.layoutSubviews()
textContainer.size = bounds.size
}
func labelTapped(_ gesture: UILongPressGestureRecognizer) {
let locationOfTouch = gesture.location(in: gesture.view)
let textBoundingBox = layoutManager.usedRect(for: textContainer)
let textContainerOffset = CGPoint(x: (bounds.width - textBoundingBox.width) / 2 - textBoundingBox.minX, y: (bounds.height - textBoundingBox.height) / 2 - textBoundingBox.minY)
let locationOfTouchInTextContainer = CGPoint(x: locationOfTouch.x - textContainerOffset.x, y: locationOfTouch.y - textContainerOffset.y)
let indexOfCharacter = layoutManager.characterIndex(for: locationOfTouchInTextContainer, in: textContainer, fractionOfDistanceBetweenInsertionPoints: nil)
if gesture.state == .began {
onCharacterTapped?(self, indexOfCharacter, true)
} else if gesture.state == .ended {
onCharacterTapped?(self, indexOfCharacter, false)
}
}
}
以下是从创建CustomCells的TableViewControllerClass中选择的内容:
class friendTextCell: UITableViewCell {
@IBOutlet weak var labelText: CustomLabel!
override func awakeFromNib() {
super.awakeFromNib()
self.layoutIfNeeded()
}
}
答案 0 :(得分:1)
替换
tapGesture.minimumPressDuration = 0
使用
tapGesture.minimumPressDuration = 0.5
识别开始得太快,没有得到表格接触
答案 1 :(得分:0)
如果滚动手势在其中一个UILongPressGestureRecognizer中开始,则包含标签的tableView不再滚动(平移)
当您将UILongPressGestureRecognizer的最小按下持续时间设置为0并且它开始抓取滚动视图的嵌入式手势识别器时,会出现此问题。你可以通过使用更大的延迟解决它,如果你需要使用延迟的长按手势识别器,它应该如何。
首先会响应您的表格视图的didSelectRow at
并在延迟您的选择器之后。
它对我有用,虽然我在声明识别器的选择器方法之前删除了tapGesture.cancelsTouchesInView = false
并添加了属性@objc
(如果你在swift 4中写,则需要)。
如果您想毫不拖延地使用UILongPressGestureRecognizer
,请使用UITapGestureRecognizer
。在这种情况下,表格视图将滚动,但如果您点击标签,则无法接收didSelectRow
方法。
表和集合视图手势委托被设置为基础滚动视图,因此您无法在UIGestureRecognizerDelegate
上使用UIViewController
方法来实现此目的。
如果你希望在识别器触发时在View Controller中收到某种回调,你可以通过实现委托方法来回调。
创建实现CustomLabel
函数的labelTapped
委托。在您的选择器中调用该委托函数。让您的单元格符合该委托,并在单元格中重复该单元格以将函数抛出到UIViewController
。您也可以使用闭包委托模式。
希望有所帮助。
<强>更新强>
因此,解决方案是让UILongPressGestureRecognizer
的{{1}}为0,并将代理分配给它的单元格(在我的情况下为superview)。
在单元格中,您需要覆盖此方法:
minimumPressDuration
顺便说一下,您不需要让您的单元格符合gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return gestureRecognizer == yourGesture || otherGestureRecognizer == yourGesture
}
的要求