Facebook'u taklit et Genişleyen / daralan Gezinme Çubuğunu gizle / göster


128

Yeni iOS7 Facebook iPhone uygulamasında, kullanıcı ekranı yukarı kaydırdığında, navigationBarkendisini yavaş yavaş tamamen kaybolduğu bir noktaya kadar gizler. Ardından kullanıcı aşağı kaydırdığında navigationBaryavaş yavaş kendini gösterir.

Bu davranışı kendiniz nasıl uygularsınız? Aşağıdaki çözümün farkındayım, ancak hemen kayboluyor ve kullanıcının kaydırma hareketinin hızına hiç bağlı değil.

[navigationController setNavigationBarHidden: YES animated:YES];

Umarım "genişleme / daralma" davranışını en iyi nasıl tanımlayacağımdan emin olmadığım için bu bir kopya değildir.


2
Aynı sorunlar: stackoverflow.com/questions/21929220/... Not o olduğunu son derece zor etmek kesinlikle Safari davranışını eşleşecek. Orada bazı çok, çok karmaşık kurallar var!
Şişko

1
Projemde bu projeyi kullandım ve gayet iyi çalıştı. Belgelerine bir göz atın.
Vinicius

github.com/bryankeller/BLKF FlexibleHeightBar , istediğinizi ve daha fazlasını yapmanızı sağlar. Büyütülmüş durumdan küçültülmüş duruma geçişin her aşamasında çubuğun tam olarak nasıl görüneceğini belirlemenize olanak tanır. Hatta kendi davranışlarınızı belirlemenize izin verir, böylece Safari, Facebook veya başka bir uygulama gibi davranabilir.
blkhp19

Bir uinavigationbar kullanmadım, bunun yerine bir uiview ekledim. Gezinme çubuğunu kopyalayan görünüm, kaydırmaya bağlı olarak genişler ve daralır. Görevi gerçekleştirmek için scrollViewDidScroll temsilci yöntemini kullandım. Aşağıdaki kaynak kodunu kontrol edip çalıştırmak isteyebilirsiniz .. dropbox.com/s/b2c0zw6yvchaia5/FailedBanks.zip?dl=0
Deepak Thakur

Yanıtlar:


162

@Peerless tarafından verilen çözüm harika bir başlangıçtır, ancak kaydırmanın hızını dikkate almadan yalnızca sürükleme başladığında bir animasyonu başlatır. Bu, Facebook uygulamasında elde ettiğinizden daha dalgalı bir deneyimle sonuçlanır. Facebook'un davranışına uymak için şunları yapmamız gerekiyor:

  • sürükleme hızıyla orantılı bir hızda gezinme çubuğunu gizleyin / gösterin
  • çubuk kısmen gizlendiğinde kaydırma durursa, çubuğu tamamen gizlemek için bir animasyonu başlat
  • çubuk küçüldükçe gezinme çubuğunun öğelerini soldurun.

Öncelikle aşağıdaki mülke ihtiyacınız olacak:

@property (nonatomic) CGFloat previousScrollViewYOffset;

Ve işte UIScrollViewDelegateyöntemler:

- (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];
    }
}

Ayrıca şu yardımcı yöntemlere ihtiyacınız olacak:

- (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];
    }];
}

Biraz farklı bir davranış için, kaydırırken çubuğu yeniden konumlandıran çizgiyi ( elseblok içeri scrollViewDidScroll) bununla değiştirin:

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

Bu, çubuğu mutlak bir miktar yerine son kaydırma yüzdesine göre konumlandırır ve bu da daha yavaş bir solmaya neden olur. Orijinal davranış daha çok Facebook'a benzer, ancak bunu da seviyorum.

Not: Bu çözüm yalnızca iOS 7+ içindir. İOS'un eski sürümlerini destekliyorsanız gerekli kontrolleri eklediğinizden emin olun.


Bu çalışıyor. Çubuk düğmesi öğelerinin özel görünümlere sahip olduğunu varsaymanız dışında. Benim durumumda özel bir görünümüm yok. Yani yukarıdakiler çubuk düğmelerini gizlemez. Ben @peerless çözüm gizleme ve gösterme navbar öğeleri için iyi olduğunu düşünüyorum
Dhanush

1
Haklısın. Bu hafta sonu daha genel bir çözüme bakabilirim. Bunun yerine varsayılan öğeleri hedeflemek çok zor olmamalı customView.
Wayne

@ Dhanush'un sorununa değinmedim ama bir güncellemem var.
Wayne

1
Stok çubuğu düğmeleriyle ilgili sorunu çözdüm, ancak bu kodun başka bir sorunu var. Eğer ScrollView'nin contentSizeçerçeve daha küçük olan, kayma animasyon çalışması değildir. Ayrıca tüm gezinme öğesinin alfa değerini 1,0 inç'e sıfırladığınızdan emin olun viewDidDisappear.
Legoless

1
AutoLayout kullanılan kontrolörlerde bu çözümü kontrol ettiniz mi? Benim durumumda, AutoLayout olmadan her şey iyi çalışıyor, ancak açıldığında, altında hala bazı garip beyaz şerit görülebilir
Aliaksandr B.

52

DÜZENLEME: Yalnızca iOS 8 ve üzeri için.

Kullanmayı deneyebilirsin

self.navigationController.hidesBarsOnSwipe = YES;

Benim için çalışıyor.

Kodlamanız hızlıysa, bu şekilde kullanmanız gerekir ( https://stackoverflow.com/a/27662702/2283308 adresinden )

navigationController?.hidesBarsOnSwipe = true

bu iOS <8.0
Petar

1
Pet60t0'ın dediği gibi özür dilerim, yalnızca iOS 8 ve üzeri için çalışır.
Pedro Romão

4
Bundan sonra onu nasıl geri getireceksiniz?
C0D3

davranış biraz tuhaf. Çok fazla keşfetmedim, ancak daha hızlı kaydırırsanız tekrar görünür.
Pedro Romão

@ PedroRomão harika cevap.
Gagan_iOS

43

İşte bir uygulama daha: TLYShyNavBar v1.0.0 yayınlandı!

Sağlanan çözümleri denedikten sonra kendim yapmaya karar verdim ve bana göre ya kötü performans gösteriyorlardı, yüksek bir giriş engeli ve kazan plakası kodu vardı ya da gezinme çubuğunun altındaki uzantı görünümünden yoksundu. Bu bileşeni kullanmak için yapmanız gereken tek şey:

self.shyNavBarManager.scrollView = self.scrollView;

Oh, ve kendi uygulamamızda savaşta test edildi.


@TimArnold Geri bildiriminiz için teşekkürler! Bu sorunu düzelttim, henüz bölmeyi güncellemedim> _ <bunu hemen şimdi yapacağım! .. Kapsül güncellendi!
Mazyod

Bir şans daha vereceğim! Teşekkürler!
Tim Kamber

Yardımın için minnettarım. Görünüşe bakılırsa işine yaradı. UICollectionView'umun gezinme çubuğu olduğu gibi düzgün şekilde yeniden boyutlandırılmadığı ve bu nedenle hücreler, koleksiyon görünümü sınırlarının dışında oldukları için KULLANILAN gezinme çubuğunun kırpıldığı yerde yukarı çıktığı garip bir sorunla karşılaşıyorum. Bunun neden olabileceğini biliyor musunuz?
Tim Kamber

4
Şekiller: Bu yorumu yazdıktan saniyeler sonra çözümümü buldum. BenimextendedLayoutIncludesOpaqueBarsYESUICollectionViewController
Tim Camber

@TimArnold Bu harika! Aynı sorunu yaşayan başka bir adam vardı ve umarım çözümünüz ona yardımcı olur.
Mazyod

33

GTScrollNavigationBar'ıma bir göz atabilirsiniz . Bir UIScrollView kaydırmasına dayalı olarak kaydırılmasını sağlamak için UINavigationBar'ı alt sınıflara ayırdım.

Not: OPAQUE gezinme çubuğunuz varsa, gezinme çubuğu GİZLİ hale geldikçe kaydırma görünümünün GENİŞLETİLMESİ gerekir. GTScrollNavigationBar'ın yaptığı tam olarak budur. (Tıpkı örneğin iOS'ta Safari'de olduğu gibi.)


Okuyan herkes için BTW, initWithNavigationBarClass'ı tam olarak nasıl çağırabilirim ... stackoverflow.com/questions/22286166
Fattie

@ Harika iş al adamım! Bu yüzden bir tablo görünümü denetleyicisinde bunun üzerinde mükemmel bir şekilde çalışıyorum, bir şey hariç ... En üstte uygulanan yenilemek için çektim. Aşağı çekip yenilemeye çalışırken tuhaflaşıyor. Bunun için bir çözüm olabilir mi?
aherrick

@Thuy ayrıca ... diyelim ki, altta bir tablo görünümü uyguladığım bir görünüm denetleyicim var. İşe yarayan bu tablo görünümüne bağlanmak istiyorum, ancak masa görünümünün üzerinde oturan ve kaybolmasını istediğim başka bir görünümüm var. Bu nasıl işleyebilir?
aherrick

25

iOS8, gezinme çubuğunun ücretsiz olarak gizlenmesini sağlayan özellikler içerir. Bunu gösteren bir WWDC videosu var, "iOS 8'de Denetleyici Gelişmelerini Görüntüle" yi arayın.

Örnek :

class QuotesTableViewController: UITableViewController {

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

    navigationController?.hidesBarsOnSwipe = true
}

}

Diğer özellikler:

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/ aracılığıyla bulunur


12

Bunun için hızlı ve kirli bir çözümüm var. Derinlemesine bir test yapmadım ama fikir şu:

Bu özellik, UITableViewController sınıfım için gezinme çubuğundaki tüm öğeleri tutacak

@property (strong, nonatomic) NSArray *navBarItems;

Aynı UITableViewController sınıfında:

-(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];
}

Bu sadece ios> = 7 için, biliyorum çirkin ama bunu başarmanın hızlı bir yolu. Herhangi bir yorum / öneri bekliyoruz :)


12

Bu, iOS 8 ve üstü için çalışır ve durum çubuğunun hala arka planını korumasını sağlar

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

Durum çubuğuna dokunduğunuzda gezinme çubuğunun gösterilmesini istiyorsanız, bunu yapabilirsiniz:

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

10

İşte benim uygulamam: SherginScrollableNavigationBar .

Benim yaklaşımımda 'ın durumunu KVOgözlemlemek için kullanıyorum UIScrollView, bu nedenle bir temsilci kullanmaya gerek yoktur (ve bu temsilciyi başka ne gerekiyorsa kullanabilirsiniz).


Bilginize, bu her zaman doğru çalışmıyor. Bunu da denedim ve kaydırma görünümünü "zıplamadığınız" sürece işe yarıyor. Sıçrama kısmında KVO tetiklenmemiş gibi görünüyor. Yine de contentOffset için temsilci çağrısı tetiklenir.
Joris Mans

7

Lütfen bu çözümümü deneyin ve bunun neden önceki cevaplar kadar iyi olmadığını bana bildirin.

- (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];
}

1
Buna benzer bir şey yaptım ve bu kolayca en iyi çözüm. Birkaç hack ve kitaplık denedim ve bu, tüm ekranı kapsamayan bir tableView ile iOS 9 için çalışan tek kitaptır. Kudos!
skensell

6

Bunu başarmanın bir yolu şudur.

Örneğin UIScrollViewDelegatesizin UITableViewiçin görünüm denetleyicinizi kaydedin .

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

UIScrollViewDelegateYöntemlerin içinden yeni contentOffset'i alabilir ve UINavigationBarbuna göre yukarı veya aşağı çevirebilirsiniz .

Alt görünümlerin alfa ayarı, ayarlayabileceğiniz ve hesaplayabileceğiniz bazı eşik değerlerine ve faktörlere dayalı olarak da yapılabilir.

Umarım yardımcı olur!



Teşekkürler Diana! UIScrollViewDelegate yöntemlerini uygulamam gerekebileceğinden şüphelenmiştim, ancak biraz fazla olabilir gibi görünüyordu. Bu şeyi çözdüğümde onu göndereceğim. Şerefe!
El Mocoso

4

Iwburk'ün yanıtına ek olarak, özel olmayan gezinme çubuklarındaki alfa sorununu düzeltmek ve gezinme çubuğunu viewWillDisappear yönteminde sıfırlamak için aşağıdakileri ekledim:

- (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];
}

Alt görünümler arasında döngü yapmaktan başka bir yol var mı?
thisiscrazy4

Özel olmayan bir gezinme çubuğunda söyleyebileceğim kadarıyla toplam 4 alt görünüm var: _UINavigationBarBackground, UINavigationItemView, UINavigationItemButtonView ve _UINavigationBarBackIndicatorView. Döngü oldukça hızlı ve uygulamamın herhangi bir performansını etkilemiyor gibi görünüyor.
blueice

_UINavigationBarBackground her zaman ilk alt görünüm gibi göründüğünden, geri kalanına doğrudan erişebilirsiniz: ((UIView *) self.navigationController.navigationBar.subviews [1]). Alpha = alpha;
blueice

4

Herhangi bir tarza ve herhangi bir davranışa izin veren bir çözüm arıyordum. Çubuk yoğunlaşma davranışının birçok farklı uygulamada farklı olduğunu fark edeceksiniz. Ve elbette, çubuğun görünüşü uygulamalar arasında tamamen farklıdır.

Bu sorun için https://github.com/bryankeller/BLKF ElasticHeightBar/ ile bir çözüm oluşturdum

Çubuğun nasıl ve ne zaman küçüldüğünü ve büyüdüğünü kontrol etmek için kendi davranış kurallarınızı tanımlayabilir ve çubuğun alt görünümlerinin çubuğun yoğunlaşmasına veya büyümesine nasıl tepki vermesini istediğinizi tam olarak tanımlayabilirsiniz.

Aklınıza gelen her türlü başlık çubuğunu oluşturmak için çok fazla esneklik istiyorsanız projeme bir göz atın.


Bu customHeaderView'e, yukarı kaydırdığımda gizlenecek bir butonu nasıl ekleyebilirim. Statik butona ihtiyacım yok Mümkün mü? Alt görünüm olarak bir buton oluşturmayı denedim, ancak herhangi bir dokunuş almıyor.
abhimuralidharan

3

Bir UITableView hakkında oturan özelleştirilmiş bir başlığa ihtiyaç duyduğum bir durumda bu davranışı taklit etmeye çalışıyordum. Kendi "gezinti" çubuğumu aldım çünkü bu, sayfadaki diğer birçok şeyin altında yer alıyor ve bölüm başlıklarının varsayılan "yerleştirme" davranışını izlemesini istedim. Facebook / Instagram / Chrome / vb'de görülene benzer bir tarzda başka bir nesne ile birlikte bir UITableView / UIScrollView ayarlamanın oldukça zekice ve özlü bir yolunu bulduğumu düşünüyorum. Uygulamaların.

.Xib dosyamda, bileşenlerim serbest biçimli bir görünüme yükledim: http://imgur.com/0z9yebJ (üzgünüm, satır içi görüntülerin temsilcisi yok)

Sol kenar çubuğunda tablonun ana başlık görünümünün arkasında sıralandığına dikkat edin. Ekran görüntüsünden ayırt edemezsiniz, ancak aynı zamanda ana başlık görünümüyle aynı y konumuna sahiptir. Görüş alanı dışında genişlediğinden, UITableView üzerindeki contentInset özelliği 76 (ana başlık görünümünün yüksekliği) olarak ayarlandı.

Ana başlık görünümünün UIScrollView ile birlikte yukarı kaymasını sağlamak için, UIScrollViewDelegate'in scrollViewDidScroll yöntemlerini bazı hesaplamalar yapmak ve UIScrollView'un contentInset'ini ve ana başlık görünümünün çerçevesini değiştirmek için kullanıyorum.

- (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);
    }
}

İlk if ifadesi zor işin çoğunu yapar, ancak kullanıcının zorla sürüklediği ve scrollViewDidScroll'a gönderilen ilk contentOffset değerlerinin ilk if ifadesinin aralığının dışında olduğu durumları işlemek için diğer ikisini de dahil etmek zorunda kaldım .

Sonuçta, bu benim için gerçekten iyi çalışıyor. Projelerimi bir grup şişirilmiş alt sınıfla yüklemekten nefret ediyorum. Bunun performans açısından en iyi çözüm olup olmadığı konusunda konuşamıyorum (her zaman çağrıldığından beri scrollViewDidScroll'a herhangi bir kod koymakta tereddüt ettim), ancak kod ayak izi, gördüğüm en küçük çözüm. Bu sorun için bir çözüm ve bir UIScrollView'da bir UITableView yerleştirmeyi içermez (Apple, belgelerde buna karşı tavsiyede bulunur ve dokunma olayları UITableView'da biraz korkaktır). Umarım bu birine yardımcı olur!



2

GTScrollNavigationBar'ı uygulamayı denedim, ancak uygulamam otomatik düzen kısıtlamalarını değiştirmemi gerektirdi. Başka birinin bunu otomatik mizanpajla yapması gerekmesi ihtimaline karşı uygulamamın bir örneğini GitHub'a koymaya karar verdim. Diğer uygulamaların çoğunda yaşadığım diğer bir sorun da, kaydırma görünümünün boyutunu aynı anda kaydırıp ayarlarken oluşturduğunuz paralaks kaydırma efektinden kaçınmak için insanların kaydırma görünümünün sınırlarını ayarlamamasıdır.

Bunu otomatik düzen ile yapmanız gerekiyorsa JSCollapsingNavBarViewController'a göz atın . İki sürüm ekledim, biri yalnızca gezinme çubuğuyla, diğeri gezinme çubuğunun altında gezinme çubuğunu daraltmadan önce çöken bir alt çubuğa sahip.


1

Bu şekilde denedim, umarım yardımcı olur. sadece kodu temsilci yönteminde uygulayın ve istenen görünüme / alt görünüme ayarlayın

-(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
                }
        }

1

@Iwburk yanıtının bir uzantısı ... Gezinme çubuğunun kaynağını değiştirmek yerine, gezinme çubuğunun boyutunu genişletmem / küçültmem gerekiyordu.

- (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;
}

stoppedScrollingHenüz yöntemle çalışmıyor , elime geçtiğinde bir güncelleme gönderiyorum


0

Tüm bu yaklaşımlar aşırı derecede karmaşık görünüyor ... Bu yüzden doğal olarak kendiminkini oluşturdum:

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
    }

}

navigationBar.height? scrollView.height? Mülkte bir uzantı kullanıyor musunuz frame?
Ely

0

Objective-C'de verilen tüm cevapları buldum. Bu benim Swift 3'teki cevabım. Bu çok genel bir koddur ve doğrudan kullanılabilir. Hem UIScrollView hem de UITableView ile çalışır.

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
    }
}

Alfa'yı gezinme öğelerine ayarlama mantığı @ WayneBurkett yanıtından kopyalanır ve Swift 3'te yeniden yazılır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.