İOS'ta UITableView'da bölümü genişlet / daralt


Yanıtlar:


109

Kendi özel başlık satırınızı oluşturmalı ve bunu her bölümün ilk satırı olarak koymalısınız. UITableViewZaten var olan veya başlıkları alt sınıflara ayırmak bir acı olacaktır. Şu anki çalışma şekillerine bakılırsa, onlardan kolayca aksiyon alabileceğinizden emin değilim. Bir hücreyi başlık gibi BAKACAKTIR vetableView:didSelectRowAtIndexPath bulunduğu bölümü manuel olarak genişletmek veya daraltmak için ayarlayabilirsiniz.

Bölümlerinizin her birinin "genişletilmiş" değerine karşılık gelen bir boole dizisi saklarım. Ardından tableView:didSelectRowAtIndexPath, özel başlık satırlarınızın her birinde bu değeri değiştirebilir ve ardından bu belirli bölümü yeniden yükleyebilirsiniz.

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    if (indexPath.row == 0) {
        ///it's the first row of any section so it would be your custom section header

        ///put in your code to toggle your boolean value here
        mybooleans[indexPath.section] = !mybooleans[indexPath.section];

        ///reload this section
        [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:indexPath.section] withRowAnimation:UITableViewRowAnimationFade];
    }
}

Ardından numberOfRowsInSection, mybooleansdeğeri kontrol etmeye ve bölüm genişletilmemişse 1 veya genişletilmişse bölümdeki öğe sayısını 1'den fazla döndürmeye ayarlayın .

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

    if (mybooleans[section]) {
        ///we want the number of people plus the header cell
        return [self numberOfPeopleInGroup:section] + 1;
    } else {
        ///we just want the header cell
        return 1;
    }
}

Ayrıca, cellForRowAtIndexPathherhangi bir bölümdeki ilk satır için özel bir başlık hücresi döndürmek için güncellemeniz gerekecektir .


2
Beejive uygulamasını kullandıysanız, tıpkı normal Apple bölüm başlıklarında olduğu gibi, katlanabilir bölüm başlıklarının, bölümünün bir bölümünde gezinirken bile tablonun üst kısmında "yüzdüğünü" bilirsiniz. bölümün başına bir hücre eklerseniz bu mümkün değildir
user102008

Güzel ve zarif bir çözüm! user102008, kayan başlık üzerinde bir noktaya sahiptir, ancak aslında "bölümlerin" kaydırılmasını istediğiniz senaryoda, bu harika bir yaklaşımdır.
Nick Cipollina

@mjdth plz bana herhangi bir örnek kodu verin bcz belirli bir hücreye ihtiyacım var gizle / göster ... şimdiden teşekkürler
Bajaj

11
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section"kendi özel başlığınızı" sağlamanın daha iyi bir yoludur, çünkü tam olarak bunu yapmak için tasarlanmıştır.
William Denniss

Bu, başlangıçta sadece bir bölümüm olduğunda benim için çalıştı, ancak daha fazlasına sahip olduğumda, "geçersiz güncelleme geçersiz satır sayısı" hatası alıyorum. bu çözümün daha eski olduğunu biliyorum, ancak bu yalnızca bir bölüm için mi işe yarayacak? birden fazla bölümümüz varsa, satırları ekleyen / silen kodu eklememiz gerekecek mi?
skinsfan00atg

103

Bir tablo görünümü bölüm üstbilgisi kullanarak bir genişletme / daraltma eylemini canlandırmak için bazı örnek kod Apple tarafından burada sağlanmıştır: Tablo Görünümü Animasyonları ve Hareketler

Bu yaklaşımın anahtarı - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section, bir düğme içeren (tipik olarak başlık görünümünün kendisiyle aynı boyutta) özel bir UIView uygulamak ve döndürmektir. UIView'ı alt sınıflara ayırarak ve bunu başlık görünümü için kullanarak (bu örnekte olduğu gibi), bölüm numarası gibi ek verileri kolayca depolayabilirsiniz.



hatırlamıyorum ama örnek kod neden iOS 4 öncesi sürümlerde çalışmıyor?
samwize

1
bilmiyorum. sadece "iOS 4.0.2 veya üstü"
yazıyor

1
Bağlantıdaki mevcut güncellenmiş kodun içinde hatalar var ve kolayca
çökebilir

1
Daha önce bahsettiğimiz Ankit Srivastava'nın bu kod örneğini kırmak kolay olduğu gibi: PlaysAndQuotations.plist'teki tüm öğe sözlüklerini kopyalayıp yapıştırın (bunu kök sözlükte 30 girişle test ettim) - Şimdi uygulamayı başlatın ve ilk oynatmayı açın - bundan sonra aşağıyı gösteren bir ok görene kadar aşağı kaydırın (bunun geldiğini düşünüyorum dequeueReusableHeaderFooterViewWithIdentifier) - o oku tıklayın ve ilk oyuna geri dönün ve kapatmayı deneyin -> NSInternalInconsistencyException (iOS 8.4 / iPhone 5s)
Raimund Wege

22

Apple'ın Masa Görünümü Animasyonları ve Hareketlerinden ilham alan güzel bir çözüm buldum . Gereksiz parçaları Apple'ın örneğinden sildim ve hızlıca tercüme ettim.

Cevabın oldukça uzun olduğunu biliyorum, ancak tüm kod gerekli. Neyse ki, kodun çoğunu kopyalayıp yapıştırabilirsiniz ve sadece 1. ve 3. adımlarda biraz değişiklik yapmanız yeterlidir.

1. oluştur SectionHeaderView.swiftveSectionHeaderView.xib

import UIKit

protocol SectionHeaderViewDelegate {
    func sectionHeaderView(sectionHeaderView: SectionHeaderView, sectionOpened: Int)
    func sectionHeaderView(sectionHeaderView: SectionHeaderView, sectionClosed: Int)
}

class SectionHeaderView: UITableViewHeaderFooterView {

    var section: Int?
    @IBOutlet weak var titleLabel: UILabel!
    @IBOutlet weak var disclosureButton: UIButton!
    @IBAction func toggleOpen() {
        self.toggleOpenWithUserAction(true)
    }
    var delegate: SectionHeaderViewDelegate?

    func toggleOpenWithUserAction(userAction: Bool) {
        self.disclosureButton.selected = !self.disclosureButton.selected

        if userAction {
            if self.disclosureButton.selected {
                self.delegate?.sectionHeaderView(self, sectionClosed: self.section!)
            } else {
                self.delegate?.sectionHeaderView(self, sectionOpened: self.section!)
            }
        }
    }

    override func awakeFromNib() {
        var tapGesture: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "toggleOpen")
        self.addGestureRecognizer(tapGesture)
        // change the button image here, you can also set image via IB.
        self.disclosureButton.setImage(UIImage(named: "arrow_up"), forState: UIControlState.Selected)
        self.disclosureButton.setImage(UIImage(named: "arrow_down"), forState: UIControlState.Normal)
    }

}

SectionHeaderView.xib(gri arka plan ile görüntü) (tabii, ihtiyaçlarınıza göre özelleştirebilirsiniz) bir tableview bu gibi görünmelidir: görüntü açıklamasını buraya girin

Not:

a) toggleOpeneylem ile bağlantılı olmalıdırdisclosureButton

b) disclosureButtonvetoggleOpen eylemi gerekli değildir. Düğmeye ihtiyacınız yoksa bu 2 şeyi silebilirsiniz.

2.Create SectionInfo.swift

import UIKit

class SectionInfo: NSObject {
    var open: Bool = true
    var itemsInSection: NSMutableArray = []
    var sectionTitle: String?

    init(itemsInSection: NSMutableArray, sectionTitle: String) {
        self.itemsInSection = itemsInSection
        self.sectionTitle = sectionTitle
    }
}

3. masa görünümünüzde

import UIKit

class TableViewController: UITableViewController, SectionHeaderViewDelegate  {

    let SectionHeaderViewIdentifier = "SectionHeaderViewIdentifier"

    var sectionInfoArray: NSMutableArray = []

    override func viewDidLoad() {
        super.viewDidLoad()

        let sectionHeaderNib: UINib = UINib(nibName: "SectionHeaderView", bundle: nil)
        self.tableView.registerNib(sectionHeaderNib, forHeaderFooterViewReuseIdentifier: SectionHeaderViewIdentifier)

        // you can change section height based on your needs
        self.tableView.sectionHeaderHeight = 30

        // You should set up your SectionInfo here
        var firstSection: SectionInfo = SectionInfo(itemsInSection: ["1"], sectionTitle: "firstSection")
        var secondSection: SectionInfo = SectionInfo(itemsInSection: ["2"], sectionTitle: "secondSection"))
        sectionInfoArray.addObjectsFromArray([firstSection, secondSection])
    }

    // MARK: - Table view data source

    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return sectionInfoArray.count
    }

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if self.sectionInfoArray.count > 0 {
            var sectionInfo: SectionInfo = sectionInfoArray[section] as! SectionInfo
            if sectionInfo.open {
                return sectionInfo.open ? sectionInfo.itemsInSection.count : 0
            }
        }
        return 0
    }

    override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        let sectionHeaderView: SectionHeaderView! = self.tableView.dequeueReusableHeaderFooterViewWithIdentifier(SectionHeaderViewIdentifier) as! SectionHeaderView
        var sectionInfo: SectionInfo = sectionInfoArray[section] as! SectionInfo

        sectionHeaderView.titleLabel.text = sectionInfo.sectionTitle
        sectionHeaderView.section = section
        sectionHeaderView.delegate = self
        let backGroundView = UIView()
        // you can customize the background color of the header here
        backGroundView.backgroundColor = UIColor(red:0.89, green:0.89, blue:0.89, alpha:1)
        sectionHeaderView.backgroundView = backGroundView
        return sectionHeaderView
    }

    func sectionHeaderView(sectionHeaderView: SectionHeaderView, sectionOpened: Int) {
        var sectionInfo: SectionInfo = sectionInfoArray[sectionOpened] as! SectionInfo
        var countOfRowsToInsert = sectionInfo.itemsInSection.count
        sectionInfo.open = true

        var indexPathToInsert: NSMutableArray = NSMutableArray()
        for i in 0..<countOfRowsToInsert {
            indexPathToInsert.addObject(NSIndexPath(forRow: i, inSection: sectionOpened))
        }
        self.tableView.insertRowsAtIndexPaths(indexPathToInsert as [AnyObject], withRowAnimation: .Top)
    }

    func sectionHeaderView(sectionHeaderView: SectionHeaderView, sectionClosed: Int) {
        var sectionInfo: SectionInfo = sectionInfoArray[sectionClosed] as! SectionInfo
        var countOfRowsToDelete = sectionInfo.itemsInSection.count
        sectionInfo.open = false
        if countOfRowsToDelete > 0 {
            var indexPathToDelete: NSMutableArray = NSMutableArray()
            for i in 0..<countOfRowsToDelete {
                indexPathToDelete.addObject(NSIndexPath(forRow: i, inSection: sectionClosed))
            }
            self.tableView.deleteRowsAtIndexPaths(indexPathToDelete as [AnyObject], withRowAnimation: .Top)
        }
    }
}

1
bu konuda çaba gösterdiğiniz için teşekkürler! Github'da küçük bir örnek proje ile daha da iyi bir cevap olabilir
Max MacLeod

Ayrıntılı cevap verdiğiniz için teşekkürler. Örnek proje daha iyi olurdu.
Thiha Aung

20

İOS'ta daraltılabilir tablo bölümünü uygulamak için sihir, her bölüm için satır sayısını nasıl kontrol edeceğimizdir veya her bölüm için satırların yüksekliğini yönetebiliriz.

Ayrıca, tap olayını başlık alanından (ister bir düğme ister tüm başlık olsun) dinleyebilmemiz için bölüm başlığını özelleştirmemiz gerekir.

Başlık ile nasıl başa çıkılır? Çok basit, UITableViewCell sınıfını genişletiyoruz ve aşağıdaki gibi özel bir başlık hücresi oluşturuyoruz:

import UIKit

class CollapsibleTableViewHeader: UITableViewCell {

    @IBOutlet var titleLabel: UILabel!
    @IBOutlet var toggleButton: UIButton!

}

sonra başlık hücresini bağlamak için viewForHeaderInSection'ı kullanın:

override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
  let header = tableView.dequeueReusableCellWithIdentifier("header") as! CollapsibleTableViewHeader

  header.titleLabel.text = sections[section].name
  header.toggleButton.tag = section
  header.toggleButton.addTarget(self, action: #selector(CollapsibleTableViewController.toggleCollapse), forControlEvents: .TouchUpInside)

  header.toggleButton.rotate(sections[section].collapsed! ? 0.0 : CGFloat(M_PI_2))

  return header.contentView
}

Bu işlev bir UIView döndürülmesini beklediği için contentView’i döndürmemiz gerektiğini unutmayın.

Şimdi daraltılabilir kısmı ele alalım, işte her bölümün daraltılabilir pervanesini değiştiren açma / kapatma işlevi:

func toggleCollapse(sender: UIButton) {
  let section = sender.tag
  let collapsed = sections[section].collapsed

  // Toggle collapse
  sections[section].collapsed = !collapsed

  // Reload section
  tableView.reloadSections(NSIndexSet(index: section), withRowAnimation: .Automatic)
}

bölüm verilerini nasıl yönettiğinize bağlıdır, bu durumda bölüm verisine şu şekilde sahibim:

struct Section {
  var name: String!
  var items: [String]!
  var collapsed: Bool!

  init(name: String, items: [String]) {
    self.name = name
    self.items = items
    self.collapsed = false
  }
}

var sections = [Section]()

sections = [
  Section(name: "Mac", items: ["MacBook", "MacBook Air", "MacBook Pro", "iMac", "Mac Pro", "Mac mini", "Accessories", "OS X El Capitan"]),
  Section(name: "iPad", items: ["iPad Pro", "iPad Air 2", "iPad mini 4", "Accessories"]),
  Section(name: "iPhone", items: ["iPhone 6s", "iPhone 6", "iPhone SE", "Accessories"])
]

nihayet, yapmamız gereken şey, her bölümün daraltılabilir payına dayanmak, o bölümün satır sayısını kontrol etmek:

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
  return (sections[section].collapsed!) ? 0 : sections[section].items.count
}

Github'ımda tam olarak çalışan bir demom var: https://github.com/jeantimex/ios-swift-collapsible-table-section

gösteri

Daraltılabilir bölümleri gruplanmış stil bir tabloda uygulamak istiyorsanız, burada kaynak kodlu başka bir demom var: https://github.com/jeantimex/ios-swift-collapsible-table-section-in-grouped-section

Umarım yardımcı olur.


Merhaba, özel başlık bölümümü bir xib dosyasında yaptım ve ucu Table View Controller'ıma kaydettim. Bir bölümü silip tekrar genişletmeyi / daraltmayı denediğimde, dizinin aralık dışı olduğunu söyleyen ölümcül bir hata alıyorum. Bunu düzeltmenin bir yolu var mı? Teşekkürler!
iamhx

çok güzel ve temiz bir çözüm!
Joel

10

Bölüm başlığına bir UIB düğmesi eklemeniz ve bu düğmenin boyutunu bölüm boyutuna eşit ayarlamanız için daha iyi bir çözümüm var, ancak bunu net arka plan rengiyle gizleyin, bundan sonra genişletmek veya daraltmak için hangi bölümün tıklandığını kolayca kontrol edebilirsiniz.


3
Bana göre, bu çözüm kabul edilen cevaptan daha iyi çünkü anlamsal olarak başlığınızı bir başlık olarak tutuyorsunuz ve bir başlığı simüle etmek için sahte bir satır kullanmıyorsunuz. Yönteme tableView:numberOfRowsInSection:dokunulmayacak ve onu gerçekten ne anlama geldiği için kullanmaya devam edeceksiniz. Aynısı için de geçerli tableView:cellForRowAtIndexPath:.
Cœur

O halde, bölüm başlığındaki butona dokunuyorsunuz, ancak hangi bölümün yeniden yüklenmesi gerektiğini nasıl belirleyeceksiniz?
memmons

@Answerbot Merhaba, Bölüm indeksi ile aynı değeri kullanarak buton için etiket ayarlayarak son derece kolaydır.
Son Nguyen

Bunu söyleyeceğinden korktum. TableView dizinleri gibi şeyler için tag özelliğinin kötüye kullanılması, kötü bir tasarım seçimidir.
memmons

Soruna "harika" bir çözüm hiç görmedim, bu yüzden farklı bir yaklaşımınız olduğunu umuyordum. Gördüğüm en iyi cevap Apple referans projesidir. Apple a alt sınıfları oluşturur UITableViewHeaderFooterViewve bir sectionözellik ekler SectionHeaderViewDelegateve bölümü açmak / kapatmak için geri aramayı sağlayan a'yı tanımlar . ( developer.apple.com/library/ios/samplecode/TableViewUpdates/… )
memmons

7

Sonunda bir düğme içeren bir headerView oluşturdum ( aslında yukarıda Son Nguyen'ın çözümünü gördüm , ancak benim kodum bu .. çok görünüyor ama oldukça basit):

bölümler için birkaç sevinç ilan ediyorum

bool customerIsCollapsed = NO;
bool siteIsCollapsed = NO;

... kod

şimdi tablo görünümünüzde delege yöntemleri ...

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, _tblSearchResults.frame.size.width, 35)];

    UILabel *lblSection = [UILabel new];
    [lblSection setFrame:CGRectMake(0, 0, 300, 30)];
    [lblSection setFont:[UIFont fontWithName:@"Helvetica-Bold" size:17]];
    [lblSection setBackgroundColor:[UIColor clearColor]];
    lblSection.alpha = 0.5;
    if(section == 0)
    {
        if(!customerIsCollapsed)
            [lblSection setText:@"Customers    --touch to show--"];
        else
            [lblSection setText:@"Customers    --touch to hide--"];
    }
    else
    {
        if(!siteIsCollapsed)
            [lblSection setText:@"Sites    --touch to show--"];
        else
            [lblSection setText:@"Sites    --touch to hide--"];    }

    UIButton *btnCollapse = [UIButton buttonWithType:UIButtonTypeCustom];
    [btnCollapse setFrame:CGRectMake(0, 0, _tblSearchResults.frame.size.width, 35)];
    [btnCollapse setBackgroundColor:[UIColor clearColor]];
    [btnCollapse addTarget:self action:@selector(touchedSection:) forControlEvents:UIControlEventTouchUpInside];
    btnCollapse.tag = section;


    [headerView addSubview:lblSection];
    [headerView addSubview:btnCollapse];

    return headerView;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // Return the number of rows in the section.
    if(section == 0)
    {
        if(customerIsCollapsed)
            return 0;
        else
            return _customerArray.count;
    }
    else if (section == 1)
    {
        if(siteIsCollapsed)
            return 0;
        else
        return _siteArray.count;

    }
    return 0;
}

ve son olarak, bölüm başlık düğmelerinden birine dokunduğunuzda çağrılan işlev:

- (IBAction)touchedSection:(id)sender
{
    UIButton *btnSection = (UIButton *)sender;

    if(btnSection.tag == 0)
    {
        NSLog(@"Touched Customers header");
        if(!customerIsCollapsed)
            customerIsCollapsed = YES;
        else
            customerIsCollapsed = NO;

    }
    else if(btnSection.tag == 1)
    {
        NSLog(@"Touched Site header");
        if(!siteIsCollapsed)
            siteIsCollapsed = YES;
        else
            siteIsCollapsed = NO;

    }
    [_tblSearchResults reloadData];
}

Merak ediyordum da, bölüm daralır ve animasyonlu mu yoksa animasyonsuz mu genişler? Animasyon olmadan çok kötü görünecek. ona nasıl animasyon ekleyebiliriz?
Sam

@Sam [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationFade];, daraltma / çözme yönteminde olduğu gibi bir şey kullanırsanız , güzelce hareket etmelidir.
William Denniss

5

Genişletilebilir tablo görünümü hücreleri oluşturmanın en iyi yolu bu

.h dosyası

  NSMutableIndexSet *expandedSections;

.m dosyası

if (!expandedSections)
    {
        expandedSections = [[NSMutableIndexSet alloc] init];
    }
   UITableView *masterTable = [[UITableView alloc] initWithFrame:CGRectMake(0,100,1024,648) style:UITableViewStyleGrouped];
    masterTable.delegate = self;
    masterTable.dataSource = self;
    [self.view addSubview:masterTable];

Tablo görünümü temsilci yöntemleri

- (BOOL)tableView:(UITableView *)tableView canCollapseSection:(NSInteger)section
{
    // if (section>0) return YES;

    return YES;
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    // Return the number of sections.
    return 4;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    if ([self tableView:tableView canCollapseSection:section])
    {
        if ([expandedSections containsIndex:section])
        {
            return 5; // return rows when expanded
        }

        return 1; // only top row showing
    }

    // Return the number of rows in the section.
    return 1;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] ;
    }

    // Configure the cell...

    if ([self tableView:tableView canCollapseSection:indexPath.section])
    {
        if (!indexPath.row)
        {
            // first row
            cell.textLabel.text = @"Expandable"; // only top row showing

            if ([expandedSections containsIndex:indexPath.section])
            {

                UIImageView *imView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"UITableContract"]];
                cell.accessoryView = imView;
            }
            else
            {

                UIImageView *imView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"UITableExpand"]];
                cell.accessoryView = imView;
            }
        }
        else
        {
            // all other rows
            if (indexPath.section == 0) {
                cell.textLabel.text = @"section one";
            }else if (indexPath.section == 1) {
                cell.textLabel.text = @"section 2";
            }else if (indexPath.section == 2) {
                cell.textLabel.text = @"3";
            }else {
                cell.textLabel.text = @"some other sections";
            }

            cell.accessoryView = nil;
            cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
        }
    }
    else
    {
        cell.accessoryView = nil;
        cell.textLabel.text = @"Normal Cell";

    }

    return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    if ([self tableView:tableView canCollapseSection:indexPath.section])
    {
        if (!indexPath.row)
        {
            // only first row toggles exapand/collapse
            [tableView deselectRowAtIndexPath:indexPath animated:YES];

            NSInteger section = indexPath.section;
            BOOL currentlyExpanded = [expandedSections containsIndex:section];
            NSInteger rows;


            NSMutableArray *tmpArray = [NSMutableArray array];

            if (currentlyExpanded)
            {
                rows = [self tableView:tableView numberOfRowsInSection:section];
                [expandedSections removeIndex:section];

            }
            else
            {
                [expandedSections addIndex:section];
                rows = [self tableView:tableView numberOfRowsInSection:section];
            }


            for (int i=1; i<rows; i++)
            {
                NSIndexPath *tmpIndexPath = [NSIndexPath indexPathForRow:i 
                                                               inSection:section];
                [tmpArray addObject:tmpIndexPath];
            }

            UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];

            if (currentlyExpanded)
            {
                [tableView deleteRowsAtIndexPaths:tmpArray 
                                 withRowAnimation:UITableViewRowAnimationTop];

                UIImageView *imView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"UITableExpand"]];
                cell.accessoryView = imView;
            }
            else
            {
                [tableView insertRowsAtIndexPaths:tmpArray 
                                 withRowAnimation:UITableViewRowAnimationTop];

                UIImageView *imView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"UITableContract"]];
                cell.accessoryView = imView;
            }
        }
    }

    NSLog(@"section :%d,row:%d",indexPath.section,indexPath.row);

}

8
Muhtemelen soruları, hepsinde aynı cevabı spamlamak yerine, aynen kopya olarak işaretlemelisiniz.
casperOne

bir bölüm zaten genişletilmişse ve başka bir bölüm tıklanmışsa, hata verir
shivam

merhaba efendim, Seçilen indeks yüksekliği nasıl değiştirilir? heightForRowAtIndexPath kodunuzla nasıl çalışılır?
Gami Nilesh

merhaba efendim, genişletilmiş satırdan seçilen başka bir görünüm denetleyicisine nasıl gidilir?
Arbaz Shaikh

1

Bu nedenle, 'başlıktaki düğme' çözümüne dayalı olarak, işte temiz ve minimalist bir uygulama:

  • bir mülkteki daraltılmış (veya genişletilmiş) bölümleri takip edersiniz
  • düğmeyi bölüm dizini ile etiketlersiniz
  • ok yönünü değiştirmek için bu düğmede seçili bir durumu ayarlarsınız (△ ve ▽ gibi)

İşte kod:

@interface MyTableViewController ()
@property (nonatomic, strong) NSMutableIndexSet *collapsedSections;
@end

...

@implementation MyTableViewController

- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (!self)
        return;
    self.collapsedSections = [NSMutableIndexSet indexSet];
    return self;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // if section is collapsed
    if ([self.collapsedSections containsIndex:section])
        return 0;

    // if section is expanded
#warning incomplete implementation
    return [super tableView:tableView numberOfRowsInSection:section];
}

- (IBAction)toggleSectionHeader:(UIView *)sender
{
    UITableView *tableView = self.tableView;
    NSInteger section = sender.tag;

    MyTableViewHeaderFooterView *headerView = (MyTableViewHeaderFooterView *)[self tableView:tableView viewForHeaderInSection:section];

    if ([self.collapsedSections containsIndex:section])
    {
        // section is collapsed
        headerView.button.selected = YES;
        [self.collapsedSections removeIndex:section];
    }
    else
    {
        // section is expanded
        headerView.button.selected = NO;
        [self.collapsedSections addIndex:section];
    }

    [tableView beginUpdates];
    [tableView reloadSections:[NSIndexSet indexSetWithIndex:section] withRowAnimation:UITableViewRowAnimationAutomatic];
    [tableView endUpdates];
}

@end

1

Bu sorunu çözmenin nispeten basit bir yolunu buldum. Bu yöntemi kullanarak, neredeyse her zaman veri dizisi indeksi ile ilgili olan hücremizi değiştirmemize gerek kalmayacaktır, bu da potansiyel olarak görünüm denetleyicimizde karışıklığa neden olur.

İlk olarak, aşağıdaki özellikleri denetleyici sınıfımıza ekliyoruz:

@property (strong, nonatomic) NSMutableArray* collapsedSections;
@property (strong, nonatomic) NSMutableArray* sectionViews;

collapsedSectionsdaraltılmış bölüm numaralarını kaydedecek. sectionViewsözel bölüm görünümümüzü saklayacak.

Sentezleyin:

@synthesize collapsedSections;
@synthesize sectionViews;

Başlatın:

- (void) viewDidLoad
{
    [super viewDidLoad];

    self.collapsedSections = [NSMutableArray array];
    self.sectionViews      = [NSMutableArray array];
}

Bundan sonra, görünüm denetleyici sınıfımızdan erişilebilmesi için UITableView'umuzu bağlamalıyız:

@property (strong, nonatomic) IBOutlet UITableView *tblMain;

ctrl + dragNormalde olduğu gibi kullanarak denetleyiciyi görüntülemek için XIB'den bağlayın .

Ardından bu UITableView temsilcisini uygulayarak tablo görünümümüz için özel bölüm başlığı olarak görünüm oluştururuz:

- (UIView*) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    // Create View
    CGRect frame = CGRectZero;

    frame.origin = CGPointZero;

    frame.size.height = 30.f;
    frame.size.width  = tableView.bounds.size.width;

    UIView* view = [[UIView alloc] initWithFrame:frame];

    [view setBackgroundColor:[UIColor blueColor]];

    // Add label for title
    NSArray* titles = @[@"Title 1", @"Title 2", @"Title 3"];

    NSString* selectedTitle = [titles objectAtIndex:section];

    CGRect labelFrame = frame;

    labelFrame.size.height = 30.f;
    labelFrame.size.width -= 20.f;
    labelFrame.origin.x += 10.f;

    UILabel* titleLabel = [[UILabel alloc] initWithFrame:labelFrame];

    [titleLabel setText:selectedTitle];
    [titleLabel setTextColor:[UIColor whiteColor]];

    [view addSubview:titleLabel];

    // Add touch gesture
    [self attachTapGestureToView:view];

    // Save created view to our class property array
    [self saveSectionView:view inSection:section];

    return view;
}

Daha sonra, önceden oluşturduğumuz özel bölüm başlığımızı sınıf özelliğine kaydetmek için yöntem uygularız:

- (void) saveSectionView:(UIView*) view inSection:(NSInteger) section
{
    NSInteger sectionCount = [self numberOfSectionsInTableView:[self tblMain]];

    if(section < sectionCount)
    {
        if([[self sectionViews] indexOfObject:view] == NSNotFound)
        {
            [[self sectionViews] addObject:view];
        }
    }
}

UIGestureRecognizerDelegateView controller .h dosyamıza ekleyin :

@interface MyViewController : UIViewController<UITableViewDelegate, UITableViewDataSource, UIGestureRecognizerDelegate>

Sonra yöntem oluşturuyoruz attachTapGestureToView:

- (void) attachTapGestureToView:(UIView*) view
{
    UITapGestureRecognizer* tapAction = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onTap:)];

    [tapAction setDelegate:self];

    [view addGestureRecognizer:tapAction];
}

Yukarıdaki yöntem, daha önce oluşturduğumuz tüm bölüm görünümlerine dokunma hareketi tanıyıcı ekleyecektir. Daha sonra onTap:seçici uygulamalıyız

- (void) onTap:(UITapGestureRecognizer*) gestureRecognizer
{
    // Take view who attach current recognizer
    UIView* sectionView = [gestureRecognizer view]; 

    // [self sectionViews] is Array containing our custom section views
    NSInteger section = [self sectionNumberOfView:sectionView];

    // [self tblMain] is our connected IBOutlet table view
    NSInteger sectionCount = [self numberOfSectionsInTableView:[self tblMain]];

    // If section more than section count minus one set at last
    section = section > (sectionCount - 1) ? 2 : section;

    [self toggleCollapseSection:section];
}

Yukarıdaki yöntem, kullanıcı tablo görünümü bölümümüzden herhangi birine dokunduğunda başlatılacaktır. Bu yöntem, bize göre doğru bölüm numarasını arar.sectionViews önce oluşturduğumuz dizimize .

Ayrıca, başlık görünümünün ait olduğu bölümü almak için yöntem uygularız.

- (NSInteger) sectionNumberOfView:(UIView*) view
{
    UILabel* label = [[view subviews] objectAtIndex:0];

    NSInteger sectionNum = 0;

    for(UIView* sectionView in [self sectionViews])
    {
        UILabel* sectionLabel = [[sectionView subviews] objectAtIndex:0];

        //NSLog(@"Section: %d -> %@ vs %@", sectionNum, [label text], [sectionLabel text]);

        if([[label text] isEqualToString:[sectionLabel text]])
        {
            return sectionNum;
        }

        sectionNum++;
    }

    return NSNotFound;
}

Sonra, yöntemi uygulamalıyız toggleCollapseSection:

- (void) toggleCollapseSection:(NSInteger) section
{
    if([self isCollapsedSection:section])
    {
        [self removeCollapsedSection:section];
    }
    else
    {
        [self addCollapsedSection:section];
    }

    [[self tblMain] reloadSections:[NSIndexSet indexSetWithIndex:section] withRowAnimation:UITableViewRowAnimationFade];
}

Bu yöntem, daha collapsedSectionsönce oluşturduğumuz dizimize bölüm numarasını ekleyecek / kaldıracaktır . Bu diziye bir bölüm numarası eklendiğinde, bu, bölümün aksi durumda daraltılması ve genişletilmesi gerektiği anlamına gelir.

Biz uygulamak Sonraki removeCollapsedSection:, addCollapsedSection:sectionveisCollapsedSection:section

- (BOOL)isCollapsedSection:(NSInteger) section
{
    for(NSNumber* existing in [self collapsedSections])
    {
        NSInteger current = [existing integerValue];

        if(current == section)
        {
            return YES;
        }
    }

    return NO;
}

- (void)removeCollapsedSection:(NSInteger) section
{
    [[self collapsedSections] removeObjectIdenticalTo:[NSNumber numberWithInteger:section]];
}

- (void)addCollapsedSection:(NSInteger) section
{
    [[self collapsedSections] addObject:[NSNumber numberWithInteger:section]];
}

Bu üç yöntem, collapsedSectionsdiziye erişmemizi kolaylaştırmak için sadece yardımcıdır .

Son olarak, özel bölüm görünümlerimizin güzel görünmesi için bu tablo görünümü temsilcisini uygulayın.

- (CGFloat) tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    return 30.f; // Same as each custom section view height
}

Umarım yardımcı olur.


1

Veri kaynağı olarak bir NSDictionary kullandım, bu çok fazla koda benziyor, ancak gerçekten basit ve çok iyi çalışıyor! buraya nasıl görünüyor

Bölümler için bir numara oluşturdum

typedef NS_ENUM(NSUInteger, TableViewSection) {

    TableViewSection0 = 0,
    TableViewSection1,
    TableViewSection2,
    TableViewSectionCount
};

bölümler özelliği:

@property (nonatomic, strong) NSMutableDictionary * sectionsDisctionary;

Bölümlerimi döndüren bir yöntem:

-(NSArray <NSNumber *> * )sections{

    return @[@(TableViewSection0), @(TableViewSection1), @(TableViewSection2)];
}

Ve sonra veri sorunuzu ayarlayın:

-(void)loadAndSetupData{

    self.sectionsDisctionary = [NSMutableDictionary dictionary];

    NSArray * sections = [self sections];

    for (NSNumber * section in sections) {

    NSArray * sectionObjects = [self objectsForSection:section.integerValue];

    [self.sectionsDisctionary setObject:[NSMutableDictionary dictionaryWithDictionary:@{@"visible" : @YES, @"objects" : sectionObjects}] forKey:section];
    }
}

-(NSArray *)objectsForSection:(NSInteger)section{

    NSArray * objects;

    switch (section) {

        case TableViewSection0:

            objects = @[] // objects for section 0;
            break;

        case TableViewSection1:

            objects = @[] // objects for section 1;
            break;

        case TableViewSection2:

            objects = @[] // objects for section 2;
            break;

        default:
            break;
    }

    return objects;
}

Sonraki yöntemler, bir bölümün ne zaman açıldığını ve tablo görünümü veri kaynağına nasıl yanıt vereceğinizi bilmenize yardımcı olacaktır:

Veri kaynağına bölümü yanıtlayın:

/**
 *  Asks the delegate for a view object to display in the header of the specified section of the table view.
 *
 *  @param tableView The table-view object asking for the view object.
 *  @param section   An index number identifying a section of tableView .
 *
 *  @return A view object to be displayed in the header of section .
 */
- (UIView *) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{

    NSString * headerName = [self titleForSection:section];

    YourCustomSectionHeaderClass * header = (YourCustomSectionHeaderClass *)[tableView dequeueReusableHeaderFooterViewWithIdentifier:YourCustomSectionHeaderClassIdentifier];

    [header setTag:section];
    [header addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGesture:)]];
    header.title = headerName;
    header.collapsed = [self sectionIsOpened:section];


    return header;
}

/**
 * Asks the data source to return the number of sections in the table view
 *
 * @param An object representing the table view requesting this information.
 * @return The number of sections in tableView.
 */
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
    // Return the number of sections.

    return self.sectionsDisctionary.count;
}

/**
 * Tells the data source to return the number of rows in a given section of a table view
 *
 * @param tableView: The table-view object requesting this information.
 * @param section: An index number identifying a section in tableView.
 * @return The number of rows in section.
 */
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{

    BOOL sectionOpened = [self sectionIsOpened:section];
    return sectionOpened ? [[self objectsForSection:section] count] : 0;
}

Araçlar:

/**
 Return the section at the given index

 @param index the index

 @return The section in the given index
 */
-(NSMutableDictionary *)sectionAtIndex:(NSInteger)index{

    NSString * asectionKey = [self.sectionsDisctionary.allKeys objectAtIndex:index];

    return [self.sectionsDisctionary objectForKey:asectionKey];
}

/**
 Check if a section is currently opened

 @param section the section to check

 @return YES if is opened
 */
-(BOOL)sectionIsOpened:(NSInteger)section{

    NSDictionary * asection = [self sectionAtIndex:section];
    BOOL sectionOpened = [[asection objectForKey:@"visible"] boolValue];

    return sectionOpened;
}


/**
 Handle the section tap

 @param tap the UITapGestureRecognizer
 */
- (void)handleTapGesture:(UITapGestureRecognizer*)tap{

    NSInteger index = tap.view.tag;

    [self toggleSection:index];
}

Bölüm görünürlüğünü değiştir

/**
 Switch the state of the section at the given section number

 @param section the section number
 */
-(void)toggleSection:(NSInteger)section{

    if (index >= 0){

        NSMutableDictionary * asection = [self sectionAtIndex:section];

        [asection setObject:@(![self sectionIsOpened:section]) forKey:@"visible"];

        [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:section] withRowAnimation:UITableViewRowAnimationFade];
    }
}

0
// -------------------------------------------------------------------------------
//  tableView:viewForHeaderInSection:
// -------------------------------------------------------------------------------
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {

    UIView *mView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 20, 20)];
    [mView setBackgroundColor:[UIColor greenColor]];

    UIImageView *logoView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 5, 20, 20)];
    [logoView setImage:[UIImage imageNamed:@"carat.png"]];
    [mView addSubview:logoView];

    UIButton *bt = [UIButton buttonWithType:UIButtonTypeCustom];
    [bt setFrame:CGRectMake(0, 0, 150, 30)];
    [bt setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
    [bt setTag:section];
    [bt.titleLabel setFont:[UIFont systemFontOfSize:20]];
    [bt.titleLabel setTextAlignment:NSTextAlignmentCenter];
    [bt.titleLabel setTextColor:[UIColor blackColor]];
    [bt setTitle: @"More Info" forState: UIControlStateNormal];
    [bt addTarget:self action:@selector(addCell:) forControlEvents:UIControlEventTouchUpInside];
    [mView addSubview:bt];
    return mView;

}

#pragma mark - Suppose you want to hide/show section 2... then
#pragma mark  add or remove the section on toggle the section header for more info

- (void)addCell:(UIButton *)bt{

    // If section of more information
    if(bt.tag == 2) {

        // Initially more info is close, if more info is open
        if(ifOpen) {
            DLog(@"close More info");

            // Set height of section
            heightOfSection = 0.0f;

            // Reset the parameter that more info is closed now
            ifOpen = NO;
        }else {
            // Set height of section
            heightOfSection = 45.0f;
            // Reset the parameter that more info is closed now
            DLog(@"open more info again");
            ifOpen = YES;
        }
        //[self.tableView reloadData];
        [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:2] withRowAnimation:UITableViewRowAnimationFade];
    }

}// end addCell
#pragma mark -
#pragma mark  What will be the height of the section, Make it dynamic

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{

    if (indexPath.section == 2) {
        return heightOfSection;
    }else {
        return 45.0f;
    }

// vKj


0
This action will happen in your didSelectRowAtIndexPath, when you will try to hide or show number of cell in a  section

first of all declare a global variable numberOfSectionInMoreInfo in .h file and in your viewDidLoad set suppose to numberOfSectionInMoreInfo = 4.

Now use following logic: 


 // More info link
        if(row == 3) {

            /*Logic: We are trying to hide/show the number of row into more information section */

            NSString *log= [NSString stringWithFormat:@"Number of section in more %i",numberOfSectionInMoreInfo];

            [objSpineCustomProtocol showAlertMessage:log];

            // Check if the number of rows are open or close in view
            if(numberOfSectionInMoreInfo > 4) {

                // close the more info toggle
                numberOfSectionInMoreInfo = 4;

            }else {

                // Open more info toggle
                numberOfSectionInMoreInfo = 9;

            }

            //reload this section
            [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:1] withRowAnimation:UITableViewRowAnimationFade];

// VKJ


Neden iki cevap? Soruna iki farklı çözüm sunmuş görünmüyorsunuz.
Cristik

0

Objective C'de yazılan bu cevabı genişleterek, Swift ile yazanlar için şunları yazdım:

Buradaki fikir, tablo içindeki bölümleri kullanmak ve o bölümdeki ilk satıra dokunulduğunda bölümdeki satır sayısını 1 (daraltılmış) ve 3 (genişletilmiş) olarak ayarlamaktır.

Tablo, bir Boolean değerleri dizisine göre kaç satır çizileceğine karar verir

Film şeridinde iki satır oluşturmanız ve onlara yeniden kullanım tanımlayıcılarını 'CollapsingRow' ve 'GroupHeading' vermeniz gerekir.

import UIKit

class CollapsingTVC:UITableViewController{

    var sectionVisibilityArray:[Bool]!// Array index corresponds to section in table

    override func viewDidLoad(){
        super.viewDidLoad()
        sectionVisibilityArray = [false,false,false]
    }

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

    override func numberOfSections(in tableView: UITableView) -> Int{
        return sectionVisibilityArray.count
    }
    override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat{
        return 0
    }

    // numberOfRowsInSection - Get count of entries
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        var rowsToShow:Int = 0
        if(sectionVisibilityArray[section]){
            rowsToShow = 3 // Or however many rows should be displayed in that section
        }else{
            rowsToShow = 1
        }
        return rowsToShow
    }// numberOfRowsInSection


    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){
        if(indexPath.row == 0){
            if(sectionVisibilityArray[indexPath.section]){
                sectionVisibilityArray[indexPath.section] = false
            }else{
                sectionVisibilityArray[indexPath.section] = true
            }
            self.tableView.reloadSections([indexPath.section], with: .automatic)
        }
    }

    // cellForRowAtIndexPath - Get table cell corresponding to this IndexPath
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        var cell:UITableViewCell

        if(indexPath.row == 0){
             cell = tableView.dequeueReusableCell(withIdentifier: "GroupHeading", for: indexPath as IndexPath)
        }else{
            cell = tableView.dequeueReusableCell(withIdentifier: "CollapsingRow", for: indexPath as IndexPath)
        }

        return cell

    }// cellForRowAtIndexPath

}

0

Bir tablo görünümü bölüm üstbilgisi kullanarak bir genişletme / daraltma eylemini canlandırmak için bazı örnek kodlar Apple tarafından Tablo Görünümü Animasyonları ve Hareketlerinde sağlanmıştır .

Bu yaklaşımın anahtarı,

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section

ve bir düğme içeren (genellikle başlık görünümünün kendisiyle aynı boyutta) özel bir UIVView döndürür. UIView alt sınıflarına ayırarak ve bunu başlık görünümü için kullanarak (bu örnekte olduğu gibi), bölüm numarası gibi ek verileri kolayca depolayabilirsiniz.


0

Aynı şeyi birden çok bölüm kullanarak yaptım.

class SCTierBenefitsViewController: UIViewController {
    @IBOutlet private weak var tblTierBenefits: UITableView!
    private var selectedIndexPath: IndexPath?
    private var isSelected:Bool = false

    override func viewDidLoad() {
        super.viewDidLoad()

        tblTierBenefits.register(UINib(nibName:"TierBenefitsTableViewCell", bundle: nil), forCellReuseIdentifier:"TierBenefitsTableViewCell")
        tblTierBenefits.register(UINib(nibName:"TierBenefitsDetailsCell", bundle: nil), forCellReuseIdentifier:"TierBenefitsDetailsCell")

        tblTierBenefits.rowHeight = UITableViewAutomaticDimension;
        tblTierBenefits.estimatedRowHeight = 44.0;
        tblTierBenefits.tableFooterView = UIView()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

}

extension SCTierBenefitsViewController : UITableViewDataSource{

    func numberOfSections(in tableView: UITableView) -> Int {
        return 7
    }
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return (isSelected && section == selectedIndexPath?.section) ? 2 : 1 
    }

    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        return  0.01
    }

    func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        return nil
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        switch indexPath.row {
        case 0:
            let cell:TierBenefitsTableViewCell = tableView.dequeueReusableCell(withIdentifier: "TierBenefitsTableViewCell")! as! TierBenefitsTableViewCell
            cell.selectionStyle = .none
            cell.contentView.setNeedsLayout()
            cell.contentView.layoutIfNeeded()
            return cell

        case 1:
            let cell:TierBenefitsDetailsCell = tableView.dequeueReusableCell(withIdentifier: "TierBenefitsDetailsCell")! as! TierBenefitsDetailsCell
            cell.selectionStyle = .none
            return cell

        default:
            break
        }

        return UITableViewCell()
    }
}

extension SCTierBenefitsViewController : UITableViewDelegate{

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        if indexPath.row == 0 {

            if let _selectedIndexPath = selectedIndexPath ,selectedIndexPath?.section == indexPath.section {
                tblTierBenefits.beginUpdates()
                expandCollapse(indexPath: _selectedIndexPath, isExpand: false)
                selectedIndexPath = nil
            }
            else{
                tblTierBenefits.beginUpdates()
                if selectedIndexPath != nil {
                    tblTierBenefits.reloadSections([(selectedIndexPath?.section)!], with: .none)
                }
                expandCollapse(indexPath: indexPath, isExpand: true)
            }
        }
    }

    private func  expandCollapse(indexPath: IndexPath?,isExpand: Bool){
        isSelected = isExpand
        selectedIndexPath = indexPath
        tblTierBenefits.reloadSections([(indexPath?.section)!], with: .none)
        tblTierBenefits.endUpdates()
    }

}

0

Bu çözümü eksiksizlik için ekliyorum ve bölüm başlıklarıyla nasıl çalışılacağını gösteriyorum.

import UIKit

class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {

    @IBOutlet var tableView: UITableView!
    var headerButtons: [UIButton]!
    var sections = [true, true, true]

    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.dataSource = self
        tableView.delegate = self

        let section0Button = UIButton(type: .detailDisclosure)
        section0Button.setTitle("Section 0", for: .normal)
        section0Button.addTarget(self, action: #selector(section0Tapped), for: .touchUpInside)

        let section1Button = UIButton(type: .detailDisclosure)
        section1Button.setTitle("Section 1", for: .normal)
        section1Button.addTarget(self, action: #selector(section1Tapped), for: .touchUpInside)

        let section2Button = UIButton(type: .detailDisclosure)
        section2Button.setTitle("Section 2", for: .normal)
        section2Button.addTarget(self, action: #selector(section2Tapped), for: .touchUpInside)

        headerButtons = [UIButton]()
        headerButtons.append(section0Button)
        headerButtons.append(section1Button)
        headerButtons.append(section2Button)
    }

    func numberOfSections(in tableView: UITableView) -> Int {
        return sections.count
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return sections[section] ? 3 : 0
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cellReuseId = "cellReuseId"
        let cell = UITableViewCell(style: .default, reuseIdentifier: cellReuseId)
        cell.textLabel?.text = "\(indexPath.section): \(indexPath.row)"
        return cell
    }

    func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        return headerButtons[section]
    }

    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        return 44
    }

    @objc func section0Tapped() {
        sections[0] = !sections[0]
        tableView.reloadSections([0], with: .fade)
    }

    @objc func section1Tapped() {
        sections[1] = !sections[1]
        tableView.reloadSections([1], with: .fade)
    }

    @objc func section2Tapped() {
        sections[2] = !sections[2]
        tableView.reloadSections([2], with: .fade)
    }

}

Ana bağlantı: https://gist.github.com/pawelkijowskizimperium/fe1e8511a7932a0d40486a2669316d2c


0

@ jean.timex çözümünü desteklemek için, herhangi bir zamanda bir bölüm açmak istiyorsanız aşağıdaki kodu kullanın. gibi bir değişken oluşturun: var expandedSection = -1;

func toggleSection(_ header: CollapsibleTableViewHeader, section: Int) {
    let collapsed = !sections[section].collapsed
    // Toggle collapse
    sections[section].collapsed = collapsed
    header.setCollapsed(collapsed)
    tableView.reloadSections(NSIndexSet(index: section) as IndexSet, with: .automatic)
    if (expandedSection >= 0 && expandedSection != section){
        sections[expandedSection].collapsed = true
        tableView.reloadSections(NSIndexSet(index: expandedSection) as IndexSet, with: .automatic)
    }
    expandedSection = section;
}
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.