在外面点击时移除视图
Posted
技术标签:
【中文标题】在外面点击时移除视图【英文标题】:Remove view when tapped outside 【发布时间】:2015-08-21 23:55:08 【问题描述】:我有一个 UIView,当点击按钮时我会出现,我基本上将它用作自定义警报视图。现在,当用户在我添加到主视图的自定义 UIView 之外点击时,我想隐藏 cusomt 视图,我可以使用 customView.hidden = YES;
轻松做到这一点,但是如何检查视图之外的点击?
感谢您的帮助
【问题讨论】:
【参考方案1】:有两种方法
第一种方法
您可以为自定义视图设置标签:
customview.tag=99;
然后在您的视图控制器中,使用 touchesBegan:withEvent:
委托
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
UITouch *touch = [touches anyObject];
if(touch.view.tag!=99)
customview.hidden=YES;
第二种方法
更有可能的是,每次您想要弹出自定义视图时,它后面都会有一个覆盖层,它会填满您的屏幕(例如,alpha ~0.4 的黑色视图)。在这些情况下,您可以向其添加UITapGestureRecognizer
,并在每次您希望自定义视图显示时将其添加到您的视图中。这是一个例子:
UIView *overlay;
-(void)addOverlay
overlay = [[UIView alloc] initWithFrame:CGRectMake(0, 0,self.view.frame.size.width, self.view.frame.size.height)];
[overlay setBackgroundColor:[UIColor colorWithRed:0 green:0 blue:0 alpha:0.5]];
UITapGestureRecognizer *overlayTap =
[[UITapGestureRecognizer alloc] initWithTarget:self
action:@selector(onOverlayTapped)];
[overlay addGestureRecognizer:overlayTap];
[self.view addSubview:overlay];
- (void)onOverlayTapped
NSLog(@"Overlay tapped");
//Animate the hide effect, you can also simply use customview.hidden=YES;
[UIView animateWithDuration:0.2f animations:^
overlay.alpha=0;
customview.alpha=0;
completion:^(BOOL finished)
[overlay removeFromSuperview];
];
【讨论】:
我会建议第一种方法,而不是使用不必要的控件 (UITapGestureRecognizer)。最重要的是“更少的代码,更稳定的应用程序” 在这个答案中,第一种方法适用于我的项目,我将分享它的快速版本【参考方案2】:就像在 FlySoFast 的答案中一样,我尝试了第一种方法,它很有效,我只是分享了它的 swift 版本。您可以将其标记为您的自定义视图并检查该视图是否触摸,因此我们实现了我猜的解决方案。在下面我将自定义视图的标记值分配给 900。
customview.tag = 900
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?)
let touch = touches.first!
if touch.view?.tag != 900
resetMenu()
希望这个回答对你有帮助
【讨论】:
【参考方案3】:当您呈现自定义警报视图时,将该自定义警报视图添加到另一个全屏视图中,通过设置其backgroundColor
清除该视图以使该视图清晰。在主视图中添加全屏视图,并在全屏不可见视图中添加tapGesture
,当它被点击时删除此视图。
但是,如果您这样做,即使您触摸自定义警报视图,它也会关闭视图,您需要设置 tapGesture
的委托并实现此方法
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
if ([touch.view isDescendantOfView:self.customAlertView])
return NO;
return YES;
【讨论】:
【参考方案4】:在 Swift 中使用函数 pointInside:
override func pointInside(point: CGPoint, withEvent event: UIEvent?) -> Bool
if let view = customView
//if UIView is open open
let newPoint = self.convertPoint(point, toView: view)
let pointIsInsideGenius = view.pointInside(newPoint, withEvent: event)
// tapping inside of UIView
if pointIsInsideGenius
return true
else
// if tapped outside then remove UIView
view.removeFromSuperview()
view = nil
return false
【讨论】:
【参考方案5】:你可以使用这个库:https://github.com/huynguyencong/EzPopup
初始化一个PopUpController你想在点击外部时关闭它的视图
let popup = PopupViewController(contentView: viewNeedToRemoveWhenTapOutside, position: .bottomLeft(position))
present(popup, animated: true, completion: nil)
【讨论】:
【参考方案6】:顺便说一句,你可以做这个。主要技巧是一个将全屏包裹在自定义视图后面的按钮。当您单击按钮时,您只需关闭您的自定义视图。这是完整的代码。
这是完整的自定义 uiview 类
import Foundation
import UIKit
class CustomAlartView: UIView
static let instance = CustomAlartView()
@IBOutlet var parentView: UIView!
@IBOutlet weak var mainView: UIView!
@IBOutlet weak var userInput: UITextField!
override init(frame: CGRect)
super.init(frame: frame)
Bundle.main.loadNibNamed("CustomAlartView", owner: self, options: nil)
setupView()
//initWithCode to init view from xib or storyboard
required init?(coder aDecoder: NSCoder)
super.init(coder: aDecoder)
// setupView()
@IBAction func tappedCancel(_ sender: Any)
parentView.removeFromSuperview()
@IBAction func tappedOk(_ sender: Any)
if userInput.text == ""
print("\(userInput.text)")
else
parentView.removeFromSuperview()
@IBAction func tappedOutside(_ sender: Any)
print("click outside")
parentView.removeFromSuperview()
//common func to init our view
private func setupView()
parentView.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
parentView.autoresizingMask = [.flexibleHeight, .flexibleWidth]
mainView.layer.shadowColor = UIColor.gray.cgColor
mainView.layer.shadowOpacity = 1
mainView.layer.shadowOffset = CGSize(width: 10, height: 10)
mainView.layer.shadowRadius = 10
mainView.layer.cornerRadius = 15
mainView.layer.masksToBounds = true
enum alartType
case success
case failed
func showAlart()
UIApplication.shared.keyWindow?.addSubview(parentView)
【讨论】:
以上是关于在外面点击时移除视图的主要内容,如果未能解决你的问题,请参考以下文章