जवाबों:
आप इस समाधान की तलाश कर रहे हैं:
StaticDataTableViewController 2.0
https://github.com/xelvenone/StaticDataTableViewController
जो एनीमेशन के साथ या उसके बिना किसी भी स्थिर सेल को दिखा / छुपा / पुनः लोड कर सकता है!
[self cell:self.outletToMyStaticCell1 setHidden:hide];
[self cell:self.outletToMyStaticCell2 setHidden:hide];
[self reloadDataAnimated:YES];
हमेशा केवल उपयोग करने के लिए ध्यान दें (पुनः लोड करेंअनुरक्षित: हाँ / नहीं) (सीधे कॉल न करें [self.tableView reloadData] सीधे)
यह 0 की ऊँचाई सेट करने के साथ हैकी समाधान का उपयोग नहीं करता है और आपको परिवर्तन को एनिमेट करने और पूरे अनुभागों को छिपाने की अनुमति देता है
IBOutletCollectionरहा है, लेकिन मैं यह नहीं देखता कि इससे कैसे फर्क पड़ेगा। मैंने कल ही कोड डाउनलोड किया है इसलिए मुझे नहीं लगता कि इसका पुराना संस्करण है।
UITable में स्थिर कोशिकाओं को छिपाने के लिए:
आपके UITableView नियंत्रक प्रतिनिधि वर्ग में:
उद्देश्य सी:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell* cell = [super tableView:tableView cellForRowAtIndexPath:indexPath];
if(cell == self.cellYouWantToHide)
return 0; //set the hidden cell's height to 0
return [super tableView:tableView heightForRowAtIndexPath:indexPath];
}
स्विफ्ट:
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
var cell = super.tableView(tableView, cellForRowAtIndexPath: indexPath)
if cell == self.cellYouWantToHide {
return 0
}
return super.tableView(tableView, heightForRowAtIndexPath: indexPath)
}
इस विधि को यूआईटेबल में प्रत्येक सेल के लिए बुलाया जाएगा। एक बार जब आप इसे उस सेल के लिए कहते हैं जिसे आप छिपाना चाहते हैं, तो हम इसकी ऊँचाई 0. पर सेट करते हैं। हम इसके लिए एक आउटलेट बनाकर लक्ष्य सेल की पहचान करते हैं:
ClipToBoundsसमस्या से बचने के लिए , आप सेल को छिपाकर भी सेट कर सकते हैं। यह मुझे साफ प्रतीत होता है। ;-)
सबसे अच्छा तरीका निम्न ब्लॉग http://ali-reynolds.com/2013/06/29/hide-cells-in-static-table-view/ के रूप में वर्णित है
इंटरफ़ेस बिल्डर में सामान्य के रूप में अपने स्थिर तालिका दृश्य को डिज़ाइन करें - सभी संभावित छिपी कोशिकाओं के साथ पूरा करें। लेकिन हर संभावित सेल के लिए एक चीज होनी चाहिए जिसे आप छिपाना चाहते हैं - सेल के "क्लिप सबव्यू" प्रॉपर्टी की जांच करें, अन्यथा जब आप कोशिश करते हैं और इसे छिपाते हैं तो सेल का कंटेंट गायब नहीं होता है (सिकुड़कर यह ऊंचाई है - और बाद में)।
एसओ - आपके पास एक सेल में एक स्विच है और स्विच को कुछ स्थिर कोशिकाओं को छिपाने और दिखाने के लिए है। इसे IBAction तक हुक करें और वहां ऐसा करें:
[self.tableView beginUpdates]; [self.tableView endUpdates];यह आपको दिखने और गायब होने वाली कोशिकाओं के लिए अच्छा एनिमेशन देता है। अब निम्नलिखित तालिका दृश्य प्रतिनिधि पद्धति को लागू करें:
- (float)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { if (indexPath.section == 1 && indexPath.row == 1) { // This is the cell to hide - change as you need // Show or hide cell if (self.mySwitch.on) { return 44; // Show the cell - adjust the height as you need } else { return 0; // Hide the cell } } return 44; }और बस। स्विच फ्लिप और सेल छुपाता है और एक अच्छा, चिकनी एनीमेशन के साथ फिर से दिखाई देता है।
मेरा समाधान गैरेथ के समान दिशा में जाता है, हालांकि मैं कुछ चीजें अलग तरीके से करता हूं।
यहाँ जाता हैं:
1. कोशिकाओं को छिपाएं
कोशिकाओं को सीधे छिपाने का कोई तरीका नहीं है। UITableViewControllerडेटा स्रोत है जो स्थैतिक कोशिकाओं को प्रदान करता है, और वर्तमान में यह बताने का कोई तरीका नहीं है कि "सेल एक्स प्रदान न करें"। इसलिए हमें अपना स्वयं का डेटा स्रोत प्रदान करना होगा, जो UITableViewControllerस्थैतिक कोशिकाओं को प्राप्त करने के लिए प्रतिनिधि होता है।
सबसे आसान उपवर्ग है UITableViewController, और उन सभी तरीकों को ओवरराइड करता है जिन्हें कोशिकाओं को छुपाते समय अलग-अलग व्यवहार करने की आवश्यकता होती है ।
सबसे सरल मामले में (एकल खंड तालिका, सभी कोशिकाओं की ऊंचाई समान है), यह इस तरह से होगा:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [super tableView:tableView numberOfRowsInSection:section] - numberOfCellsHidden;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Recalculate indexPath based on hidden cells
indexPath = [self offsetIndexPath:indexPath];
return [super tableView:tableView cellForRowAtIndexPath:indexPath];
}
- (NSIndexPath*)offsetIndexPath:(NSIndexPath*)indexPath
{
int offsetSection = indexPath.section; // Also offset section if you intend to hide whole sections
int numberOfCellsHiddenAbove = ... // Calculate how many cells are hidden above the given indexPath.row
int offsetRow = indexPath.row + numberOfCellsHiddenAbove;
return [NSIndexPath indexPathForRow:offsetRow inSection:offsetSection];
}
यदि आपकी तालिका में कई खंड हैं, या कोशिकाओं में अलग-अलग ऊंचाइयां हैं, तो आपको अधिक विधियों को ओवरराइड करने की आवश्यकता है। यहां एक ही सिद्धांत लागू होता है: आपको सुपर को सौंपने से पहले indexPath, अनुभाग और पंक्ति को ऑफसेट करने की आवश्यकता है।
यह भी ध्यान रखें कि जैसे तरीकों के लिए indexPath पैरामीटर didSelectRowAtIndexPath: राज्य के आधार पर (यानी छिपी हुई कोशिकाओं की संख्या) के आधार पर, एक ही सेल के लिए अलग होगा। इसलिए किसी भी इंडेक्सपैथ पैरामीटर को हमेशा ऑफसेट करना और इन मूल्यों के साथ काम करना शायद एक अच्छा विचार है।
2. परिवर्तन को चेतन करें
जैसा कि गैरेथ ने पहले ही कहा था, यदि आप उपयोग करके चेतन परिवर्तन करते हैं, तो आपको बड़ी गड़बड़ियाँ मिलती हैं reloadSections:withRowAnimation: विधि ।
मुझे पता चला कि अगर तुम बुलाओ reloadData: तुरंत बाद में करते हैं, तो एनीमेशन में बहुत सुधार हुआ है (केवल मामूली गड़बड़ियां बची हैं)। एनीमेशन के बाद तालिका को सही ढंग से प्रदर्शित किया गया है।
तो मैं क्या कर रहा हूँ:
- (void)changeState
{
// Change state so cells are hidden/unhidden
...
// Reload all sections
NSIndexSet* reloadSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [self numberOfSectionsInTableView:tableView])];
[tableView reloadSections:reloadSet withRowAnimation:UITableViewRowAnimationAutomatic];
[tableView reloadData];
}
numberOfRowsInSection:केवल तभी कहा जाता है जब तालिका पहली बार लोड होती है। जब मैं [self.tableView reloadData] को कॉल करता हूं - numberOfRowsInSection:फिर कभी कॉल नहीं किया जाता है। ही cellForRowAtIndexPath:कहलाता है। मैं क्या खो रहा हूँ?
cellOneOutlet.hidden = true
अब नीचे दी गई विधि को ओवरराइड करें, जांचें कि कौन सी सेल की स्थिति छिपी हुई है और उन सेल (एस) के लिए ऊँचाई 0 लौटाएं। यह कई तरीकों में से एक है जिसे आप किसी भी सेल को स्टैटिक टेबल व्यू में तेजी से छिपा सकते हैं।
override func tableView(tableView: UITableView, heightForRowAtIndexPathindexPath: NSIndexPath) -> CGFloat
{
let tableViewCell = super.tableView(tableView,cellForRowAtIndexPath: indexPath)
if tableViewCell.hidden == true
{
return 0
}
else{
return super.tableView(tableView, heightForRowAtIndexPath: indexPath)
}
}
let tableViewCell = super.tableView(tableView,cellForRowAtIndexPath: indexPath)। मुझे लगता है कि यह द्वारा प्रतिस्थापित किया गया है let tableViewCell = tableView.cellForRow(at: indexPath as IndexPath)।
UITableViewControllerरहा हूं, मेरे पास कोई UITableViewप्रतिनिधि विधियां नहीं हैं । कॉल करने के लिए इसे प्राप्त करने के लिए heightForRow, क्या मुझे किसी अन्य तरीके की भी आवश्यकता है?
मैं एक विकल्प के साथ आया था जो वास्तव में वर्गों को छुपाता है और उन्हें हटाता नहीं है। मैंने @ henning77 के दृष्टिकोण की कोशिश की, लेकिन जब मैंने स्थैतिक UITableView के वर्गों की संख्या बदल दी तो मैं समस्याओं में भागता रहा। इस विधि ने मेरे लिए वास्तव में अच्छी तरह से काम किया है, लेकिन मैं मुख्य रूप से पंक्तियों के बजाय अनुभागों को छिपाने की कोशिश कर रहा हूं। मैं सफलतापूर्वक मक्खी पर कुछ पंक्तियों को हटा रहा हूं, लेकिन यह बहुत अधिक गड़बड़ है, इसलिए मैंने चीजों को उन वर्गों में समूहित करने की कोशिश की है जिन्हें मुझे दिखाने या छिपाने की आवश्यकता है। यहाँ एक उदाहरण है कि मैं किस तरह से वर्गों को छिपा रहा हूँ:
पहले मैं एक NSMutableArray संपत्ति घोषित करता हूं
@property (nonatomic, strong) NSMutableArray *hiddenSections;
ViewDidLoad में (या आपके द्वारा अपने डेटा को क्वेर किए जाने के बाद) आप उन वर्गों को जोड़ सकते हैं जिन्हें आप सरणी में छिपाना चाहते हैं।
- (void)viewDidLoad
{
hiddenSections = [NSMutableArray new];
if(some piece of data is empty){
// Add index of section that should be hidden
[self.hiddenSections addObject:[NSNumber numberWithInt:1]];
}
... add as many sections to the array as needed
[self.tableView reloadData];
}
फिर निम्नलिखित TableView प्रतिनिधि विधियों को लागू करें
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
if([self.hiddenSections containsObject:[NSNumber numberWithInt:section]]){
return nil;
}
return [super tableView:tableView titleForHeaderInSection:section];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if([self.hiddenSections containsObject:[NSNumber numberWithInt:indexPath.section]]){
return 0;
}
return [super tableView:tableView heightForRowAtIndexPath:[self offsetIndexPath:indexPath]];
}
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
if([self.hiddenSections containsObject:[NSNumber numberWithInt:indexPath.section]]){
[cell setHidden:YES];
}
}
फिर शीर्षकों और पाद लेख की ऊँचाई को छिपे हुए खंडों के लिए 1 पर सेट करें क्योंकि आप ऊँचाई को 0 पर सेट नहीं कर सकते हैं। यह अतिरिक्त 2 पिक्सेल स्थान का कारण बनता है, लेकिन हम अगले दृश्यमान शीर्ष लेख की ऊँचाई को समायोजित करके इसके लिए बना सकते हैं।
-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
CGFloat height = [super tableView:tableView heightForHeaderInSection:section];
if([self.hiddenSections containsObject:[NSNumber numberWithInt:section]]){
height = 1; // Can't be zero
}
else if([self tableView:tableView titleForHeaderInSection:section] == nil){ // Only adjust if title is nil
// Adjust height for previous hidden sections
CGFloat adjust = 0;
for(int i = (section - 1); i >= 0; i--){
if([self.hiddenSections containsObject:[NSNumber numberWithInt:i]]){
adjust = adjust + 2;
}
else {
break;
}
}
if(adjust > 0)
{
if(height == -1){
height = self.tableView.sectionHeaderHeight;
}
height = height - adjust;
if(height < 1){
height = 1;
}
}
}
return height;
}
-(CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
if([self.hiddenSections containsObject:[NSNumber numberWithInt:section]]){
return 1;
}
return [super tableView:tableView heightForFooterInSection:section];
}
फिर, यदि आपके पास छिपाने के लिए विशिष्ट पंक्तियाँ हैं, तो आप संख्याओं को समायोजित कर सकते हैं। InSection और कौन-सी पंक्तियाँ सेलफ़ोररौटइंडेक्सपैथ में वापस आ जाती हैं। इस उदाहरण में यहाँ मेरा एक खंड है जिसमें तीन पंक्तियाँ हैं जहाँ कोई भी तीन खाली हो सकता है और उसे निकालने की आवश्यकता है।
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSInteger rows = [super tableView:tableView numberOfRowsInSection:section];
if(self.organization != nil){
if(section == 5){ // Contact
if([self.organization objectForKey:@"Phone"] == [NSNull null]){
rows--;
}
if([self.organization objectForKey:@"Email"] == [NSNull null]){
rows--;
}
if([self.organization objectForKey:@"City"] == [NSNull null]){
rows--;
}
}
}
return rows;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
return [super tableView:tableView cellForRowAtIndexPath:[self offsetIndexPath:indexPath]];
}
जहाँ आप सशर्त रूप से पंक्तियों को हटा रहे हैं, उन पंक्तियों के लिए indexPath की गणना करने के लिए इस ऑफ़सेटइंडैक्स का उपयोग करें। जरूरत नहीं है अगर आप केवल वर्गों को छिपा रहे हैं
- (NSIndexPath *)offsetIndexPath:(NSIndexPath*)indexPath
{
int row = indexPath.row;
if(self.organization != nil){
if(indexPath.section == 5){
// Adjust row to return based on which rows before are hidden
if(indexPath.row == 0 && [self.organization objectForKey:@"Phone"] == [NSNull null] && [self.organization objectForKey:@"Email"] != [NSNull null]){
row++;
}
else if(indexPath.row == 0 && [self.organization objectForKey:@"Phone"] == [NSNull null] && [self.organization objectForKey:@"Address"] != [NSNull null]){
row = row + 2;
}
else if(indexPath.row == 1 && [self.organization objectForKey:@"Phone"] != [NSNull null] && [self.organization objectForKey:@"Email"] == [NSNull null]){
row++;
}
else if(indexPath.row == 1 && [self.organization objectForKey:@"Phone"] == [NSNull null] && [self.organization objectForKey:@"Email"] != [NSNull null]){
row++;
}
}
}
NSIndexPath *offsetPath = [NSIndexPath indexPathForRow:row inSection:indexPath.section];
return offsetPath;
}
ओवरराइड करने के लिए बहुत सारे तरीके हैं, लेकिन मुझे इस दृष्टिकोण के बारे में जो पसंद है वह यह है कि यह फिर से प्रयोग करने योग्य है। हिडेन सेक्शन को सेट करें, इसमें जोड़ें, और यह सही सेक्शन को छिपाएगा। पंक्तियों को छुपाना थोड़ा मुश्किल है, लेकिन संभव है। यदि हम एक समूहीकृत UITableView का उपयोग कर रहे हैं तो हम केवल उन पंक्तियों की ऊँचाई सेट नहीं कर सकते हैं जिन्हें हम 0 पर छुपाना चाहते हैं क्योंकि सीमाएँ सही तरीके से नहीं खींची जाएंगी।
NSMutableSetके लिए hiddenSectionsबजाय। यह बहुत तेज़ है क्योंकि आप ज्यादातर सदस्यता के लिए परीक्षण कर रहे हैं।
NSMutableSetके बारे में एक अच्छा बिंदु बनाता है hiddenSections, हालांकि मैं समझता हूं कि आपके उत्तर का बिंदु नाइट-पिकी की तुलना में अधिक वैचारिक था कि आपको किस प्रकार की डेटा संरचना का उपयोग करना चाहिए।
बाहर मुड़ता है, आप एक स्थिर UITableView में कोशिकाओं को छिपा सकते हैं और दिखा सकते हैं - और एनीमेशन के साथ। और यह पूरा करना उतना कठिन नहीं है।
सार:
Use tableView:heightForRowAtIndexPath: कुछ राज्य के आधार पर गतिशील रूप से सेल ऊंचाइयों को निर्दिष्ट करने के लिए।tableView.beginUpdates();tableView.endUpdates()tableView.cellForRowAtIndexPath:अंदर मत बुलाओ tableView:heightForRowAtIndexPath:। कोशिकाओं को अलग करने के लिए कैश्ड इंडेक्सपैथ का उपयोग करें।हां, यह निश्चित रूप से संभव है, हालांकि मैं इस समय उसी मुद्दे से जूझ रहा हूं। मैं छिपाने के लिए कोशिकाओं को प्राप्त करने में कामयाब रहा हूं और सब कुछ ठीक काम करता है, लेकिन मैं वर्तमान में बड़े करीने से बात नहीं कर सकता। यहाँ मैं क्या पाया है:
मैं पहले खंड की पहली पंक्ति में चालू / बंद स्विच की स्थिति के आधार पर पंक्तियों को छिपा रहा हूं। यदि स्विच चालू है तो उसी खंड में उसके नीचे 1 पंक्ति है, अन्यथा 2 अलग-अलग पंक्तियाँ हैं।
मुझे एक चयनकर्ता कहा जाता है जब स्विच को टॉगल किया जाता है, और मैं यह इंगित करने के लिए एक चर सेट करता हूं कि मैं किस राज्य में हूं। फिर मैं कॉल करता हूं:
[[self tableView] reloadData];
मैं तालिका को ओवरराइड करता हूं : willDisplayCell: forRowAtIndexPath: फ़ंक्शन और यदि सेल को छिपाना चाहिए तो मैं ऐसा करता हूं:
[cell setHidden:YES];
यह सेल और उसकी सामग्री को छुपाता है, लेकिन उस स्थान को नहीं हटाता है जो वह व्याप्त है।
स्थान निकालने के लिए, तालिका को ओवरराइड करें : heightForRowAtIndexPath: फ़ंक्शन और उन पंक्तियों के लिए 0 लौटें जिन्हें छिपाया जाना चाहिए।
आपको तालिका को ओवरराइड करने की भी आवश्यकता है : numberOfRowsInSection: और उस अनुभाग में पंक्तियों की संख्या लौटाएं। आपको यहां कुछ अजीब करना होगा ताकि अगर आपकी टेबल एक समूहित शैली हो तो सही कोनों पर गोल कोनों हो। मेरी स्टैटिक टेबल में सेक्शन के लिए सेल्स का पूरा सेट होता है, इसलिए ऑप्शन वाला पहला सेल होता है, फिर ON स्टेट ऑप्शन के लिए 1 सेल और OFF स्टेट ऑप्शन के लिए 2 और सेल, कुल 4 सेल। जब विकल्प चालू होता है, तो मुझे 4 को वापस करना पड़ता है, इसमें छिपा हुआ विकल्प शामिल होता है ताकि प्रदर्शित अंतिम विकल्प में एक गोल बॉक्स हो। जब विकल्प बंद हो जाता है, तो अंतिम दो विकल्प प्रदर्शित नहीं होते हैं इसलिए मैं वापस लौटता हूं। यह सब क्लिंकी लगता है। क्षमा करें यदि यह बहुत स्पष्ट नहीं है, तो इसका वर्णन करना मुश्किल है। बस सेटअप को दर्शाने के लिए, यह IB में टेबल सेक्शन का निर्माण है:
इसलिए जब विकल्प तालिका पर होता है तो दो पंक्तियों की रिपोर्ट करता है जो हैं:
जब विकल्प बंद होता है तो तालिका चार पंक्तियों की रिपोर्ट करती है जो हैं:
यह दृष्टिकोण कई कारणों से सही नहीं लगता है, इसका अभी तक जहाँ तक मुझे अपने प्रयोग के साथ मिला है, इसलिए कृपया मुझे बताएं कि क्या आपको बेहतर तरीका मिल सकता है। अब तक मैंने जो समस्याएं देखी हैं, वे हैं:
यह बताना गलत है कि तालिका की पंक्तियों की संख्या अंतर्निहित डेटा में मौजूद है जो भिन्न है।
मैं परिवर्तन को चेतन नहीं कर सकता। मैंने tableView का उपयोग करने की कोशिश की है : reloadSections: withRowAnimation: reloadData के बजाय और परिणाम समझ में नहीं आते हैं, मैं अभी भी इस काम को पाने की कोशिश कर रहा हूं। वर्तमान में जो होना प्रतीत होता है वह यह है कि तालिका दृश्य सही पंक्तियों को अपडेट नहीं करता है इसलिए एक छिपा रहता है जिसे प्रदर्शित किया जाना चाहिए और पहली पंक्ति के नीचे एक शून्य छोड़ दिया जाता है। मुझे लगता है कि यह अंतर्निहित डेटा के बारे में पहले बिंदु से संबंधित हो सकता है।
उम्मीद है कि कोई व्यक्ति वैकल्पिक तरीकों का सुझाव देने में सक्षम होगा या शायद एनीमेशन के साथ कैसे आगे बढ़ सकता है, लेकिन शायद यह आपको शुरू कर देगा। फ़ंक्शंस के लिए हाइपरलिंक्स की कमी के लिए मेरी माफी, मैंने उन्हें डाल दिया लेकिन उन्हें स्पैम फ़िल्टर द्वारा अस्वीकार कर दिया गया क्योंकि मैं एक काफी नया उपयोगकर्ता हूं।
[[self tableView] reloadData];कोशिकाओं को छुपाने के बाद एक बार और कॉल करना चाहिए
return [super tableView:tableView cellForRowAtIndexPath:indexPath];में कॉल करें UITableViewController। सूचकांक पथ स्थिर अनुक्रमित हैं - गतिशील नहीं ...
जस्टस के जवाब के अनुसार, लेकिन स्विफ्ट 4 के लिए:
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
let cell = super.tableView(tableView, cellForRowAt: indexPath)
if cell == self.cellYouWantToHide {
return 0
}
return super.tableView(tableView, heightForRowAt: indexPath)
}
tableView.reloadRows(at:, with:)यदि आपको पंक्ति पहले से ही दिखाई दे रही है, तो ऊंचाई बदलने पर आपको कक्षों को अपडेट करने की आवश्यकता हो सकती है ।
ठीक है, कुछ कोशिशों के बाद, मेरे पास एक गैर सामान्य उत्तर है। मैं "हैडिड" या "हिडन" वैरिएबल का उपयोग कर रहा हूं यह जांचने के लिए कि क्या यह सेल छिपा होना चाहिए।
अपने दृश्य नियंत्रक के लिए एक IBOutlet बनाएँ।
@IBOutlet weak var myCell: UITableViewCell!
myCellअपने कस्टम फ़ंक्शन में अपडेट करें , उदाहरण के लिए आप इसे viewDidLoad में जोड़ सकते हैं:
override func viewDidLoad() {
super.viewDidLoad()
self.myCell.isHidden = true
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
let cell = super.tableView(tableView, cellForRowAt: indexPath)
guard !cell.isHidden else {
return 0
}
return super.tableView(tableView, heightForRowAt: indexPath)
}
यह प्रतिनिधि पद्धति में आपके तर्क को कम करेगा, और आपको केवल अपनी व्यावसायिक आवश्यकता पर ध्यान देने की आवश्यकता है।
उपरोक्त उत्तर जो कोशिकाओं को छिपाते हैं / दिखाते हैं, रोहाइट बदलते हैं, या ऑटो लेआउट की गड़बड़ी के कारण गड़बड़ होती है, मेरे लिए ऑटो लेआउट मुद्दों के कारण काम नहीं किया। कोड असहनीय हो गया।
एक साधारण स्थिर तालिका के लिए, मेरे लिए सबसे अच्छा काम क्या था:
यहाँ मेरे टेबल व्यू कंट्रोलर से एक उदाहरण है:
@IBOutlet weak var titleCell: UITableViewCell!
@IBOutlet weak var nagCell: UITableViewCell!
@IBOutlet weak var categoryCell: UITableViewCell!
var cellsToShow: [UITableViewCell] = []
override func viewDidLoad() {
super.viewDidLoad()
determinCellsToShow()
}
func determinCellsToShow() {
if detail!.duration.type != nil {
cellsToShow = [titleCell, nagCell, categoryCell]
}
else {
cellsToShow = [titleCell, categoryCell]
}
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
return cellsToShow[indexPath.row]
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return cellsToShow.count
}
IOS 11 के लिए, मैंने पाया कि मोहम्मद सालेह के जवाब का एक संशोधित संस्करण सबसे अच्छा काम करता है, जिसमें Apple के प्रलेखन के आधार पर कुछ सुधार किए गए हैं। यह अच्छी तरह से एनिमेट करता है, किसी भी बदसूरत हैक या हार्डकोड के मूल्यों से बचा जाता है, और इंटरफ़ेस बिल्डर में पहले से निर्धारित पंक्ति ऊंचाइयों का उपयोग करता है ।
मूल अवधारणा किसी भी छिपी हुई पंक्तियों के लिए पंक्ति की ऊंचाई 0 पर सेट करना है। फिर tableView.performBatchUpdatesएक एनीमेशन को ट्रिगर करने के लिए उपयोग करें जो लगातार काम करता है।
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath == indexPathOfHiddenCell {
if cellIsHidden {
return 0
}
}
// Calling super will use the height set in your storyboard, avoiding hardcoded values
return super.tableView(tableView, heightForRowAt: indexPath)
}
आपको यह सुनिश्चित करना चाहेंगे cellIsHiddenऔर indexPathOfHiddenCellआपके उपयोग मामले पर उचित रूप में निर्धारित कर रहे हैं। मेरे कोड के लिए वे मेरे टेबल व्यू कंट्रोलर के गुण हैं।
जिस भी विधि में दृश्यता को नियंत्रित किया जा सकता है (एक बटन क्रिया या didSelectRow), एक performBatchUpdatesब्लॉक के अंदर, सेल की स्थिति को टॉगल करें :
tableView.performBatchUpdates({
// Use self to capture for block
self.cellIsHidden = !self.cellIsHidden
}, completion: nil)
एप्पल की सिफारिश की performBatchUpdatesअधिक beginUpdates/endUpdates जब भी संभव हो।
मुझे स्थैतिक तालिका में कोशिकाओं को छुपाने के लिए एक समाधान मिला।
// Class for wrapping Objective-C block
typedef BOOL (^HidableCellVisibilityFunctor)();
@interface BlockExecutor : NSObject
@property (strong,nonatomic) HidableCellVisibilityFunctor block;
+ (BlockExecutor*)executorWithBlock:(HidableCellVisibilityFunctor)block;
@end
@implementation BlockExecutor
@synthesize block = _block;
+ (BlockExecutor*)executorWithBlock:(HidableCellVisibilityFunctor)block
{
BlockExecutor * executor = [[BlockExecutor alloc] init];
executor.block = block;
return executor;
}
@end
केवल एक अतिरिक्त शब्दकोश की जरूरत है:
@interface MyTableViewController ()
@property (nonatomic) NSMutableDictionary * hidableCellsDict;
@property (weak, nonatomic) IBOutlet UISwitch * birthdaySwitch;
@end
और MyTableViewController के कार्यान्वयन को देखें। हमें indexPath को दृश्य और अदृश्य अनुक्रमित के बीच बदलने के लिए दो तरीकों की आवश्यकता है ...
- (NSIndexPath*)recoverIndexPath:(NSIndexPath *)indexPath
{
int rowDelta = 0;
for (NSIndexPath * ip in [[self.hidableCellsDict allKeys] sortedArrayUsingSelector:@selector(compare:)])
{
BlockExecutor * executor = [self.hidableCellsDict objectForKey:ip];
if (ip.section == indexPath.section
&& ip.row <= indexPath.row + rowDelta
&& !executor.block())
{
rowDelta++;
}
}
return [NSIndexPath indexPathForRow:indexPath.row+rowDelta inSection:indexPath.section];
}
- (NSIndexPath*)mapToNewIndexPath:(NSIndexPath *)indexPath
{
int rowDelta = 0;
for (NSIndexPath * ip in [[self.hidableCellsDict allKeys] sortedArrayUsingSelector:@selector(compare:)])
{
BlockExecutor * executor = [self.hidableCellsDict objectForKey:ip];
if (ip.section == indexPath.section
&& ip.row < indexPath.row - rowDelta
&& !executor.block())
{
rowDelta++;
}
}
return [NSIndexPath indexPathForRow:indexPath.row-rowDelta inSection:indexPath.section];
}
यूआईस्विच मूल्य परिवर्तन पर एक आईबीएशन:
- (IBAction)birthdaySwitchChanged:(id)sender
{
NSIndexPath * indexPath = [self mapToNewIndexPath:[NSIndexPath indexPathForRow:1 inSection:1]];
if (self.birthdaySwitch.on)
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
else
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
कुछ UITableViewDataSource और UITableViewDelegate तरीके:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
int numberOfRows = [super tableView:tableView numberOfRowsInSection:section];
for (NSIndexPath * indexPath in [self.hidableCellsDict allKeys])
if (indexPath.section == section)
{
BlockExecutor * executor = [self.hidableCellsDict objectForKey:indexPath];
numberOfRows -= (executor.block()?0:1);
}
return numberOfRows;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
indexPath = [self recoverIndexPath:indexPath];
return [super tableView:tableView cellForRowAtIndexPath:indexPath];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
indexPath = [self recoverIndexPath:indexPath];
return [super tableView:tableView heightForRowAtIndexPath:indexPath];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// initializing dictionary
self.hidableCellsDict = [NSMutableDictionary dictionary];
[self.hidableCellsDict setObject:[BlockExecutor executorWithBlock:^(){return self.birthdaySwitch.on;}] forKey:[NSIndexPath indexPathForRow:1 inSection:1]];
}
- (void)viewDidUnload
{
[self setBirthdaySwitch:nil];
[super viewDidUnload];
}
@end
तेजी से उत्तर दें :
अपने TableViewController में निम्न विधि जोड़ें:
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return indexPathOfCellYouWantToHide == indexPath ? 0 : super.tableView(tableView, heightForRowAtIndexPath: indexPath)
}
यदि tableView उस सेल को खींचने का प्रयास करता है जिसे आप छिपाना चाहते हैं, तो वह इसे प्रदर्शित नहीं करेगा, क्योंकि इसकी ऊँचाई ऊपर की विधि के लिए 0pt पर सेट की जाएगी, बाकी सब कुछ अनलक्ड रहता है।
कृपया ध्यान दें कि indexPathOfCellYouWantToHideकभी भी बदला जा सकता है :)
> स्विफ्ट 2.2 में, मैंने यहां कुछ उत्तर जोड़े हैं।
अपने स्टैटिकसेल से लिंक करने के लिए स्टोरीबोर्ड से एक आउटलेट बनाएं।
@IBOutlet weak var updateStaticCell: UITableViewCell!
override func viewDidLoad() {
...
updateStaticCell.hidden = true
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if indexPath.row == 0 {
return 0
} else {
return super.tableView(tableView, heightForRowAtIndexPath: indexPath)
}
}
मैं अपनी पहली सेल को छुपाना चाहता हूं, इसलिए मैंने ऊपर वर्णित के अनुसार ऊंचाई को 0 पर सेट किया है।
स्विफ्ट 4:
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
var height = super.tableView(tableView, heightForRowAt: indexPath)
if (indexPath.row == HIDDENROW) {
height = 0.0
}
return height
}
सबसे आसान परिदृश्य के लिए जब आप तालिका दृश्य के बहुत नीचे की कोशिकाओं को छिपाते हैं, तो आप सेल छिपाने के बाद तालिका दृश्य की सामग्री को समायोजित कर सकते हैं:
- (void)adjustBottomInsetForHiddenSections:(NSInteger)numberOfHiddenSections
{
CGFloat bottomInset = numberOfHiddenSections * 44.0; // or any other 'magic number
self.tableView.contentInset = UIEdgeInsetsMake(self.tableView.contentInset.top, self.tableView.contentInset.left, -bottomInset, self.tableView.contentInset.right);
}
Https://github.com/k06a/ABStaticTableViewController का उपयोग करके ऐसा करने का यह नया तरीका है
NSIndexPath *ip = [NSIndexPath indexPathForRow:1 section:1];
[self deleteRowsAtIndexPaths:@[ip] withRowAnimation:UITableViewRowAnimationFade]
K06a ( https://github.com/k06a/ABStaticTableViewController ) से समाधान बेहतर है, क्योंकि यह सेल हेडर और फुटर सहित पूरे खंड को छुपाता है, जहां यह समाधान ( https://github.com/peterpaulis-StaticDataTableViewController) ) पाद को छोड़कर सब कुछ छुपाता है।
संपादित करें
यदि आप पाद को छिपाना चाहते हैं तो मुझे इसका समाधान मिल गया है StaticDataTableViewController। इसे आपको StaticTableViewController.m फाइल में कॉपी करने की आवश्यकता है:
- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section {
if ([tableView.dataSource tableView:tableView numberOfRowsInSection:section] == 0) {
return nil;
} else {
return [super tableView:tableView titleForFooterInSection:section];
}
}
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
CGFloat height = [super tableView:tableView heightForFooterInSection:section];
if (self.originalTable == nil) {
return height;
}
if (!self.hideSectionsWithHiddenRows) {
return height;
}
OriginalSection * os = self.originalTable.sections[section];
if ([os numberOfVissibleRows] == 0) {
//return 0;
return CGFLOAT_MIN;
} else {
return height;
}
//return 0;
return CGFLOAT_MIN;
}
निश्चित रूप से आप कर सकते हैं। सबसे पहले, अपनी उन तालिका संख्याओं पर लौटें, जिन्हें आप दिखाना चाहते हैं, फिर superअपने स्टोरीबोर्ड से कुछ सेल प्राप्त करने के लिए कॉल करें और इसे तालिका दृश्य के लिए लौटा दें:
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.mode.numberOfCells()
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = super.tableView(tableView, cellForRowAtIndexPath: self.mode.indexPathForIndexPath(indexPath))
return cell
}
यदि आपकी कोशिकाओं में अलग-अलग वापसी होती है, तो यह भी:
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return super.tableView(tableView, heightForRowAtIndexPath: self.mode.indexPathForIndexPath(indexPath))
}
@ साले मासूम समाधान के अलावा:
यदि आपको ऑटो-लेआउट त्रुटियाँ मिलती हैं , तो आप बाधाओं को दूर कर सकते हैंtableViewCell.contentView
स्विफ्ट 3:
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
let tableViewCell = super.tableView(tableView, cellForRowAt: indexPath)
if tableViewCell.isHidden == true
{
tableViewCell.contentView.removeConstraints(tableViewCell.contentView.constraints)
return 0
}
else{
return super.tableView(tableView, heightForRowAt: indexPath)
}
}
यह समाधान आपके ऐप के प्रवाह पर निर्भर करता है । यदि आप सेल को एक ही व्यू कंट्रोलर इंस्टेंस में दिखाना / छिपाना चाहते हैं तो यह सबसे अच्छा विकल्प नहीं हो सकता है, क्योंकि यह बाधाओं को दूर करता है ।
मुझे स्थैतिक कोशिकाओं और यहां तक कि वर्गों को गतिशील रूप से बिना किसी हैक के छिपाने का एक बेहतर तरीका मिला।
पंक्ति की ऊँचाई को 0 पर सेट करने से एक पंक्ति छिपाई जा सकती है, लेकिन यह काम नहीं करता है यदि आप एक संपूर्ण खंड को छुपाना चाहते हैं जो कुछ पंक्तियों को छिपाएगा, भले ही आप सभी पंक्तियों को छिपाएँ।
मेरा दृष्टिकोण स्थिर कोशिकाओं के एक खंड सरणी का निर्माण करना है। तब तालिका दृश्य सामग्री अनुभाग सरणी द्वारा संचालित की जाएगी।
यहाँ कुछ नमूना कोड है:
var tableSections = [[UITableViewCell]]()
private func configTableSections() {
// seciton A
tableSections.append([self.cell1InSectionA, self.cell2InSectionA])
// section B
if shouldShowSectionB {
tableSections.append([self.cell1InSectionB, self.cell2InSectionB])
}
// section C
if shouldShowCell1InSectionC {
tableSections.append([self.cell1InSectionC, self.cell2InSectionC, self.cell3InSectionC])
} else {
tableSections.append([self.cell2InSectionC, self.cell3InSectionC])
}
}
func numberOfSections(in tableView: UITableView) -> Int {
return tableSections.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tableSections[section].count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
return tableSections[indexPath.section][indexPath.row]
}
इस प्रकार, आप पंक्तियों और वर्गों की संख्या की गणना करने के लिए गंदा कोड लिखने के बिना अपने सभी कॉन्फ़िगरेशन कोड को एक साथ रख सकते हैं। और हां, नहीं0 अब ऊंचाइयां नहीं।
यह कोड बहुत आसान रखरखाव भी है। उदाहरण के लिए, यदि आप अधिक सेल या अनुभाग जोड़ना / हटाना चाहते हैं।
इसी प्रकार, आप अपने सेक्शन के शीर्षक को गतिशील रूप से कॉन्फ़िगर करने के लिए एक अनुभाग शीर्ष लेख शीर्षक सरणी और अनुभाग पाद लेख शीर्षक सरणी बना सकते हैं।