【问题标题】:Remove view when tapped outside在外面点击时移除视图
【发布时间】:2015-08-21 23:55:08
【问题描述】:

我有一个 UIView,当点击按钮时我会出现,我基本上将它用作自定义警报视图。现在,当用户在我添加到主视图的自定义 UIView 之外点击时,我想隐藏 cusomt 视图,我可以使用 customView.hidden = YES; 轻松做到这一点,但是如何检查视图之外的点击?

感谢您的帮助

【问题讨论】:

    标签: ios objective-c uiview


    【解决方案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)
                }
                
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2020-08-04
              • 1970-01-01
              • 1970-01-01
              • 2018-11-26
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多