Objective c 在子视图外部触摸时删除子视图

Objective c 在子视图外部触摸时删除子视图,objective-c,uitableview,uiview,uinavigationbar,Objective C,Uitableview,Uiview,Uinavigationbar,我的情况比上面列出的其他情况要复杂一点 我有一个占据大部分屏幕的UITableView。 每行弹出一个子视图,其中包含更多的配置文件信息。再次单击屏幕时,此子视图将消失。这很好用 在导航栏中,我有一个按钮,可以显示一个小菜单 - (IBAction)menuButtonClicked:(UIBarButtonItem *)sender { //If menuView exists and Menu button is clicked, remove it from view if

我的情况比上面列出的其他情况要复杂一点

我有一个占据大部分屏幕的UITableView。 每行弹出一个子视图,其中包含更多的配置文件信息。再次单击屏幕时,此子视图将消失。这很好用

在导航栏中,我有一个按钮,可以显示一个小菜单

- (IBAction)menuButtonClicked:(UIBarButtonItem *)sender {
    //If menuView exists and Menu button is clicked, remove it from view
    if (self.menuView) {
        self.tableView.userInteractionEnabled = true;
        [self.menuView removeFromSuperview];
        self.menuView = Nil;
    }
    //Menu View doesn't exist so create it
    else {
        // Create the Menu View and add it to the parent view
        self.menuView = [[[NSBundle mainBundle] loadNibNamed:@"MenuView" owner:self 
           options:nil] objectAtIndex:0];
        self.menuView.layer.cornerRadius = 20.0f;
        self.menuView.layer.borderWidth = 3.0f;
        self.menuView.layer.borderColor = [UIColor whiteColor].CGColor;
        self.menuView.frame = CGRectMake(0, 64, self.menuView.frame.size.width,
                                     self.menuView.frame.size.height);

        UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] 
            initWithTarget:self action:@selector(singleTapGestureCaptured:)];
        [self.menuView addGestureRecognizer:singleTap];

        //Disable Selection of Profiles while Menu is showing
        self.tableView.userInteractionEnabled = false;

        //Add MenuView to View
        [self.view addSubview: self.menuView];
    }
}

//Removed Sub Views from View when tapped
-(void)singleTapGestureCaptured:(UITapGestureRecognizer *)gesture{
    if(self.profileView){
        [self.profileView removeFromSuperview];
        self.profileView = Nil;
    }
    if(self.menuView) {
        self.tableView.userInteractionEnabled = true;
        [self.menuView removeFromSuperview];
        self.menuView = Nil;
    }
}
现在,如果再次单击菜单按钮(在上面的代码中工作),并且当用户触摸菜单外和tableView或导航栏时,我想关闭此菜单。如果显示菜单,我不希望tableView显示它的profile子视图(在上面的代码中工作),而只是删除menuView。如果我触摸桌面视图,我就无法让菜单视图消失


有人能给我指出正确的方向吗?

制作一个新的透明覆盖视图,其大小可以覆盖整个屏幕。将菜单视图添加为覆盖的子视图,然后将覆盖添加为主窗口的子视图。在覆盖层上放置一个轻触手势识别器,轻触时会将其关闭

如果菜单视图上的按钮不工作,您可能需要在手势识别器上将cancelsTouchesInView设置为NO

大致如下(请原谅拼写错误,我还没有编译):


您可能还想添加一个滑动手势识别器来消除覆盖,因为有人可能会试图滚动表格,期望菜单被消除。

在尝试使用自己的自定义NIB文件制作自己的自定义自上而下幻灯片菜单时,我发现这可以通过许多技术实现。我想建议和分享一个不同的解决方案,这是非常相似的,但创建一个自定义按钮的背景。 我一直在四处寻找,但找不到提到这一点的答案。 这与点击识别器非常相似,只是有一点不同:点击识别器遍布整个布局(包括子视图),而使用一层自定义按钮可以与俯视图进行交互,并在单击下层(下层为背景按钮)时将其从superview中移除。我就是这样做的:

  • 您可以创建布局
  • 将UIButtonTypeCustom类型的UIButton添加到布局中
  • 您可以在希望响应该点击/单击的视图上框显此布局
  • 您可以将菜单视图添加到该布局的顶部,并设置菜单显示的动画

    - (void)showMenuViewWithBackgroundButtonOverlay
        {
            self.backgroundButton = ({
                UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
                button.frame = self.view.frame;
                [button addTarget:self action:@selector(toggleAppMenu) forControlEvents:UIControlEventTouchUpInside];
                button;
            });
    
            if (!self.menu) {
                self.menu = [self createMenu]; // <-- get your own custom menu UIView
            }
            if (!self.overlay) {
                self.overlay = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    
                self.overlay.backgroundColor = [UIColor clearColor];
    
                [self.overlay addSubview:self.backgroundButton];
    
                [self.overlay addSubview:self.menu];
    
                [self.view addSubview:self.overlay];
            }
    
            [self toggleAppMenu];
        }
    

    我希望这将对某人有所帮助。

    适用于Swift 5

    我创建自定义视图,并希望通过点击子视图外部来隐藏它。也许它可以帮助某人,或者任何人都可以建议一个更好的方法:)


    听起来好像你想要一个爆米花。你能发布一个草图来演示你想要的行为吗?我已经得到了一个“popover”,但它是一个使用NIB子视图的菜单视图。我想在用户触摸子视图外部时删除该子视图。
    - (void)showMenuViewWithBackgroundButtonOverlay
        {
            self.backgroundButton = ({
                UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
                button.frame = self.view.frame;
                [button addTarget:self action:@selector(toggleAppMenu) forControlEvents:UIControlEventTouchUpInside];
                button;
            });
    
            if (!self.menu) {
                self.menu = [self createMenu]; // <-- get your own custom menu UIView
            }
            if (!self.overlay) {
                self.overlay = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    
                self.overlay.backgroundColor = [UIColor clearColor];
    
                [self.overlay addSubview:self.backgroundButton];
    
                [self.overlay addSubview:self.menu];
    
                [self.view addSubview:self.overlay];
            }
    
            [self toggleAppMenu];
        }
    
    - (void)toggleAppMenu
    {
        CGRect nowFrame = [self.menu frame];
        CGRect toBeFrame = nowFrame;
        CGFloat navHeight = self.navigationController.navigationBar.frame.size.height;
        CGFloat statusBarHeight = [UIApplication sharedApplication].statusBarFrame.size.height;
    
        if (self.showingMenu) {
            toBeFrame.origin.y = toBeFrame.origin.y-nowFrame.size.height-navHeight-statusBarHeight;
            [UIView animateWithDuration:0.5 animations:^{
                [self.menu setFrame: toBeFrame];
            }completion:^(BOOL finished) {
                self.showingMenu = !self.showingMenu;
                [self.view endEditing:YES];
    
                [self.overlay removeFromSuperview];
                self.overlay = nil;
                NSLog(@"menu is NOT showing");
            }];
        }
        else{
            toBeFrame.origin.y = navHeight+statusBarHeight;
    
            [UIView animateWithDuration:0.5 animations:^{
                [self.menu setFrame: toBeFrame];
            }completion:^(BOOL finished) {
                self.showingMenu = !self.showingMenu;
                NSLog(@"menu is showing");
            }];
    
        }
    }
    
    // create tap for view
            let tapGesture = UITapGestureRecognizer(target: self, action: #selector(animateOut))
            self.addGestureRecognizer(tapGesture)
            
     // create tap for subview
            let tapGesture2 = UITapGestureRecognizer(target: self, action: nil)
            container.addGestureRecognizer(tapGesture2)