it-swarm.dev

Bir UITableView bir tabloHeaderView nasıl yeniden boyutlandırılır?

Bir tableHeaderView'ü yeniden boyutlandırmada sorun yaşıyorum. Bu basit çalışmıyor.

1) Bir UITableView ve UIView oluşturun (100 x 320 piksel);

2) UIView'ı UITableView'ın tableHeaderView olarak ayarlayın;

3) Yap ve Git. Her şey yolunda.

Şimdi tableHeaderView'ü yeniden boyutlandırmak istiyorum, bu yüzden viewDidLoad içine bu kodu ekliyorum:

self.tableView.autoresizesSubviews = YES;

self.tableView.tableHeaderView = myHeaderView;
self.tableView.tableFooterView = myFooterView;

CGRect newFrame = self.tableView.tableHeaderView.frame;
newFrame.size.height = newFrame.size.height + 100;
self.tableView.tableHeaderView.frame = newFrame;

TableHeaderView'ın yüksekliği 200 ile, ancak 100 ile görünmelidir.

Eğer yazarsam:

self.tableView.autoresizesSubviews = YES;


CGRect newFrame = myHeaderView.frame;
newFrame.size.height = newFrame.size.height + 100;
myHeaderView.frame = newFrame;


self.tableView.tableHeaderView = myHeaderView;
self.tableView.tableFooterView = myFooterView;

Sonra istediğim gibi, yüksekliği 200 ile başlar. Ancak çalışma zamanında bunu değiştirebilmek istiyorum.

Bunu da başardım, denedim:

self.tableView.autoresizesSubviews = YES;

self.tableView.tableHeaderView = myHeaderView;
self.tableView.tableFooterView = myFooterView;

CGRect newFrame = self.tableView.tableHeaderView.frame;
newFrame.size.height = newFrame.size.height + 100;
self.tableView.tableHeaderView.frame = newFrame;

[self.tableView.tableHeaderView setNeedsLayout];
[self.tableView.tableHeaderView setNeedsDisplay];
[self.tableView setNeedsLayout];
[self.tableView setNeedsDisplay];

Buradaki nokta şudur: Çalışma zamanında tableHeaderView öğesini nasıl yeniden boyutlandırabiliriz ???

Bunu yapabilen var mı?

Teşekkürler

ime

96
iMe

Bilginize: Bunu tabloHeaderView değiştirerek ve yeniden ayarlayarak çalışmak için aldım. Bu durumda, UIWebView alt görünümü yüklemesi tamamlandığında tableHeaderView boyutunu ayarlıyorum.

[webView sizeToFit];
CGRect newFrame = headerView.frame;
newFrame.size.height = newFrame.size.height + webView.frame.size.height;
headerView.frame = newFrame;
[self.tableView setTableHeaderView:headerView];
179
kubi

Bu cevap eski ve görünüşe göre iOS 7 ve üzeri için çalışmıyor.

Aynı problemle karşılaştım ve değişikliklerin canlandırılmasını da istedim, bu yüzden başlık görünümüm için bir UIView alt sınıfı hazırladım ve şu yöntemleri ekledim:

- (void)adjustTableHeaderHeight:(NSUInteger)newHeight{
    NSUInteger oldHeight = self.frame.size.height;
    NSInteger originChange = oldHeight - newHeight;

    [UIView beginAnimations:nil context:nil];

    [UIView setAnimationDuration:1.0f];
    [UIView setAnimationDelegate:self];
    [UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)];

    self.frame = CGRectMake(self.frame.Origin.x, 
                        self.frame.Origin.y, 
                        self.frame.size.width, 
                        newHeight);

    for (UIView *view in [(UITableView *)self.superview subviews]) {
        if ([view isKindOfClass:[self class]]) {
            continue;
        }
        view.frame = CGRectMake(view.frame.Origin.x, 
                            view.frame.Origin.y - originChange, 
                            view.frame.size.width, 
                            view.frame.size.height);
    }

    [UIView commitAnimations];
}

- (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context{
    [(UITableView *)self.superview setTableHeaderView:self];
}

Bu, esas olarak, çağıran sınıfla aynı sınıf türü olmayan UITableView öğesinin tüm alt görünümlerini canlandırır. Animasyonun sonunda, denetimdeki setTableHeaderView öğesini çağırır (UITableView) - bu olmadan UITableView içeriği, kullanıcı bir sonraki kaydırma işleminde geri atlayacaktır. Bu konuda şu ana kadar bulduğum tek sınırlama, kullanıcı, animasyon gerçekleşirken UITableView’i kaydırmaya çalışırsa, kaydırma, başlık görünümü yeniden boyutlandırılmamış gibi animasyon uygulanacak hızlı).

12
garrettmoon

Değişiklikleri koşullu olarak uygulamak istiyorsanız, aşağıdakileri yapabilirsiniz:

- (void) showHeader:(BOOL)show animated:(BOOL)animated{

    CGRect closedFrame = CGRectMake(0, 0, self.view.frame.size.width, 0);
    CGRect newFrame = show?self.initialFrame:closedFrame;

    if(animated){
        // The UIView animation block handles the animation of our header view
        [UIView beginAnimations:nil context:nil];
        [UIView setAnimationDuration:0.3];
        [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];

        // beginUpdates and endUpdates trigger the animation of our cells
        [self.tableView beginUpdates];
    }

    self.headerView.frame = newFrame;
    [self.tableView setTableHeaderView:self.headerView];

    if(animated){
        [self.tableView endUpdates];
        [UIView commitAnimations];
    }
}

Lütfen animasyonun iki katlı olduğunu unutmayın: 

  1. tableHeaderView altındaki hücrelerin animasyonu. Bu beginUpdates ve endUpdates kullanılarak yapılır
  2. Gerçek başlık görünümünün animasyonu. Bu UIView bir animasyon bloğu kullanılarak yapılır. 

Bu iki animasyonu senkronize etmek için animationCurve, UIViewAnimationCurveEaseInOut olarak ve 0.3 olarak ayarlanmalıdır; bu, UITableView'ın animasyon için kullandığı gibi görünüyor.

Güncelleştirme

Bunu yapan gihub'da bir Xcode projesi hazırladım . besi/ios-quickies içindeki ResizeTableHeaderViewAnimated projesini gözden geçirin.

screenshot

10
Besi

Sanırım myHeaderView'ın yüksekliğini sadece şöyle ayarladıysanız çalışması gerekir:

CGRect newFrame = myHeaderView.frame;
newFrame.size.height = newFrame.size.height + 100;
myHeaderView.frame = newFrame;

self.tableView.tableHeaderView = myHeaderView;
8
Greg Martin

İOS 7'ye kadar @ @ garrettmoon çözümü kullanıldı.
İşte @ garrettmoon'a dayanan güncellenmiş bir çözüm:

- (void)adjustTableHeaderHeight:(NSUInteger)newHeight animated:(BOOL)animated {

    [UIView beginAnimations:nil context:nil];

    [UIView setAnimationDuration:[CATransaction animationDuration]];
    [UIView setAnimationDelegate:self];
    [UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)];

    self.frame = CGRectMake(self.frame.Origin.x,
                        self.frame.Origin.y,
                        self.frame.size.width,
                        newHeight);

    [(UITableView *)self.superview setTableHeaderView:self];

    [UIView commitAnimations];
}

- (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context{
    [(UITableView *)self.superview setTableHeaderView:self];
}
6
avishic

Bu benim için iOS 7 ve 8'de çalıştı. Bu kod tablo görünümü denetleyicisinde çalışıyor.

[UIView animateWithDuration:0.3 animations:^{
    CGRect oldFrame = self.headerView.frame;
    self.headerView.frame = CGRectMake(oldFrame.Origin.x, oldFrame.Origin.y, oldFrame.size.width, newHeight);
    [self.tableView setTableHeaderView:self.headerView];
}];
5
Darcy Rayner

Çünkü tableHeaderView ayarlayıcısı.

TableHeaderView'ı ayarlamadan önce UIView yüksekliğini ayarlamanız gerekir. (Apple bu çerçeveyi açarsa çok daha kolay olurdu ...) 

4
Thomas Decaux

İOS 9 ve altındaki sürümlerde tableHeaderView, yeniden boyutlandırdıktan sonra yeniden yerleştirilmez.

Bu sorunu çözmek için, sadece aşağıdaki kodla yapın:

self.tableView.tableHeaderView = self.tableView.tableHeaderView;
3
klaudz

İOS 9.x'te, bunu viewDidLoad üzerinde yapmak gayet iyi çalışır:

var frame = headerView.frame
frame.size.height = 11  // New size
headerView.frame = frame

headerView, @IBOutlet var headerView: UIView! olarak bildirilir ve tableHeaderView işlevi görmek için tableView öğesinin üstüne yerleştirildiği storyboard'a bağlanır.

2
Eneko Alonso

Başlık görünümü özelliği için height öğelerini viewDidLoad içinde tableView.tableHeaderView olarak ayarlamak işe yaramaz, başlık görünümü yüksekliği yine de beklendiği gibi değişmez.

Bu deneye karşı mücadele ettikten sonra birçok denemeler için. Bulunduğum gibi, yüksekliği görüntülemek için - (void)didMoveToParentViewController:(UIViewController *)parent yöntemini kullanarak mantık oluştur başlıklarını çağırmak suretiyle değiştirebilirsiniz.

Böylece örnek kod şöyle görünür:

- (void)didMoveToParentViewController:(UIViewController *)parent {
    [super didMoveToParentViewController:parent];

    if ( _tableView.tableHeaderView == nil ) {
        UIView *header = [[[UINib nibWithNibName:@"your header view" bundle:nil] instantiateWithOwner:self options:nil] firstObject];

        header.frame = CGRectMake(0, 0, CGRectGetWidth([UIScreen mainScreen].bounds), HeaderViewHeight);

        [_tableView setTableHeaderView:header];
    }
}
1
Enix

Açıkçası, Apple şimdiye kadar tableHeaderView & tableFooterView için UITableViewAutomaticDimension uygulamış olmalı ...

Aşağıdaki, düzen kısıtlamalarını kullanarak benim için çalışıyor gibi görünüyor:

CGSize   s  = [ self  systemLayoutSizeFittingSize : UILayoutFittingCompressedSize ];
CGRect   f  = [ self  frame ];

f.size   = s;

[ self  setFrame : f ];
0
digitaldaemon

Bu sadece otomatik yerleşimi kullandığınızda ve translatesAutoresizingMaskIntoConstraints = false öğesini özel bir başlık görünümüne ayarladığınızda içindir.

En iyi ve en basit yol intrinsicContentSize işlevini geçersiz kılmaktır. Dahili olarak UITableView, üstbilgi/altbilgi boyutuna karar vermek için intrinsicContentSize öğesini kullanır. Özel görünümünüzde intrinsicContentSize öğesini geçersiz kıldığınızda, yapmanız gerekenler aşağıdaki gibidir

  1. Özel üstbilgi/altbilgi görünümünün düzenini (alt görünümler) yapılandırın
  2. invalidateIntrinsicContentSize() çağırmak
  3. tableView.setNeedsLayout() ve tableView.layoutIfNeeded() işlevlerini çağır

Daha sonra UITableView 'başlığı/altbilgisi istediğiniz gibi güncellenecektir. Görünümü sıfırlamaya veya sıfırlamaya gerek yoktur.

UITableView.tableHeaderView veya .tableFooterView için gerçekten ilginç olan şey, UIStackView'ın arrangedSubviews işlevini yönetme yeteneğini kaybetmesidir. UIStackView öğesini tableHeaderView veya tableFooterView olarak kullanmak istiyorsanız, stackView öğesini bir UIView içine gömmeniz ve UIView 'ın intrinsicContentSize değerini geçersiz kılmanız gerekir.

0
Ryan

TableHeaderView'ınız içerik ayarlı bir webView ise, deneyebilirsiniz:

[self.webView.scrollView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionNew context:nil];

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
    self.webView.height = self.webView.scrollView.contentSize.height;
    self.tableView.tableHeaderView = self.webView;
}

İOS9 ve iOS11 üzerinde test ettim, iyi çalıştım.

0
无夜之星辰

Bir UIView'un initWithFrame başlatıcısını, geçtiğim rektifi tam olarak onurlandırmadı.

 - (id)initWithFrame:(CGRect)aRect {

    CGRect frame = [[UIScreen mainScreen] applicationFrame];

    if ((self = [super initWithFrame:CGRectZero])) {

        // Ugly initialization behavior - initWithFrame will not properly honor the frame we pass
        self.frame = CGRectMake(0, 0, frame.size.width, 200);

        // ...
    }
}

Bunun avantajı, görünüm kodunuza daha iyi yerleştirilmiş olmasıdır.

0
Harald Schubert

UITableView yeniden boyutlandırma başlığı - Scope Bar ile UISearchBar

Masaya başlık olarak UITableView__ olan bir UISearchBar istedim, böylece böyle bir hiyerarşiye sahibim.

UITableView
  |
  |--> UIView
  |     |--> UISearchBar
  |
  |--> UITableViewCells

UISearchBarDelegate yöntemleri

Başka bir yerde belirtildiği gibi, değiştirdikten sonraTableViewHeader'ı ayarlamazsanız hiçbir şey olmaz.

- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar
{
    searchBar.showsScopeBar = YES;
    [UIView animateWithDuration:0.2f animations:^{
        [searchBar sizeToFit];
        CGFloat height = CGRectGetHeight(searchBar.frame);

        CGRect frame = self.tableView.tableHeaderView.frame;
        frame.size.height = height;
        self.tableHeaderView.frame = frame;
        self.tableView.tableHeaderView = self.tableHeaderView;
    }];

    [searchBar setShowsCancelButton:YES animated:YES];
    return YES;
}

- (BOOL)searchBarShouldEndEditing:(UISearchBar *)searchBar
{
    searchBar.showsScopeBar = NO;
    [UIView animateWithDuration:0.f animations:^{
        [searchBar sizeToFit];

        CGFloat height = CGRectGetHeight(searchBar.frame);

        CGRect frame = self.tableView.tableHeaderView.frame;
        frame.size.height = height;
        self.tableHeaderView.frame = frame;
        self.tableView.tableHeaderView = self.tableHeaderView;
    }];

    [searchBar setShowsCancelButton:NO animated:YES];
    return YES;
}

Dokunduğunuzda genel ekrana genişlemek için tablonun başlığının animasyonlu yükseklik değişikliğini uyguladım. Ancak, kod başka durumlarda yardımcı olabilir:

// Swift
@IBAction func tapped(sender: UITapGestureRecognizer) {

    self.tableView.beginUpdates()       // Required to update cells. 

    // Collapse table header to original height
    if isHeaderExpandedToFullScreen {   

        UIView.animateWithDuration(0.5, animations: { () -> Void in
            self.scrollView.frame.size.height = 110   // original height in my case is 110
        })

    }
    // Expand table header to overall screen            
    else {      
        let screenSize = self.view.frame           // "screen" size

        UIView.animateWithDuration(0.5, animations: { () -> Void in
            self.scrollView.frame.size.height = screenSize.height
        })
    }

    self.tableView.endUpdates()  // Required to update cells. 

    isHeaderExpandedToFullScreen= !isHeaderExpandedToFullScreen  // Toggle
}
0
Alexander Volkov

Özel headerView, autolayout kullanılarak tasarlandıysa ve headerView, web getirme veya benzer tembel görevlerden sonra güncellenmelidir, Sonra iOS-Swift 'de, bunu yaptım ve headerView'üm aşağıdaki kod kullanılarak güncellenir:

//to reload your cell data
self.tableView.reloadData()
dispatch_async(dispatch_get_main_queue(),{
// this is needed to update a specific tableview's headerview layout on main queue otherwise it's won't update perfectly cause reloaddata() is called
  self.tableView.beginUpdates()
  self.tableView.endUpdates()
} 
0