Как скрыть панель вкладок при перетаскивании, как приложение Safari?

Я хочу знать, как реализовать анимацию, которая скрывает панель вкладок при перетаскивании вниз, например приложение Safari на iOS 7. Любая информация от вас будет оценена.

Аналогичный вопрос: Показать/скрыть UIToolbar, и "перемещать пальцы рук" , точно так же, как, например, в iOS7 Safari.

Ответ 1

Что-то вроде этого должно работать. Я не знаю, дает ли это то же самое, что и приложение Safari, но оно закрывается:

@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
@property (nonatomic) CGRect originalFrame;
@end

@implementation ViewController

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    self.scrollView.contentSize = CGSizeMake(self.view.frame.size.width, 1000);
    self.originalFrame = self.tabBarController.tabBar.frame;
}


-(void)scrollViewDidScroll:(UIScrollView *)scrollView {
    UITabBar *tb = self.tabBarController.tabBar;
    NSInteger yOffset = scrollView.contentOffset.y;
    if (yOffset > 0) {
        tb.frame = CGRectMake(tb.frame.origin.x, self.originalFrame.origin.y + yOffset, tb.frame.size.width, tb.frame.size.height);
    }
   if (yOffset < 1) tb.frame = self.originalFrame;
}

Ответ 2

Принятый ответ не работает, когда у вас много ячеек в виде таблицы. Панель вкладок отображается только в том случае, если вы прокручиваете весь путь до вершины.

Я улучшил его следующим образом:

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    self.scrollView.contentSize = CGSizeMake(self.view.frame.size.width, 1000);
    self.originalFrame = self.tabBarController.tabBar.frame;
}


-(void)scrollViewDidScroll:(UIScrollView *)scrollView{

UITabBar *tabBar = self.tabBarController.tabBar;

NSInteger yOffset = scrollView.contentOffset.y;
CGFloat yPanGesture = [scrollView.panGestureRecognizer translationInView:self.view].y;
CGFloat heightTabBar = tabBar.frame.size.height;

CGFloat tabBarOriginY = tabBar.frame.origin.y;
CGFloat frameHeight = self.view.frame.size.height;

if(yOffset>=heightTabBar)
    yOffset = heightTabBar;

// GOING UP ------------------
if(yPanGesture >= 0 && yPanGesture < heightTabBar && tabBarOriginY > frameHeight-heightTabBar){
    yOffset = heightTabBar - fabsf(yPanGesture);
}
else if(yPanGesture >= 0 && yPanGesture < heightTabBar && tabBarOriginY <= frameHeight-heightTabBar){
    yOffset = 0;
}
// GOING DOWN ------------------
else if(yPanGesture < 0 && tabBarOriginY < frameHeight){
    yOffset = fabsf(yPanGesture);
}else if(yPanGesture < 0 && tabBarOriginY >= frameHeight){
    yOffset = heightTabBar;
}
else{
    yOffset = 0;
}

if (yOffset > 0) {
    tabBar.frame = CGRectMake(tabBar.frame.origin.x, self.originalFrame.origin.y + yOffset, tabBar.frame.size.width, tabBar.frame.size.height);
}
else if (yOffset <= 0){
    tabBar.frame = self.originalFrame;
}
}

    - (void)scrollViewWillEndDragging:(UIScrollView*)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset{ 

// Handle unfinished animations   
    UITabBar *tabBar = self.tabBarController.tabBar;
    CGFloat yPanGesture = [scrollView.panGestureRecognizer translationInView:self.view].y;
    CGFloat heightTabBar = tabBar.frame.size.height;
    CGFloat tabBarOriginY = tabBar.frame.origin.y;
    CGFloat frameHeight = self.view.frame.size.height;


    if(yPanGesture > 0){

        if(tabBarOriginY != frameHeight - heightTabBar) {

            [UIView animateWithDuration:0.3 animations:^(void){
                tabBar.frame = self.originalFrame;
            }];

        }

    }else if(yPanGesture < 0){

    if (tabBarOriginY != frameHeight) {
        [UIView animateWithDuration:0.3 animations:^(void){
            tabBar.frame = CGRectMake(tabBar.frame.origin.x, frameHeight, tabBar.frame.size.width, tabBar.frame.size.height);
        }];
    }

}

}

Ответ 3

Честно говоря, я пробовал все эти решения, и они не были достаточно надежными для меня. Они скрывали бы панель вкладок, когда она должна была отображаться, или они перемещали панель вкладок странным образом.

В итоге я провел целый день, пытаясь заставить их работать. Я, наконец, сдался и использовал: https://github.com/tristanhimmelman/HidingNavigationBar.

Это дало мне возможность скрывать навигационную панель и панель вкладок (именно этого я и хотел в первую очередь). Он работает очень хорошо, и я установил его за 10 минут.

Надеюсь, это поможет кому-то еще не потерять день кодирования: -0.

Ответ 4

Ну, хотя все ответы других не работают и не работают частично, HidingNavigationBar от @RobNorback работает блестяще, и это на самом деле довольно легко настроить.

Тем не менее, я немного боролся с каркасом и потратил 2 часа на его исправление, поэтому я добавляю свои два цента для того, чтобы кто-то не попал в один и тот же файл.

Если количество элементов или строк в представлении коллекции или табличном представлении невелико, оно не скрывает навигационную панель (или панель инструментов или панель инструментов), , даже если количество элементов или строк достаточно велико, чтобы выйти за пределы экрана. Вы должны добавить немного больше элементов или строк, чтобы структура правильно спрятала панель.

Ответ 5

Вы можете использовать переменную, чтобы сохранить значение lastContentOffset. Ключевой идеей является начало полосы вкладок. Это диапазон между CGRectGetMaxY (screenRect) и CGRectGetMaxY (screenRect) - CGRectGetHeight (tabBarRect).

Это хорошо работает в моем проекте.

@interface ViewController ()
    @property (nonatomic, assign) CGFloat lastContentOffsetY;
@end

@implementation ViewController
-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    if (!self.tabBarController) {
      return;
    }

  BOOL isStatusBarHidden = [UIApplication sharedApplication].isStatusBarHidden;
  CGFloat kStatusBarHeight = [UIApplication sharedApplication].statusBarFrame.size.height;

if (scrollView.contentOffset.y > (scrollView.contentSize.height - scrollView.frame.size.height)
    || (scrollView.contentOffset.y < (isStatsuBarHidden ? 0 : -kStatusBarHeight))) {
    // bottom & top bouncing - don't need to update
    return;
}

CGFloat offset = scrollView.contentOffset.y - self.lastContentOffsetY;
CGRect tabBarRect = self.tabBarController.tabBar.frame;
CGRect screenRect = [UIScreen mainScreen].bounds;

if (CGRectGetMaxY(tabBarRect) == CGRectGetMaxY(screenRect) + CGRectGetHeight(tabBarRect)) {
    //view could only scroll downward
    if (offset < 0) {
        tabBarRect.origin.y += offset;
    }
} else if (CGRectGetMaxY(tabBarRect) == CGRectGetMaxY(screenRect)) {
    //view could only scroll upward
    if (offset > 0) {
        tabBarRect.origin.y += offset;
    }
} else {
    //view could scroll upward & downward
    tabBarRect.origin.y += offset;
}

//safty reset handling
if (CGRectGetMaxY(tabBarRect) > CGRectGetMaxY(screenRect) + CGRectGetHeight(tabBarRect)) {
    tabBarRect.origin.y = CGRectGetMaxY(screenRect);
} else if (CGRectGetMaxY(tabBarRect) < CGRectGetMaxY(screenRect)) {
    tabBarRect.origin.y = CGRectGetMaxY(screenRect) - CGRectGetHeight(tabBarRect); // over bouncing, set it back
}

self.tabBarController.tabBar.frame = tabBarRect;
self.lastContentOffsetY = scrollView.contentOffset.y;
}

Ответ 6

static CGFloat navBarOriginY = 20.0;

Создать константу для базового значения начала навигационной панели Y-позиция

- (void)viewDidLoad {
[super viewDidLoad];
 self.navigationController.hidesBarsOnSwipe = true;
[self.navigationController.barHideOnSwipeGestureRecognizer addTarget:self action:@selector(swipe:)];
}

Добавьте свой пользовательский селектор, чтобы обрабатывать жест жесткой системы, который будет срабатывать до того, как navBar станет скрытым и во время скрытия

- (void)swipe:(UIPanGestureRecognizer *)recognizer {
if (recognizer.state == UIGestureRecognizerStateEnded || recognizer.state == UIGestureRecognizerStateCancelled || recognizer.state == UIGestureRecognizerStateFailed) {

Если состояние gesture завершено/отменено или не выполнено, вам нужно полностью изменить рамку tabBar

    CGRect finalFrame = self.tabBarController.tabBar.frame;
    if (self.navigationController.navigationBar.frame.origin.y < 0) {
         //Tab bar will be hidden
        finalFrame.origin.y = self.maxTabBarY;
    } else {
         //Tab bar will be visible
        finalFrame.origin.y = self.minTabBarY;
    }

    [self setFrameForTabBar:finalFrame animationDuration:0.3];

} else if (recognizer.state == UIGestureRecognizerStateChanged) {

Если состояние == изменилось, вам нужно панорамировать ваш tabBar с помощью navBar, как в приложении Safari.

    CGRect frame = self.tabBarController.tabBar.frame;
    CGFloat delta = navBarOriginY - self.navigationController.navigationBar.layer.presentationLayer.frame.origin.y;
    frame.origin.y = self.minTabBarY + delta;
    [self setFrameForTabBar:frame animationDuration:0.0];
} } }

- (void)setFrameForTabBar:(CGRect)frame animationDuration:(CGFloat)duration {
dispatch_async(dispatch_get_main_queue(), ^{
    [UIView animateWithDuration:duration delay:0.0 options:UIViewAnimationOptionCurveLinear animations:^{
        self.tabBarController.tabBar.frame = frame;
    } completion:^(BOOL finished) {}];
});