2013-09-22 25 views
16

我有使用IB/Storyboard中的靜態單元創建的表格視圖表單。但是,我需要在運行時根據特定條件隱藏一些單元。使用靜態單元隱藏UITableView中的單元格 - 並且沒有自動佈局崩潰

我找到了一些答案;在SO上的這個問題上,例如

UITableView set to static cells. Is it possible to hide some of the cells programmatically?

..和他們注重的是電池/行的高度設置爲0。這是偉大的,但我現在得到的自動版式異常,因爲約束條件不能滿足。我如何解決這個最後的問題?我可以暫時禁用子視圖的自動佈局嗎?有沒有更好的方式在iOS7中做到這一點?

回答

14

我發現最好的辦法是簡單地處理numberOfRowsInSection,cellForRowAtIndexPath和heightForRowAtIndexPath來選擇性地刪除某些行。這是我的場景的一個「硬編碼」示例,您可以做一些更智能的事情來智能地移除某些單元格,而不是像這樣硬編碼,但這對於我的簡單場景來說是最簡單的。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    UITableViewCell *cell = [super tableView:tableView cellForRowAtIndexPath:indexPath]; 
    if (indexPath.section == 0 && hideStuff) { 
     cell = self.cellIWantToShow; 
    } 
    return cell; 
} 

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { 
    CGFloat height = [super tableView:tableView heightForRowAtIndexPath:indexPath]; 
    if (indexPath.section == 0 && hideStuff) { 
     height = [super tableView:tableView heightForRowAtIndexPath:[NSIndexPath indexPathForRow:2 inSection:0]]; 
    } 
    return height; 
} 

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
{ 
    NSInteger count = [super tableView:tableView numberOfRowsInSection:section]; 

    if (section == 0 && hideStuff) { 
     count -= hiddenCells.count; 
    } 

    return count; 
} 
+0

很高興您對此進行了排序,我對我的舊「答案」不工作感到內疚! – jrturton

+4

這可能有效,但我認爲它不被支持,因爲Apple的Table View Programming Guid說:「如果故事板中的表視圖是靜態的,那麼包含表視圖的UITableViewController的自定義子類不應該實現數據源協議。」 (來自https://developer.apple.com/library/ios/documentation/userexperience/conceptual/tableview_iphone/CreateConfigureTableView/CreateConfigureTableView.html#//apple_ref/doc/uid/TP40007451-CH6-SW27)。這些方法全部來自數據源協議。換句話說,當Apple升級產品時,不能保證這個解決方案不會中斷。 – algal

+0

這似乎在iOS 8中失敗。控制檯吐出一個警告,該委託實現了靜態表視圖,這可能是錯誤的,它會忽略委託。謝謝,蘋果! – osxdirk

2

這樣做的猶太方式是使用動態單元格,將行高設置爲0是一種破解。靜態單元非常方便,但功能有限。

+2

要做到這一點與動態細胞會發送表單的複雜性通過屋頂。我不相信沒有更好的解決方案,即使隱藏單元格的複雜性很高,總體複雜性(並因此可維護性)仍然會低於通過動態單元格渲染的這種大型表單(我可以在IB看不到)。除非您知道在動態單元中完成這項工作的好方法,同時仍然支持IB和網點等。 – ConfusedNoob

+0

您仍然可以在故事板中使用具有動態單元原型的IB網點。您只需要子類「UITableCell」並控制將插口拖到新的子類中。然後在您的表視圖控制器中訪問該屬性。 – GayleDDS

2

如果確保觸摸單元格底部邊緣沒有限制,則自動佈局不應該禁用(在iOS 6.0,6.1,7.0上測試)。你仍然會'錨'到頂部邊緣,並且必須釘住高度。 (當然,你可以做相反的操作並將其固定到底部。)

如果你的佈局取決於頂部和底部的邊緣位置,可以用編程方式去除約束(它們只是對象,之後所有)。

+0

這對我有用。 ConfusedNoob的答案似乎更合適。但是因爲我使用Xamarin,所以我無法輕鬆工作。 – m1sk

+0

更好的方法是將底部約束更改爲<=,而不是==。 – Joey

1

我設法避免了自動佈局的例外,方法是首先以viewDidLoad以編程方式刪除單元的contentView上的約束,然後在heightForRowAtIndexPath中將該單元的高度設置爲0。

3

最簡單的方法是更改​​部分和行的高度。這個對我有用。

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section 
{ 
    if (section == 3) { 
     return 0; 
    } else { 
     return [super tableView:tableView heightForHeaderInSection:section]; 
    } 
} 

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { 
    UITableViewCell *cell = [super tableView:tableView cellForRowAtIndexPath:indexPath]; 
    if (indexPath.section == 3) { 
     cell.hidden = YES; 
     return 0; 
    } else { 
     cell.hidden = NO; 
     return [super tableView:tableView heightForRowAtIndexPath:indexPath]; 
    } 
} 
0

對我來說最好的方法是修改numberOfRowsInSection方法。我刪除了我不想顯示的數據源。對我來說最好的解決方案,因爲一切都在一個功能。

(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 
if(section==0) { 
    NSUInteger productCount = _products.count; 
    for(loop trough your data) { 
     if(your condition is true) 
     productCount--; 
     } 
    } 
    return productCount; 
} else 
    return self.groups.count; 
} 
0

對於StoryBoard中的tableview也實現了這一點。我的單元格嵌入在具有標題的部分中,由xcode6IB中的該藍色立方體表示。實際上,如果實現heightForHeaderInSection,heightForFooterInSection和titleForHeaderInSection,titleForFooterInSection,則可以在顯示錶時訪問標題,並分別返回0.0和nil,併爲numberOfRowsInSection返回0。

基本上這一切工作正常,除了每個細胞隱藏ca.對於您隱藏的每個單元(部分)都會保留10像素高的垂直空間。任何想法可能是什麼?

7

隱藏在故事板細胞和高度設置爲0:

override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { 
    let cell: UITableViewCell = super.tableView(tableView, cellForRowAtIndexPath:indexPath) 
    return cell.hidden ? 0 : super.tableView(tableView, heightForRowAtIndexPath:indexPath) 
    } 
} 
+0

天才!迄今爲止的最佳答案 –

1

我已經找到一種方法,讓你連排的動畫,並正在努力在iOS 8.3。所有你需要的是落實的tableView:numberOfRowsInSection:數據源的方法,然後添加/由UITableView的方法刪除行 insertRowsAtIndexPaths:withRowAnimation:deleteRowsAtIndexPaths:withRowAnimation:

下面是示例隱藏基於確切行UISwitch的狀態:

- (IBAction)alowNotif:(id)sender { 
    UISwitch *sw = (UISwitch*)sender; 
    NSIndexPath *index = [NSIndexPath indexPathForRow:5 inSection:0]; 
    if ([sw isOn]) { 
     [self.tableView insertRowsAtIndexPaths:@[index] withRowAnimation:UITableViewRowAnimationAutomatic]; 
    } 
    else { 
     [self.tableView deleteRowsAtIndexPaths:@[index] withRowAnimation:UITableViewRowAnimationAutomatic]; 
    } 
} 

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 
    if (![notifications isOn]) { 
     return 5; 
    } 
    return 6; 
} 

正如由@algal,numberOfRowInSection如上所述:仍然是UITableViewDataSource方法,因此一個不只是知道它會工作多久。

相關問題