自定义按钮视图:检测触摸向下/向上,快速,并回退拖动到 UIScrollView
Posted
技术标签:
【中文标题】自定义按钮视图:检测触摸向下/向上,快速,并回退拖动到 UIScrollView【英文标题】:Custom button view: detect touch down/up, quickly, and fall back dragging to UIScrollView 【发布时间】:2016-11-21 17:46:46 【问题描述】:对不起,如果这已经被问到/回答了。
我正在尝试创建一个自定义按钮 (UIView) 来检测触摸向下和向上(以自定义背景颜色、文本颜色等的变化)。
我试过touchesBegan
,但反应太慢了。
我已经尝试过UILongPressGestureRecognizer
,但它并没有退回到将UIScrollView
拖到下面。我的意思是:拖动按钮时不会拖动滚动视图。
到目前为止,这是我的解决方案,使用 UILongPressGestureRecognizer
,想法来自 here。
请问,您能想出比我更好的解决方案吗?谢谢!
/** View that can be pressed like a button */
import UIKit
class ButtonView : UIView, UIGestureRecognizerDelegate
static let NoChange = (btn:ButtonView) in
var enabled = true
/* Called when the view goes to normal state (set desired appearance) */
var onNormal = NoChange
/* Called when the view goes to pressed state (set desired appearance) */
var onPressed = NoChange
/* Called when the view is released (perform desired action) */
var action =
override init(frame: CGRect)
super.init(frame: frame)
let recognizer = UILongPressGestureRecognizer(target: self, action: #selector(touched))
recognizer.delegate = self
recognizer.minimumPressDuration = 0.0
addGestureRecognizer(recognizer)
userInteractionEnabled = true
override func layoutSubviews()
super.layoutSubviews()
onNormal(self)
func touched(sender: UILongPressGestureRecognizer)
guard enabled else return
print("Current state: \(sender.state.rawValue)")
if sender.state == .Began
onPressed(self)
else if sender.state == .Ended
onNormal(self)
action()
else if sender.state == .Changed
onNormal(self)
// This cancels recognizer when dragging
// TODO: but doesn't drag scroll view
sender.enabled = false
sender.enabled = true
required init?(coder aDecoder: NSCoder)
fatalError("init(coder:) has not been implemented")
用法:
let button = ButtonView()
// add some views to the ButtonView, e.g. add a label
button.onNormal = $0.backgroundColor = normalColor
button.onPressed = $0.backgroundColor = pressedColor
button.action = doSomethingWhenButtonIsClicked()
【问题讨论】:
GestureRecognizers 可能(根据定义?)需要更长的时间来了解用户在做什么。如果 touchesBegan() 花费的时间太长,您能否以某种方式重新(定义)UI 以消除您正在尝试做的一些事情?换句话说,“你能给我一个你想要的工作示例吗”?你可能想做一些不可能的事情。 谢谢,基本上我有一个“垂直”UIScrollView
,最重要的是我有几个视图,包括我的ButtonView
。我有其他使用UITapGestureRecognizer
的视图并且它们工作正常(我可以点击打开某些东西,但我也可以在顶部拖动以滚动 UIScrollView)。这些视图实际上位于另一个嵌套的“水平”UIScrollView 中,因此我可以拖动两个方向来滚动主垂直滚动视图或嵌套的水平滚动视图。我会调查是否可以使用UITapGestureRecognizer
解决我的问题。
【参考方案1】:
UIControl
的另一个解决方案。反应比较慢但是还不错,可以在下面拖一个UIScrollView
。
/**
* View that can be pressed like a button.
*
* Note that, since UIView has userInteractionEnabled = true by default,
* you should disable it for UIView layers that you put insde this ButtonView.
* Otherwise the ButtonView will not receive the touch events.
*/
// See: http://***.com/q/40726283/custom-button-view
import UIKit
class ButtonView : UIControl
static let NoChange = (btn:ButtonView) in
/* Called when the view goes to normal state (set desired appearance) */
var onNormal = NoChange
/* Called when the view goes to pressed state (set desired appearance) */
var onPressed = NoChange
/* Called when the view goes to disabled state, i.e. enabled = false (set desired appearance) */
var onDisabled = NoChange
/* Called when the view is released (perform desired action) */
var action =
override init(frame: CGRect)
super.init(frame: frame)
self.addTarget(self, action: #selector(pressed), forControlEvents: .TouchDown)
self.addTarget(self, action: #selector(clicked), forControlEvents: .TouchUpInside)
self.addTarget(self, action: #selector(cancelled), forControlEvents: [.TouchCancel, .TouchDragExit, .TouchUpOutside])
userInteractionEnabled = true // this is the default!
override func layoutSubviews()
super.layoutSubviews()
updateBaseStyle()
func pressed()
onPressed(self)
func clicked()
onNormal(self)
action()
func cancelled()
onNormal(self)
override var enabled: Bool
willSet(e)
super.enabled = e
updateBaseStyle()
func updateBaseStyle()
if self.enabled
onNormal(self)
else
onDisabled(self)
required init?(coder aDecoder: NSCoder)
fatalError("init(coder:) has not been implemented")
用法类似(我只是加了onDisable):
let button = ButtonView()
// add some views to the ButtonView, e.g. add a label
// note child views should have userInteractionEnabled = false
button.onNormal = $0.backgroundColor = normalColor
button.onPressed = $0.backgroundColor = pressedColor
button.onDisabled = $0.backgroundColor = disabledColor
button.action = callToAction()
【讨论】:
以上是关于自定义按钮视图:检测触摸向下/向上,快速,并回退拖动到 UIScrollView的主要内容,如果未能解决你的问题,请参考以下文章
在 UIScrollView 中检测“向上”UIGesture
如何在快速向上和向下滚动表格时停止自动重新加载表格视图? [关闭]