如果我淡出导航栏,然后以编程方式将其隐藏,该如何做呢?如果我撤消此操作,就不会出现计时问题? [英] How can I make it so if I fade my navigation bar out, then actually hide it programmatically, that if I undo this there's no timing issues?

查看:57
本文介绍了如果我淡出导航栏,然后以编程方式将其隐藏,该如何做呢?如果我撤消此操作,就不会出现计时问题?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

长话短说,我有一个视图控制器,用户可以在其中单击self.view(导航栏以外的任何位置),它将进入全屏模式,其中底部的控件会淡出,导航和状态栏消退.类似于iBooks.

Long story short, I have a view controller where the user can tap on self.view (anywhere but the nav bar) and it will enter a full screen mode where the controls at the bottom fade out and the navigation and status bar fade out. Similar to iBooks.

我可以简单地淡化导航栏的Alpha,但是为了允许用户点击新获得的区域(现在它淡化了导航栏的位置)并使其有所作为,我必须做更多的事情而不是更改Alpha,因为导航栏在技术上仍会占用区域.

I could simply fade the alpha of the navigation bar, but as to allow the user to tap in the newly gained area (where the navigation bar was now that it's faded out) and have it do something, I have to do more than change the alpha, as the nav bar is still technically there taking up area.

所以我用[self.navigationController setNavigationBarHidden:YES animated:NO];隐藏了导航栏.我必须在动画块完成后执行此操作,否则它将在动画块中并作为该块的一部分进行动画处理.因此,我使用dispatch_after使其在动画完成(延迟0.35秒)后完成.

So I hide the navigation bar with [self.navigationController setNavigationBarHidden:YES animated:NO];. I have to do this after the animation block finishes, else it will be in the animation block and animate as part of the block. So I use a dispatch_after to make it finish after the animation completes (0.35 second delay).

但是,这会导致以下问题:如果用户在动画播放的0.35秒时间段内的任何时间点按,而事情正在等待完成,则会导致故障现象,即使仍在等待0.35秒,另一个块也会开始另一个完成.这会导致一些小故障,并使导航栏保持隐藏状态.毛.

However, this causes the issue where if the user taps any time during that 0.35 second time period where it's animating out and things are waiting to be finished, it causes glitchy behaviour where another block starts even though it's still waiting 0.35 seconds for the other one to finish. It causes some glitchy behaviour and causes the navigation bar to stay hidden. Gross.

它发生的视频: http://cl.ly/2i3H0k0Q1T0V

这是我的代码来演示我在做什么:

Here's my code to demonstrate what I'm doing:

- (void)hideControls:(BOOL)hidden {
    self.navigationController.view.backgroundColor = self.view.backgroundColor;
    int statusBarHeight = [UIApplication sharedApplication].statusBarFrame.size.height;

    [UIView animateWithDuration:0.35 animations:^{
        [[UIApplication sharedApplication] setStatusBarHidden:hidden withAnimation:UIStatusBarAnimationFade];

        if (hidden) {
            self.navigationController.navigationBar.alpha = 0.0;
            self.instructionsLabel.alpha = 0.0;
            self.backFiftyWordsButton.alpha = 0.0;
            self.forwardFiftyWordsButton.alpha = 0.0;
            self.WPMLabel.alpha = 0.0;
            self.timeRemainingLabel.alpha = 0.0;
        }
        else {
            self.navigationController.navigationBar.alpha = 1.0;
            self.instructionsLabel.alpha = 1.0;
            self.backFiftyWordsButton.alpha = 1.0;
            self.forwardFiftyWordsButton.alpha = 1.0;
            self.WPMLabel.alpha = 1.0;
            self.timeRemainingLabel.alpha = 1.0;
        }

        [self.view layoutIfNeeded];
    }];

    // Perform an "actual" hide (more than just alpha changes) after the animation finishes in order to regain that touch area
    if (hidden) {
        double delayInSeconds = 0.35;
        dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
        dispatch_after(popTime, dispatch_get_main_queue(), ^(void) {
            [self.navigationController setNavigationBarHidden:YES animated:NO];
            self.textToReadLabelPositionFromTopConstraint.constant = TEXT_LABEL_DISTANCE + self.navigationController.navigationBar.frame.size.height + statusBarHeight;
        });
    }
    else {
        [self.navigationController setNavigationBarHidden:NO animated:NO];
        self.textToReadLabelPositionFromTopConstraint.constant = TEXT_LABEL_DISTANCE;
    }
}

我要做的另一件事是更改自动布局"约束上的常量,以根据导航栏和状态栏是否存在来进行解释.

The only other thing I'm doing is changing the constant on my Auto Layout constraint to account for the navigation bar and status bar dependent on whether or not they're there.

我不确定如何考虑两次轻击会真正干扰全屏过程的事实.如果他们在动画过程中轻按,我该怎么做才能取消动画并按预期方式执行所需的动作?我可以做得更好吗?

I'm not sure how to factor in the fact that double tapping can really glitch out the full screen process. How could I make it so if they tap during the animation process it will just cancel the animation and do their desired action as intended? Could I be doing this process better?

推荐答案

我认为您可以执行以下操作而无需使用以下原理调整任何框架或约束:

I think you can do this without adjusting any frames or constraints using these principles:

1)使窗口的背景颜色与视图的颜色相同

1) Make the window's background color the same as your view's

2)将轻击手势识别器添加到窗口.这样,无论是否显示导航栏,都可以在屏幕上的任意位置(状态栏的Alpha不为0时)轻按.这样一来,您不必将导航栏设置为隐藏即可导致视图调整大小.

2) Add a tap gesture recognizer to the window. This allows tapping anywhere on the screen (except the status bar when its alpha isn't 0) whether the navigation bar is visible or not. This allows you to not have to set the navigation bar to hidden which would cause your view to resize.

3)在敲击器的操作方法中使用hitTest:来检查用户是否轻按了导航栏,并且如果敲击在其中,则不要淡出.

3) Use hitTest: in the tapper's action method to check if the user tapped the navigation bar, and don't fade out if the tap was there.

4)在动画块中使用UIViewAnimationOptionBeginFromCurrentState和UIViewAnimationOptionAllowUserInteraction,以便可以通过再次触摸平滑地淡入或淡出.

4) Use UIViewAnimationOptionBeginFromCurrentState and UIViewAnimationOptionAllowUserInteraction in the animation block so the fade-in or fade-out can be reversed smoothly with another touch.

5)将所有底部控件包含在一个清晰的UIView中,以便您可以淡出该UIView而不是所有单个控件.

5) Enclose all the bottom controls in a clear UIView so you can just fade out that UIView instead of all the individual controls.

这是起作用的代码:

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    self.view.window.backgroundColor = self.view.backgroundColor;
    UITapGestureRecognizer *tapper = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(fadeInFadeOut:)];
    [self.view.window addGestureRecognizer:tapper];

}


-(void)fadeInFadeOut:(UITapGestureRecognizer *)sender {
    static BOOL hide = YES;
    id hitView = [self.navigationController.view hitTest:[sender locationInView:self.navigationController.view] withEvent:nil];

    if (! [hitView isKindOfClass:[UINavigationBar class]] && hide == YES) {
        hide = ! hide;
        [[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationFade];
        [UIView animateWithDuration:.35 delay:0 options:UIViewAnimationOptionBeginFromCurrentState|UIViewAnimationOptionAllowUserInteraction animations:^{
            self.navigationController.navigationBar.alpha = 0;
            self.bottomView.alpha = 0;
        } completion:nil];

    }else if (hide == NO){
        hide = ! hide;
        [[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationFade];
        [UIView animateWithDuration:.35 delay:0 options:UIViewAnimationOptionBeginFromCurrentState|UIViewAnimationOptionAllowUserInteraction animations:^{
            self.navigationController.navigationBar.alpha = 1;
            self.bottomView.alpha = 1;
        } completion:nil];
    }
}

这篇关于如果我淡出导航栏,然后以编程方式将其隐藏,该如何做呢?如果我撤消此操作,就不会出现计时问题?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆