长按后如何跟踪按钮选择? [英] How to track button selection after long press?
问题描述
我试图模仿键盘的长按提示 UIButton 控件的字母.我想要做的是长按 UIButton,在按住按钮 3 个新按钮后,选择这 3 个新按钮之一.就像键盘字母建议一样.
I am trying to imitate the long press of the keyboard suggesting a letter for UIButton control. What I am trying to do is long press on UIButton, after keep pressing on the button 3 new buttons shows and select one of these 3 new buttons. just like the Keyboard letter suggestion.
我该怎么做?任何的想法?谢谢
How can I do this? any idea? Thank you
推荐答案
这已经很老了,但因为我遇到了同样的问题,所以我将提出我的解决方案.
This is quite old, but as I had the same problem I will present my solution for it.
我的键盘是由派生自 UIView 的类键盘布局和创建的每个字母按钮都是类 LetterButton,派生自 UIButton.键盘实现了一个协议,用于处理来自按钮的 KeyPressed 事件.
I have my keyboard laid out and created by class Keyboard, derived from UIView Each of the letter buttons is of class LetterButton, derived from UIButton. Keyboard implements a protocol which handles KeyPressed events from the buttons.
对于主键盘的每个按钮应用一个 UILongPressGestureRecognizer:
For each button of the main keyboard a UILongPressGestureRecognizer is applied:
let longTouchRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(onButtonLongPressed))
longTouchRecognizer.cancelsTouchesInView = false
button.addGestureRecognizer(longTouchRecognizer)
button.delegate = self
与
@objc func onButtonLongPressed (_ sender: UIGestureRecognizer)
{
if (sender.state == .began)
{
guard let tag = sender.view?.tag else { return }
createPopupView(button: buttons[tag])
}
}
必须将cancelsTouchesInView 设置为false,否则我们将不会收到任何进一步的事件!
It is essential to set cancelsTouchesInView to false, else we wouldn't receive any further events !
在一个按钮上长按时,会在触摸的按钮上方创建一个或多个按钮的弹出视图.我们可以直接从触摸的按钮滑动到这些按钮.
On a longtouch on a button a popupview is created with one or more buttons above the button touched. We can swipe to these buttons directly from the button touched.
LetterButton 类的实现:
Implementation of LetterButton class:
class LetterButton : UIButton
{
var delegate : LetterButtonDelegate?
var isInside = false
这是从键盘类调用的:
func setIsInside(val: Bool)
{
if (val)
{
if (!isInside)
{
setBackgroundColor(UIColor.lightGray, for: .normal)
}
}
else
{
if (!isInside)
{
setBackgroundColor(UIColor.white, for: .normal)
}
}
isInside = val
}
实际上我只需要键盘类的按钮
Actually I only need the button here for the Keyboard class
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?)
{
if let touch = touches.first
{
let point = touch.location(in: self)
delegate?.onBegan(button: self, point: point)
}
super.touchesBegan(touches, with: event)
}
只要我们将触摸移到按钮外,移动信息就会被发送到Keyboard类:
As long as we move the touch outside of the button, the movement information will be sent to the Keyboard class:
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?)
{
if let touch = touches.first
{
let point = touch.location(in: self)
if !bounds.contains(point)
{
delegate?.onMoved(point: convert(point, to: superview))
return
}
}
super.touchesMoved(touches, with: event)
}
这是按钮的字母实际处理的地方
This is where the letter of the button is actually processed
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?)
{
if let touch = touches.first
{
let point = touch.location(in: self)
delegate?.onEnded(point: convert(point, to: superview))
}
super.touchesEnded(touches, with: event)
}
}
如我们所见,LetterButton 类建立了以下需要由 Keyboard 类实现的协议:
As we see, the LetterButton class establishes the following protocol which need to be implemented by the Keyboard class:
protocol LetterButtonDelegate
{
func onBegan(button: LetterButton, point: CGPoint)
func onMoved(point: CGPoint)
func onEnded(point: CGPoint)
}
Keyboard 类中协议的实现如下:
The implementation of the protocol within Keyboard class is as follows:
最初被触摸的按钮存储在这里
The button which got initially touched is stored here
func onBegan(button: LetterButton, point: CGPoint)
{
buttonPressed = button
}
处理我们滑动的按钮的背景颜色变化
Processes background color change for buttons we swipe over
func onMoved(point: CGPoint)
{
let _ = findPopupButton(point: point)
}
触摸结束的处理
func onEnded(point: CGPoint)
{
// Check if touch ended on a popup button
if let button = findPopupButton(point: point)
{
// yes, let the keyboard process the key
delegate?.KeyPressed(key: button.title(for: .normal)!)
button.setIsInside(val: false)
// remove popupbuttons
popupView?.removeFromSuperview()
popupView = nil
}
else
{
// remove popup buttons if touch ended anywhere else
if popupView != nil
{
popupView!.removeFromSuperview()
popupView = nil
}
// buttons is an array of all normal keyboard buttons
// we use it to check if the button, where the touch ended is the same where the touch began
for button in buttons
{
if (button.frame.contains(point))
{
if (button.button.tag == buttonPressed?.tag)
{
// Still on same button, process the key
delegate?.KeyPressed(key: button.button.title(for: .normal)!) break
}
}
}
}
}
// Let's see if we are moving within the bounds of a popup button
func findPopupButton (point: CGPoint) -> LetterButton?
{
var result : LetterButton? = nil
if (popupView != nil)
{
if (popupView!.frame.contains(point))
{
for sub in popupView!.subviews
{
if (sub.isKind(of: LetterButton.self))
{
let button = sub as! LetterButton
let frame = popupView!.convert(button.frame, to: self)
if (frame.contains(point))
{
button.setIsInside(val: true)
result = button
}
else
{
button.setIsInside(val: false)
}
}
}
}
}
return result
}
这篇关于长按后如何跟踪按钮选择?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!