之前有类似的问题,我已经提到使用hitTest:withEvent:在其超视图框架之外的子视图上捕获触摸,并将触摸事件传递到其父视图边界之外的视图.但他们似乎没有回答我的特殊问题.
我有一个具有以下结构的自定义控件:
+-------------------------------+
| UIButton |
+-------------------------------+
| |
| |
| UITableView |
| |
| |
+------------------------- +
Run Code Online (Sandbox Code Playgroud)
自定义控件会覆盖UIButton子类并将UITableView其添加为其子视图.这个想法是让整个控件像下拉列表一样.当UIButton按下时,UITableView将下拉列表和使选择的选择.
如果控件是最顶层的直接子项,这一切都适用hitTest于UIButton上面Apple的Q&A链接中所描述的被覆盖的内容UIView.但是,如果控件位于另一个视图层次结构中,UITableView则不会接收触摸事件.
以下是使用的hitTest代码:
override func hitTest(point: CGPoint, withEvent event: UIEvent?) -> UIView? {
// Convert the point to the target view's coordinate system.
// The target view isn't necessarily the immediate subview
let pointForTargetView = self.spinnerTableView.convertPoint(point, fromView:self)
if (CGRectContainsPoint(self.spinnerTableView.bounds, pointForTargetView)) {
// The target view may have its view hierarchy,
// so call its hitTest method to return the right hit-test view
return self.spinnerTableView.hitTest(pointForTargetView, withEvent:event);
}
return super.hitTest(point, withEvent: event)
}
Run Code Online (Sandbox Code Playgroud)
编辑:
我很抱歉没有能够查看答案并检查他们是否解决了问题,因为其他一些任务需要立即引起注意.我会检查它们并接受一个有帮助的.谢谢你的耐心.
如你所说:
但是,如果控件位于另一个视图层次结构中,则UITableView不会接收触摸事件.
即使你让它工作了,如果你已经在另一个UIView下查看了这个控件?
这样我们就有了为视图层次结构转换点的负担,我的建议是,正如您在此控件中看到的那样,它将tableview添加到控件本身所在的同一层次结构中.(例如,它在添加了此控件的控制器上添加了表视图)
链接的一部分:
-(void)textFieldDidBeginEditing:(UITextField *)textField
{
[self setupSuggestionList];
[suggestionListView setHidden:NO];
// Add list to the super view.
if(self.dataSourceDelegate && [self.dataSourceDelegate isKindOfClass:UIViewController.class])
{
[((UIViewController *)self.dataSourceDelegate).view addSubview:suggestionListView];
}
// Setup list as per the given direction
[self adjustListFrameForDirection:dropDownDirection];
}
Run Code Online (Sandbox Code Playgroud)
希望有所帮助!
我认为你应该重写pointInside实现:
class Control: UIButton {\n\n var dropdown: Bool = false\n\n override func pointInside(point: CGPoint, withEvent event: UIEvent?) -> Bool {\n if dropdown {\n return CGRectContainsPoint(CGRect(x: 0, y:0, width: self.bounds.width, self.bounds.height + spinnerTableView.frame.height), point)\n }\n return super.pointInside(point, withEvent: event)\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n像这样,当超级视图调用控件hittest超出控件边界时,它不会返回 nil。
但仍然存在一个问题\xef\xbc\x8c 如果控件位于另一个视图层次结构中,UITableView 可能无法接收触摸事件。
\n\n我认为这个问题很正常\xef\xbc\x8c你无法决定其他视图的点在哪个控制之下,如果控制超级视图hitTest返回nil,控制hitTest方法将不会被调用。\n除非你覆盖了pointInside该控制下的所有视图方法控制,但不现实。
我在想UIResponder,类似的事情:
override func hitTest(point: CGPoint, withEvent event: UIEvent?) -> UIView? {
// Convert the point to the target view's coordinate system.
// The target view isn't necessarily the immediate subview
var responder: UIResponder = self
while responder.nextResponder() != nil {
responder = responder.nextResponder()!
if responder is UITableView {
// Got UITableView
break;
}
}
let pointForTargetView = responder.convertPoint(point, fromView:self)
if (CGRectContainsPoint(responder.bounds, pointForTargetView)) {
// The target view may have its view hierarchy,
// so call its hitTest method to return the right hit-test view
return self.responder.hitTest(pointForTargetView, withEvent:event);
}
return super.hitTest(point, withEvent: event)
}
Run Code Online (Sandbox Code Playgroud)
如果此方法不起作用,请尝试convertPoint使用 superview:
当您确定它self.spinnerTableView不为零并且它是您的表时,请执行以下操作:
let pointForTargetView = self.spinnerTableView.superView.convertPoint(point, fromView:self)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2907 次 |
| 最近记录: |