我试图模仿长按键盘,建议用 UIButton 控制一封信。我想要做的是长按 UIButton ,按住按钮3新按钮显示并选择这3个新按钮中的一个。就像键盘字母的建议一样。
我该怎么做?任何的想法? 谢谢
答案 0 :(得分:1)
UIControl
只有minimumPressDuration
UIButton
您可以按{{1}}属性
如果您想在{{1}}上执行此操作,则必须将此手势识别器添加到按钮并处理第一次呼叫(单击)。
答案 1 :(得分:1)
你有一套完整的UIControl事件(UIButton是它的子类)来处理你需要的所有触摸事件:
enum {
UIControlEventTouchDown = 1 << 0,
UIControlEventTouchDownRepeat = 1 << 1,
UIControlEventTouchDragInside = 1 << 2,
UIControlEventTouchDragOutside = 1 << 3,
UIControlEventTouchDragEnter = 1 << 4,
UIControlEventTouchDragExit = 1 << 5,
UIControlEventTouchUpInside = 1 << 6,
UIControlEventTouchUpOutside = 1 << 7,
UIControlEventTouchCancel = 1 << 8,
UIControlEventValueChanged = 1 << 12,
UIControlEventEditingDidBegin = 1 << 16,
UIControlEventEditingChanged = 1 << 17,
UIControlEventEditingDidEnd = 1 << 18,
UIControlEventEditingDidEndOnExit = 1 << 19,
UIControlEventAllTouchEvents = 0x00000FFF,
UIControlEventAllEditingEvents = 0x000F0000,
UIControlEventApplicationReserved = 0x0F000000,
UIControlEventSystemReserved = 0xF0000000,
UIControlEventAllEvents = 0xFFFFFFFF
};
UIControlEventTouchDown
将会触发UIControlEventTouchDownRepeat
将会触发(注意这个事件会多次触发,所以你应该只处理第一个) - 这里你应该显示popover UIControlEventTouchDragExit
将会触发 - 在这里你应该隐藏弹出窗口UIControlEventTouchDragEnter
将会触发 - 此处应显示弹出窗口UIControlEventTouchUpInside
,UIControlEventTouchUpOutside
和UIControlEventTouchCancel
将会触发 - 在这里你应该隐藏弹出窗口 <强>更新强>
你将有一些逻辑来实现处理弹出窗口内的手指(因为那时你将从按钮中拖出)。
答案 2 :(得分:1)
这已经很老了,但是由于我有同样的问题,我将提出解决方案。
我安排了键盘类并由UIView派生的类Keyboard创建 每个字母按钮都是从UIButton派生的LetterButton类。 键盘实现了一种协议,该协议可以处理按钮中的KeyPressed事件。
对于主键盘的每个按钮,都会应用UILongPressGestureRecognizer:
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,否则我们将不会再接收任何事件!
在按钮上进行长按时,会创建一个弹出视图,其中触摸按钮上方的一个或多个按钮。我们可以直接从触摸的按钮上滑动到这些按钮。
LetterButton类的实现:
class LetterButton : UIButton
{
var delegate : LetterButtonDelegate?
var isInside = false
这是从Keyboard类调用的:
func setIsInside(val: Bool)
{
if (val)
{
if (!isInside)
{
setBackgroundColor(UIColor.lightGray, for: .normal)
}
}
else
{
if (!isInside)
{
setBackgroundColor(UIColor.white, for: .normal)
}
}
isInside = val
}
实际上,我只需要这里的键盘类按钮即可
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类:
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)
}
这是实际处理按钮字母的地方
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类实现:
protocol LetterButtonDelegate
{
func onBegan(button: LetterButton, point: CGPoint)
func onMoved(point: CGPoint)
func onEnded(point: CGPoint)
}
Keyboard类中协议的实现如下:
最初触摸的按钮存储在此处
func onBegan(button: LetterButton, point: CGPoint)
{
buttonPressed = button
}
处理我们滑过的按钮的背景颜色更改
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
}