programing

Facebook 숨기기/확장/축소 탐색 모음 표시하기

padding 2023. 6. 2. 20:12
반응형

Facebook 숨기기/확장/축소 탐색 모음 표시하기

Facebook 가 새로 iOS7 Facebook iPhone을 때navigationBar점점 완전히 사라질 때까지 몸을 숨깁니다.그런 다음 사용자가 아래로 스크롤할 때navigationBar점차 모습을 드러냅니다.

이 동작을 직접 구현하려면 어떻게 해야 합니까?저는 다음과 같은 해결책을 알고 있지만, 그것은 바로 사라지고 사용자의 스크롤 제스처 속도와 전혀 관련이 없습니다.

[navigationController setNavigationBarHidden: YES animated:YES];

저는 "확장/축소" 행동을 어떻게 가장 잘 설명해야 할지 모르기 때문에 이것이 중복되지 않기를 바랍니다.

@peerless가 제공하는 솔루션은 훌륭한 시작이지만 스크롤 속도를 고려하지 않고 드래그가 시작될 때마다 애니메이션을 시작합니다.이것은 페이스북 앱에서 얻을 수 있는 것보다 더 멋진 경험을 하게 됩니다.Facebook의 행동과 일치하려면 다음과 같은 작업이 필요합니다.

  • 드래그 속도에 비례하는 속도로 탐색 막대 숨기기/표시
  • 막대가 부분적으로 숨겨져 있을 때 스크롤이 중지되는 경우 애니메이션을 시작하여 막대를 완전히 숨깁니다.
  • 막대가 줄어들면 탐색 막대의 항목이 희미해집니다.

먼저 다음 속성이 필요합니다.

@property (nonatomic) CGFloat previousScrollViewYOffset;

그리고 여기 있습니다.UIScrollViewDelegate메서드:

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    CGRect frame = self.navigationController.navigationBar.frame;
    CGFloat size = frame.size.height - 21;
    CGFloat framePercentageHidden = ((20 - frame.origin.y) / (frame.size.height - 1));
    CGFloat scrollOffset = scrollView.contentOffset.y;
    CGFloat scrollDiff = scrollOffset - self.previousScrollViewYOffset;
    CGFloat scrollHeight = scrollView.frame.size.height;
    CGFloat scrollContentSizeHeight = scrollView.contentSize.height + scrollView.contentInset.bottom;

    if (scrollOffset <= -scrollView.contentInset.top) {
        frame.origin.y = 20;
    } else if ((scrollOffset + scrollHeight) >= scrollContentSizeHeight) {
        frame.origin.y = -size;
    } else {
        frame.origin.y = MIN(20, MAX(-size, frame.origin.y - scrollDiff));
    }

    [self.navigationController.navigationBar setFrame:frame];
    [self updateBarButtonItems:(1 - framePercentageHidden)];
    self.previousScrollViewYOffset = scrollOffset;
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    [self stoppedScrolling];
}

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView 
                  willDecelerate:(BOOL)decelerate
{
    if (!decelerate) {
        [self stoppedScrolling];
    }
}

다음과 같은 도우미 방법도 필요합니다.

- (void)stoppedScrolling
{
    CGRect frame = self.navigationController.navigationBar.frame;
    if (frame.origin.y < 20) {
        [self animateNavBarTo:-(frame.size.height - 21)];
    }
}

- (void)updateBarButtonItems:(CGFloat)alpha
{
    [self.navigationItem.leftBarButtonItems enumerateObjectsUsingBlock:^(UIBarButtonItem* item, NSUInteger i, BOOL *stop) {
        item.customView.alpha = alpha;
    }];
    [self.navigationItem.rightBarButtonItems enumerateObjectsUsingBlock:^(UIBarButtonItem* item, NSUInteger i, BOOL *stop) {
        item.customView.alpha = alpha;
    }];
    self.navigationItem.titleView.alpha = alpha;
    self.navigationController.navigationBar.tintColor = [self.navigationController.navigationBar.tintColor colorWithAlphaComponent:alpha];
}

- (void)animateNavBarTo:(CGFloat)y
{
    [UIView animateWithDuration:0.2 animations:^{
        CGRect frame = self.navigationController.navigationBar.frame;
        CGFloat alpha = (frame.origin.y >= y ? 0 : 1);
        frame.origin.y = y;
        [self.navigationController.navigationBar setFrame:frame];
        [self updateBarButtonItems:alpha];
    }];
}

동작의 때 .else 인 을다scrollViewDidScroll) 다음과 같이 입력합니다.

frame.origin.y = MIN(20, 
                     MAX(-size, frame.origin.y - 
                               (frame.size.height * (scrollDiff / scrollHeight))));

이렇게 하면 절대적인 양 대신 마지막 스크롤 백분율을 기준으로 막대가 배치되어 페이드가 느려집니다.원래의 행동은 페이스북과 비슷하지만, 저는 이것도 좋아합니다.

참고: 이 솔루션은 iOS 7+ 전용입니다.이전 버전의 iOS를 지원하는 경우 필요한 검사를 추가해야 합니다.

편집: iOS 8 이상에서만 가능합니다.

사용해 볼 수 있습니다.

self.navigationController.hidesBarsOnSwipe = YES;

나한테 효과가 있어요.

만약 당신의 코딩이 신속하다면, 당신은 이 방법을 사용해야 합니다 (https://stackoverflow.com/a/27662702/2283308) .

navigationController?.hidesBarsOnSwipe = true

다음은 한 가지 더 구현한 내용입니다.TLYShyNavBar v1.0.0 출시!

저는 제공된 솔루션을 사용해 본 후 직접 제작하기로 결정했는데, 저에게는 성능이 좋지 않거나 진입 장벽과 보일러 플레이트 코드가 높거나 내비게이션 바 아래 확장 뷰가 부족했습니다.이 구성 요소를 사용하려면 다음 작업만 수행하면 됩니다.

self.shyNavBarManager.scrollView = self.scrollView;

아, 그리고 그것은 우리 앱에서 전투 테스트를 받았습니다.

GTScroll Navigation Bar를 보실 수 있습니다.UIScrollView 스크롤을 기준으로 스크롤되도록 UINavigationBar를 하위 분류했습니다.

참고: 불투명 탐색 모음이 있는 경우 탐색 모음이 숨겨지면 스크롤 보기가 확장되어야 합니다.이것이 바로 GTScroll Navigation Bar가 하는 일입니다.(예를 들어 iOS의 Safari와 같습니다.

iOS8에는 내비게이션 바를 무료로 숨길 수 있는 속성이 포함되어 있습니다.그것을 보여주는 WWDC 비디오가 있는데, "View Controller Advanced in iOS 8"을 검색하세요.

:

class QuotesTableViewController: UITableViewController {

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)

    navigationController?.hidesBarsOnSwipe = true
}

}

기타 속성:

class UINavigationController : UIViewController {

    //... truncated

    /// When the keyboard appears, the navigation controller's navigationBar toolbar will be hidden. The bars will remain hidden when the keyboard dismisses, but a tap in the content area will show them.
    @availability(iOS, introduced=8.0)
    var hidesBarsWhenKeyboardAppears: Bool
    /// When the user swipes, the navigation controller's navigationBar & toolbar will be hidden (on a swipe up) or shown (on a swipe down). The toolbar only participates if it has items.
    @availability(iOS, introduced=8.0)
    var hidesBarsOnSwipe: Bool
    /// The gesture recognizer that triggers if the bars will hide or show due to a swipe. Do not change the delegate or attempt to replace this gesture by overriding this method.
    @availability(iOS, introduced=8.0)
    var barHideOnSwipeGestureRecognizer: UIPanGestureRecognizer { get }
    /// When the UINavigationController's vertical size class is compact, hide the UINavigationBar and UIToolbar. Unhandled taps in the regions that would normally be occupied by these bars will reveal the bars.
    @availability(iOS, introduced=8.0)
    var hidesBarsWhenVerticallyCompact: Bool
    /// When the user taps, the navigation controller's navigationBar & toolbar will be hidden or shown, depending on the hidden state of the navigationBar. The toolbar will only be shown if it has items to display.
    @availability(iOS, introduced=8.0)
    var hidesBarsOnTap: Bool
    /// The gesture recognizer used to recognize if the bars will hide or show due to a tap in content. Do not change the delegate or attempt to replace this gesture by overriding this method.
    @availability(iOS, introduced=8.0)
    unowned(unsafe) var barHideOnTapGestureRecognizer: UITapGestureRecognizer { get }
}

http://natashatherobot.com/navigation-bar-interactions-ios8/ 를 통해 검색됨

저는 그것에 대한 빠르고 더러운 해결책을 가지고 있습니다.심층적인 테스트는 하지 않았지만 다음과 같은 아이디어가 있습니다.

이 속성은 내 UITableViewController 클래스에 대한 navbar의 모든 항목을 유지합니다.

@property (strong, nonatomic) NSArray *navBarItems;

동일한 UITableViewController 클래스에서 다음을 수행합니다.

-(void)scrollViewDidScrollToTop:(UIScrollView *)scrollView
{
    if([[[UIDevice currentDevice] systemVersion] floatValue] < 7.0f){
        return;
    }

    CGRect frame = self.navigationController.navigationBar.frame;
    frame.origin.y = 20;

    if(self.navBarItems.count > 0){
        [self.navigationController.navigationBar setItems:self.navBarItems];
    }

    [self.navigationController.navigationBar setFrame:frame];
}

-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    if([[[UIDevice currentDevice] systemVersion] floatValue] < 7.0f){
        return;
    }

    CGRect frame = self.navigationController.navigationBar.frame;
    CGFloat size = frame.size.height - 21;

    if([scrollView.panGestureRecognizer translationInView:self.view].y < 0)
    {
        frame.origin.y = -size;

        if(self.navigationController.navigationBar.items.count > 0){
            self.navBarItems = [self.navigationController.navigationBar.items copy];
            [self.navigationController.navigationBar setItems:nil];
        }
    }
    else if([scrollView.panGestureRecognizer translationInView:self.view].y > 0)
    {
        frame.origin.y = 20;

        if(self.navBarItems.count > 0){
            [self.navigationController.navigationBar setItems:self.navBarItems];
        }
    }

    [UIView beginAnimations:@"toggleNavBar" context:nil];
    [UIView setAnimationDuration:0.2];
    [self.navigationController.navigationBar setFrame:frame];
    [UIView commitAnimations];
}

그것은 오직 ios >= 7만을 위한 것입니다, 제가 아는 추악하지만 이것을 달성하는 빠른 방법입니다.어떤 의견/제안이든 환영합니다 :)

이것은 iOS 8 이상에서 작동하며 상태 표시줄이 여전히 배경을 유지하도록 보장합니다.

self.navigationController.hidesBarsOnSwipe = YES;
CGRect statuBarFrame = [UIApplication sharedApplication].statusBarFrame;
UIView *statusbarBg = [[UIView alloc] initWithFrame:statuBarFrame];
statusbarBg.backgroundColor = [UIColor blackColor];
[self.navigationController.view addSubview:statusbarBg];

상태 표시줄을 누를 때 탐색 모음을 표시하려면 다음 작업을 수행할 수 있습니다.

- (void)scrollViewDidScrollToTop:(UIScrollView *)scrollView {
     self.navigationController.navigationBarHidden = NO;
}

다음은 제 구현입니다.Shergin 스크롤 가능 탐색 막대.

의 접근 방식에 나는 현재사중방식접근인을 하고 있습니다.KVO▁observing.UIScrollView의 상태입니다. 따라서 대리인을 사용할 필요가 없습니다(그리고 이 대리인을 다른 필요한 용도로 사용할 수 있습니다).

저의 이 솔루션을 사용해 보시고 왜 이것이 이전 답변보다 좋지 않은지 알려주시기 바랍니다.

- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
{
    if (fabs(velocity.y) > 1)
        [self hideTopBar:(velocity.y > 0)];
}

- (void)hideTopBar:(BOOL)hide
{
    [self.navigationController setNavigationBarHidden:hide animated:YES];
    [[UIApplication sharedApplication] setStatusBarHidden:hide withAnimation:UIStatusBarAnimationSlide];
}

제가 이를 달성한 한 가지 방법은 다음과 같습니다.

를 뷰컨롤다등다니합으로 합니다.UIScrollViewDelegate의 신의의UITableView예를들면.

- (void)scrollViewDidScroll:(UIScrollView *)scrollView;
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView;
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate;

쪽에서안 에서.UIScrollViewDelegate새로운 컨텐츠를 얻을 수 있는 방법오프셋 및 번역UINavigationBar그에 따라 위 또는 아래로.

하위 보기의 알파 설정은 설정 및 계산할 수 있는 일부 임계값과 요인을 기반으로 수행할 수도 있습니다.

도움이 되길 바랍니다!

Iwburk의 답변 외에도 사용자 지정이 아닌 탐색 모음에서 알파 문제를 해결하고 viewWillDisparen 메서드에서 탐색 모음을 재설정하기 위해 다음을 추가했습니다.

- (void)updateBarButtonItems:(CGFloat)alpha
{
    for (UIView *view in self.navigationController.navigationBar.subviews) {
        NSString *className = NSStringFromClass([view class]);

        if ( ![className isEqualToString:@"_UINavigationBarBackground"] ) {
            view.alpha = alpha;
        }
    }
}

- (void)resetNavigationBar {
    CGRect frame = self.navigationController.navigationBar.frame;
    frame.origin.y = 20;
    [self.navigationController.navigationBar setFrame:frame];
    [self updateBarButtonItems:1.0f];
}

저는 어떤 스타일이든 어떤 행동이든 가능한 해결책을 찾고 있었습니다.막대 응축 동작은 많은 다른 앱에서 다르다는 것을 알게 될 것입니다.물론, 바의 모양은 앱마다 완전히 다릅니다.

https://github.com/bryankeller/BLKFlexibleHeightBar/ 에서 이 문제에 대한 솔루션을 만들었습니다.

막대가 축소 및 증가하는 방법과 시기를 제어하는 사용자 고유의 동작 규칙을 정의할 수 있으며 막대의 하위 뷰가 막대 응축 또는 증가에 반응하는 방식을 정확하게 정의할 수 있습니다.

당신이 생각할 수 있는 어떤 종류의 머리글 막대를 만들 수 있는 많은 유연성을 원한다면 제 프로젝트를 보세요.

UITableView에 대한 사용자 정의 헤더가 필요한 상황에서 이 동작을 모방하려고 했습니다.저는 제 "내비게이션" 막대를 굴렸습니다. 왜냐하면 이것은 페이지의 다른 많은 항목 아래에 위치하고 섹션 헤더가 기본 "도킹" 동작을 따르기를 원했기 때문입니다.Facebook/Instagram/Chrome/등의 앱에서 볼 수 있는 것과 유사한 스타일로 다른 개체와 함께 UITableView/UIScrollView를 조정하는 꽤 영리하고 간결한 방법을 찾은 것 같습니다.

.xib 파일에서 자유 형식 보기에 구성 요소를 로드했습니다. http://imgur.com/0z9yebJ (죄송합니다. 인라인 이미지에 대한 담당자가 없습니다.)

왼쪽 사이드바에서 테이블은 기본 머리글 보기 뒤에 정렬됩니다.스크린샷을 보면 알 수 없지만 메인 헤더 뷰와 동일한 y 위치를 가지고 있습니다.눈에 보이지 않는 범위까지 확장되기 때문에 내용은UITableView에서 76(기본 헤더 뷰의 높이)으로 설정된 속성을 삽입합니다.

기본 헤더 뷰를 UIScrollView와 함께 위로 슬라이드하려면 UIScrollViewDelegate의 scrollViewDidScroll 메서드를 사용하여 계산을 수행하고 UIScrollView의 내용을 변경합니다.기본 헤더 뷰의 프레임과 함께 삽입됩니다.

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    UIEdgeInsets insets = scrollView.contentInset;
    //tableViewInsetDelta and tableViewOriginalInsetValue are NSInteger variables that I set to 0 and 76, respectively, in viewDidLoad
    tableViewInsetDelta = tableViewOriginalInsetValue + scrollView.contentOffset.y;
    insets.top = tableViewOriginalInsetValue - tableViewInsetDelta;

    if (scrollView.contentOffset.y > -76 && scrollView.contentOffset.y < 0) {
        [scrollView setContentInset:insets];
        self.pathTitleContainer.frame = CGRectMake(self.pathTitleContainer.frame.origin.x, 44 - tableViewInsetDelta, self.pathTitleContainer.frame.size.width, self.pathTitleContainer.frame.size.height);
    } else if (scrollView.contentOffset.y > 0) {
        insets.top = 0;
        [scrollView setContentInset:insets];
        self.pathTitleContainer.frame = CGRectMake(self.pathTitleContainer.frame.origin.x, -32, self.pathTitleContainer.frame.size.width, self.pathTitleContainer.frame.size.height);
    } else if (scrollView.contentOffset.y < -76) {
        insets.top = 76;
        [scrollView setContentInset:insets];
        self.pathTitleContainer.frame = CGRectMake(self.pathTitleContainer.frame.origin.x, 44, self.pathTitleContainer.frame.size.width, self.pathTitleContainer.frame.size.height);
    }
}

번째 if 문은 대부분의 무거운 리프팅을 수행하지만, 사용자가 강제로 끌리는 상황과 scrollViewDidScroll로 전송되는 초기 contentOffset 값이 첫 번째 if 문의 범위를 벗어나는 상황을 처리하기 위해 나머지 두 개를 포함해야 했습니다.

궁극적으로, 이것은 저에게 정말 잘 작동합니다.저는 제 프로젝트를 부풀린 하위 클래스들로 가득 채우는 것을 싫어합니다.성능 측면에서 이것이 최고의 솔루션인지 아닌지에 대해서는 말할 수 없습니다(스크롤ViewDidScroll이 항상 호출되기 때문에 scrollViewDidScroll에 코드를 넣는 것이 항상 망설여졌습니다).그러나 코드 설치 공간은 이 문제에 대한 솔루션 중에서 가장 작으며 UIScrollView에 UITableView를 중첩하는 것은 포함되지 않습니다(Apple은 설명서에서 이에 대해 조언하고 터치 이벤트는 UITableView에서 약간 펑키하게 됩니다.이것이 누군가에게 도움이 되기를 바랍니다!

탐색 모음 숨기기는 원하는 경우 탐색 모음과 탭 모음을 숨기는 훌륭한 프로젝트입니다.

Hidden Navigation Bar는 다음 보기 요소의 숨기기/표시를 지원합니다.

UI 탐색 모음

UI 탐색 모음 및 확장 UI 보기

UI 탐색 모음 및 UI 도구 모음

UI 탐색 모음 및 UI 탭 모음

https://github.com/tristanhimmelman/HidingNavigationBar

GTScrollNavigationBar를 구현하려고 했지만 앱에서 자동 레이아웃 제약 조건을 수정해야 했습니다.다른 사용자가 자동 레이아웃으로 이 작업을 수행해야 할 경우를 대비하여 GitHub에 구현 사례를 올리기로 결정했습니다.다른 대부분의 구현에서 제가 겪었던 또 다른 문제는 스크롤 뷰의 크기를 동시에 조정하고 스크롤할 때 발생하는 시차 스크롤 효과를 피하기 위해 사람들이 스크롤 뷰의 경계를 설정하지 않는다는 것입니다.

자동 레이아웃으로 이 작업을 수행해야 하는 경우 JS CollapsingNavBarViewController를 확인하십시오.저는 두 가지 버전을 포함했는데, 하나는 탐색 막대만 있는 것이고 다른 하나는 탐색 막대 아래에 있는 하위 막대가 탐색 막대를 접기 전에 접히는 것입니다.

Swift 4.5 - iOS 11 이상용

private var previousScrollViewYOffset: CGFloat = 0
private var firstLoad = true
// to avoid scrollViewDidScroll called when first time view controller load
override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        firstLoad = false
    }
// MARK: - UIScrollViewDelegate
extension ViewController: UIScrollViewDelegate {
    func stoppedScrolling() {
        let frame = self.navigationController?.navigationBar.frame ?? .zero
        if frame.origin.y < UIView.statusBarFrame.size.height {
            self.animateNavBar(to: -frame.size.height + UIView.statusBarFrame.size.height)
        }
    }
    func updateBarButtonItems(alpha: CGFloat) {
        self.navigationItem.leftBarButtonItems?.forEach{ item in
            item.customView?.alpha = alpha
        }
        self.navigationItem.rightBarButtonItems?.forEach{ item in
            item.customView?.alpha = alpha
        }
        self.navigationItem.titleView?.alpha = alpha
        self.navigationController?.navigationBar.tintColor = self.navigationController?.navigationBar.tintColor.withAlphaComponent(alpha)
    }
    
    func animateNavBar(to y: CGFloat) {
        UIView.animate(withDuration: 0.2) {[weak self] in
            var frame: CGRect = self?.navigationController?.navigationBar.frame ?? .zero
            let alpha: CGFloat = frame.origin.y >= y ? 0 : 1
            frame.origin.y = y
            self?.navigationController?.navigationBar.frame = frame
            self?.updateBarButtonItems(alpha: alpha)
        }
    }
    
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        if firstLoad { return }
        var frame = self.navigationController?.navigationBar.frame ?? .zero
        let size = frame.size.height - UIView.statusBarFrame.size.height
        let framePercentageHidden = (UIView.statusBarFrame.size.height - frame.origin.y) / (frame.size.height - 1)
        let scrollOffset = scrollView.contentOffset.y
        let scrollDiff = scrollOffset - previousScrollViewYOffset
        let scrollHeight = scrollView.frame.size.height
        let scrollContentSizeHeight = scrollView.contentSize.height + scrollView.contentInset.bottom
        if scrollOffset <= -scrollView.contentInset.top {
            frame.origin.y = UIView.statusBarFrame.size.height
        } else if ((scrollOffset + scrollHeight) >= scrollContentSizeHeight) {
            frame.origin.y = -size
        } else {
            frame.origin.y = min(UIView.statusBarFrame.size.height, max(-size, frame.origin.y - scrollDiff))
        }
        self.navigationController?.navigationBar.frame = frame
        self.updateBarButtonItems(alpha: 1 - framePercentageHidden)
        self.previousScrollViewYOffset = scrollOffset
    }
    
    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        self.stoppedScrolling()
    }
    
    func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
        if(!decelerate) {
            self.stoppedScrolling()
        }
    }
}

UIView 확장자

extension UIView {
    public static var statusBarFrame: CGRect {
        get {
            return UIApplication.shared.statusBarFrame
        }
    }
}

은 지야합니다해정을 커스텀해야 .navigationItem.titleView세트를 alpha

나는 이 방법으로 그것을 시도했습니다. 도움이 되기를 바랍니다. 단지 대리자 방식으로 코드를 구현하고 원하는 보기/개요로 설정하세요.

-(void)scrollViewDidScroll:(UIScrollView *)scrollView{ 
            CGRect frame=self.view.frame;
            CGRect resultFrame=CGRectZero;
            if(scrollView.contentOffset.y==0 || scrollView.contentOffset.y<0){
                self.lastContentOffset=0;
                self.offset=0;
                resultFrame=CGRectMake(0, frame.size.height-(40-self.offset.intValue), frame.size.width, 40-self.offset.intValue);
    // Pass the resultFrame
                [self showHide:YES withFrame:resultFrame];
            }else if (self.lastContentOffset > scrollView.contentOffset.y){
                NSNumber *temp=[NSNumber numberWithDouble:self.lastContentOffset-scrollView.contentOffset.y];
                if(temp.intValue>40 || self.offset.intValue<temp.intValue){
                    self.offset=[NSNumber numberWithInt:0];
                    resultFrame=CGRectMake(0, frame.size.height-(40-self.offset.intValue), frame.size.width, 40-self.offset.intValue);
    // Pass the resultFrame
                    [self showHide:YES withFrame:resultFrame];
                }else{
                    if(temp.intValue>0){
                        self.offset=[NSNumber numberWithInt:self.offset.intValue-temp.intValue];
                        resultFrame=CGRectMake(0, frame.size.height-(40-self.offset.intValue), frame.size.width, 40-self.offset.intValue);
    // Pass the resultFrame
                        [self showHide:YES withFrame:resultFrame];
                    }
                }
            }else if (self.lastContentOffset < scrollView.contentOffset.y){
                NSNumber *temp=[NSNumber numberWithDouble:scrollView.contentOffset.y-self.lastContentOffset];
                if(self.offset.intValue>40 || (self.offset.intValue+temp.intValue)>40){
                    self.offset=[NSNumber numberWithInt:40];
    // Pass the resultFrame
                    [self showHide:NO withFrame:resultFrame];
                }else{
                    self.offset=[NSNumber numberWithInt:self.offset.intValue+temp.intValue];
                    resultFrame=CGRectMake(0, frame.size.height-(40-self.offset.intValue), frame.size.width, 40-self.offset.intValue);
    // Pass the resultFrame
                    [self showHide:YES withFrame:resultFrame];
                }
            }
            self.lastContentOffset = scrollView.contentOffset.y;

        }

-(void)showHide:(Boolean)boolView withFrame:(CGRect)frame{
               if(showSRPFilter){
                        //Assign value of "frame"to any view on which you wan to to perform animation
                }else{
                       //Assign value of "frame"to any view on which you wan to to perform animation
                }
        }

@Iwburk의 대답의 연장...탐색 모음의 원점을 변경하는 대신 탐색 모음의 크기를 확장/축소해야 했습니다.

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    CGRect frame = self.previousRect; // a property set in the init method to hold the initial size of the uinavigationbar
    CGFloat size = frame.size.height;
    CGFloat framePercentageHidden = ((MINIMUMNAVBARHEIGHT - frame.origin.y) / (frame.size.height - 1));
    CGFloat scrollOffset = scrollView.contentOffset.y;
    CGFloat scrollDiff = scrollOffset - self.previousScrollViewYOffset;
    CGFloat scrollHeight = scrollView.frame.size.height;
    CGFloat scrollContentSizeHeight = scrollView.contentSize.height + scrollView.contentInset.bottom;

    if (scrollOffset <= -scrollView.contentInset.top) {
        frame.origin.y = -MINIMUMNAVBARHEIGHT;
    } else if ((scrollOffset + scrollHeight) >= scrollContentSizeHeight) {
        frame.origin.y = -size;
    } else {
        frame.origin.y = MIN(-MINIMUMNAVBARHEIGHT, MAX(-size, frame.origin.y - scrollDiff));
    }

    self.previousRect = CGRectMake(0, frame.origin.y, self.jsExtendedBarView.frame.size.width, 155);
    self.layoutConstraintExtendedViewHeight.constant = MAXIMUMNAVBARHEIGHT + frame.origin.y + MINIMUMNAVBARHEIGHT;
    [self updateBarButtonItems:(1 - framePercentageHidden)];
    self.previousScrollViewYOffset = scrollOffset;
}

그것은 그것과 함께 작동하지 않습니다.stoppedScrolling은, 내가 때 할 것입니다.

이 모든 접근법들은 너무 복잡해 보입니다...그래서 자연스럽게, 저는 제 자신을 만들었습니다.

class ViewController: UIViewController, UIScrollViewDelegate {
    var originalNavbarHeight:CGFloat = 0.0
    var minimumNavbarHeight:CGFloat = 0
    weak var scrollView:UIScrollView!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        // setup delegates 
        scrollView.delegate = self
        // save the original nav bar height
        originalNavbarHeight = navigationController!.navigationBar.height
    }


    func scrollViewDidScroll(scrollView: UIScrollView) {
        // will relayout subviews
        view.setNeedsLayout() // calls viewDidLayoutSubviews
    }

    override func viewDidLayoutSubviews() {
        var percentageScrolled = min(scrollView.contentOffset.y / originalNavbarHeight, 1)
        navigationController?.navigationBar.height = min(max((1 - percentageScrolled) * originalNavbarHeight, minimumNavbarHeight), originalNavbarHeight)
        // re-position and scale scrollview
        scrollView.y = navigationController!.navigationBar.height + UIApplication.sharedApplication().statusBarFrame.height
        scrollView.height = view.height - scrollView.y
    }

    override func viewWillDisappear(animated: Bool) {
        navigationController?.navigationBar.height = originalNavbarHeight
    }

}

나는 목표-C에서 주어진 모든 답을 찾았습니다.이것은 스위프트 3에 있는 나의 대답입니다.이것은 매우 일반적인 코드이며 직접 사용할 수 있습니다.UIScrollView 및 UITableView 모두에서 작동합니다.

var lastContentOffset: CGPoint? = nil
var maxMinus: CGFloat           = -24.0
var maxPlus: CGFloat            = 20.0
var initial: CGFloat            = 0.0

override func viewDidLoad() {
    super.viewDidLoad()

    self.title = "Alarm Details"
    self.lastContentOffset = self.alarmDetailsTableView.contentOffset
    initial = maxPlus
}

func scrollViewDidScroll(_ scrollView: UIScrollView)
{
    var navigationBarFrame: CGRect   = self.navigationController!.navigationBar.frame
    let currentOffset = scrollView.contentOffset

    if (currentOffset.y > (self.lastContentOffset?.y)!) {
        if currentOffset.y > 0 {
            initial = initial - fabs(CGFloat(currentOffset.y - self.lastContentOffset!.y))
        }
        else if scrollView.contentSize.height < scrollView.frame.size.height {
            initial = initial + fabs(CGFloat(currentOffset.y - self.lastContentOffset!.y))
        }
    }
    else {
        if currentOffset.y < scrollView.contentSize.height - scrollView.frame.size.height {
            initial = initial + fabs(CGFloat(currentOffset.y - self.lastContentOffset!.y))
        }
        else if scrollView.contentSize.height < scrollView.frame.size.height && initial < maxPlus {
            initial = initial - fabs(CGFloat(currentOffset.y - self.lastContentOffset!.y))
        }
    }

    initial = (initial <= maxMinus) ? maxMinus : initial
    initial = (initial >= maxPlus) ? maxPlus : initial

    navigationBarFrame.origin.y = initial

    self.navigationController!.navigationBar.frame = navigationBarFrame
    scrollView.frame = CGRect(x: 0.0, y: initial + navigationBarFrame.size.height , width: navigationBarFrame.size.width, height: self.view.frame.size.height - (initial + navigationBarFrame.size.height))

    let framePercentageHidden: CGFloat              = ((20 - navigationBarFrame.origin.y) / (navigationBarFrame.size.height));
    self.lastContentOffset                          = currentOffset;
    self.updateBarButtonItems(alpha: 1 - framePercentageHidden)
}

func updateBarButtonItems(alpha: CGFloat)
{
    self.navigationController?.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName: UIColor.darkGray.withAlphaComponent(alpha)]
    self.navigationController?.navigationBar.isUserInteractionEnabled = (alpha < 1) ? false: true

    guard (self.navigationItem.leftBarButtonItems?.count) != nil else { return }

    for (_, value) in self.navigationItem.leftBarButtonItems!.enumerated() {
        value.customView?.alpha = alpha
    }

    guard (self.navigationItem.rightBarButtonItems?.count) != nil else { return }

    for (_, value) in (self.navigationItem.rightBarButtonItems?.enumerated())! {
        value.customView?.alpha = alpha
    }
}

알파를 탐색 항목으로 설정하는 논리는 @WayneBurkett 답변에서 복사되어 Swift 3에서 다시 작성됩니다.

언급URL : https://stackoverflow.com/questions/19819165/imitate-facebook-hide-show-expanding-contracting-navigation-bar

반응형