यूआईटेबल व्यू सेक्शन के डिफॉल्ट स्क्रॉलिंग बिहेवियर को बदलें


147

मेरे पास दो खंडों के साथ एक UITableView है। यह एक साधारण टेबल व्यू है। मैं इन हेडर के लिए कस्टम दृश्य बनाने के लिए viewForHeaderInSection का उपयोग कर रहा हूं। अब तक सब ठीक है।

डिफ़ॉल्ट स्क्रॉलिंग व्यवहार यह है कि जब एक खंड का सामना किया जाता है, तो अनुभाग शीर्षलेखक नव बार के नीचे लंगर डाले रहता है, जब तक कि अगला खंड दृश्य में स्क्रॉल न हो जाए।

मेरा सवाल यह है: क्या मैं डिफ़ॉल्ट व्यवहार को बदल सकता हूं ताकि अनुभाग शीर्षकों को शीर्ष पर लंगर डाले न रहें, बल्कि, बाकी अनुभाग पंक्तियों के साथ नौसेना पट्टी के नीचे स्क्रॉल करें?

क्या मुझसे साफ़ - साफ़ कुछ चीज़ चूक रही है?

धन्यवाद।


1
इस साइट पर सबसे अच्छे लिखित प्रश्नों में से एक होना चाहिए! :) धन्यवाद।
फटी

1
इस प्रभाव को प्राप्त करने के सही तरीके के लिए यहां देखें stackoverflow.com/a/13735238/1880899
सुमित अनंतवार

जवाबों:


175

जिस तरह से मैंने इस समस्या को हल किया है वह इस तरह से (फैली हुई ) के contentOffsetअनुसार समायोजित करना है :contentInsetUITableViewControllerDelegateUIScrollViewDelegate

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
       CGFloat sectionHeaderHeight = 40;
   if (scrollView.contentOffset.y<=sectionHeaderHeight&&scrollView.contentOffset.y>=0) {
       scrollView.contentInset = UIEdgeInsetsMake(-scrollView.contentOffset.y, 0, 0, 0);
   } else if (scrollView.contentOffset.y>=sectionHeaderHeight) {
       scrollView.contentInset = UIEdgeInsetsMake(-sectionHeaderHeight, 0, 0, 0);
   }
}

केवल यहाँ समस्या यह है कि यह थोड़ा सा उछाल देता है जब ऊपर की ओर वापस स्क्रॉल किया जाता है।


{नोट: "40" आपके अनुभाग 0 हेडर की सटीक ऊंचाई होनी चाहिए। यदि आप एक ऐसी संख्या का उपयोग करते हैं जो आपके अनुभाग 0 हेडर की ऊँचाई से बड़ी है, तो आप देखेंगे कि फिंगर-फील प्रभावित होता है ("1000" की तरह प्रयास करें और आप देखेंगे कि उछाल का व्यवहार शीर्ष पर अजीब तरह का है)। यदि संख्या आपके सेक्शन 0 हेडर की ऊँचाई से मेल खाती है, तो लगता है कि उंगली एकदम सही है या निकट-परिपूर्ण है।}


1
ऊपर वाले की तुलना में सही समाधान।
प्रथुम्का

4
धन्यवाद! यह एक सही समाधान है। क्या आपके पास अनुभाग पाद लेख का हल है?
तुआन गुयेन

12
यह समाधान टैप-ऑन-मेनूबार को सही ढंग से नहीं संभालता है, जिसे सूची के शीर्ष पर स्क्रॉल करना है।
रीड एलिस

scrollView.contentInset = UIEdgeInsetsMake (0, 0, sectionHeaderHeight, 0): यदि u अनुभाग पाद लेख को देखने के लिए एक ही व्यवहार की जरूरत है सिर्फ इस तरह अंतिम पंक्ति को बदलने
एलेक्स

यह पर्याप्त प्रतीत होता है: स्क्रॉलव्यू. कॉन्टेंटइंटरसेट = यूआईईडेजइंसेट्समेक (स्क्रॉलव्यू. कॉन्टेंटऑफसेट.य> = 0; -scrollView.contentOffset.y: 0, 0, 0, 0);
मैकमार

85

आप शीर्ष पर शून्य पंक्तियों के साथ एक खंड भी जोड़ सकते हैं और बस पिछले अनुभाग के पाद लेख को अगले के लिए हेडर के रूप में उपयोग कर सकते हैं।


13
मेरे मामले में जहां मेरे पास 2 से अधिक अनुभाग हैं, पाद नीचे तल पर लंगर डालेगा ..
जोसेफ लिन

3
यदि आप एक NSFetchedResultsController तालिका लोड करने के लिए उपयोग कर रहे हैं तो यह रचनात्मक है, लेकिन आपको इंडेक्सपाथ को समायोजित करने की आवश्यकता है।
XJones

+1 अब तक का सबसे अच्छा समाधान - मुझे लागू करने के लिए 3 लाइनों की तरह लगा!
जॉन

ब्रिलियंट ब्रिलियंट ब्रिलिएंट :-)
आईपोनिक

पाद लेख के लिए यह कैसे काम करेगा? कुछ मदद की सराहना करेंगे! धन्यवाद
darwindeeds

36

क्या मैं ऐसा कर रहा था, मैं इस तथ्य का लाभ उठाऊंगा कि सादा शैली में UITableViews के पास चिपचिपा हेडर हैं और समूहित शैली में नहीं हैं। मैं शायद कम से कम एक समूहीकृत तालिका में सादा कोशिकाओं की उपस्थिति की नकल करने के लिए एक कस्टम टेबल सेल का उपयोग करने की कोशिश करूंगा।

मैंने वास्तव में यह कोशिश नहीं की है, इसलिए यह काम नहीं कर सकता है, लेकिन यह वही है जो मैं सुझाऊंगा।


शायद काम करेगा, लेकिन क्या यह कोशिश की गई है? और यह बहुत काम की तरह लगता है जब @ voidStern का जवाब पूरी तरह से काम करता है !!
bentford

जब मेरे पास दो से अधिक अनुभाग होते हैं तो voidStern का उत्तर मेरे लिए काम नहीं करता है। कॉलिन का उत्तर सरल / अधिक सुरुचिपूर्ण है, मैन्युअल रूप से अनुभाग संख्या को स्थानांतरित करने और अनुभाग की संख्या को जोड़ने की आवश्यकता के बिना।
जोसेफ लिन

सुझाव: tableView.separatorColor = [UIColor clearColor];एक सादे तालिका दृश्य की नकल करने के लिए उपयोग करें।
जोसेफ लिन

3
मैंने ऐसा करने की कोशिश की, लेकिन जब मैं समूहीकृत टेबल सेल को सादे लोगों की तरह नहीं बना सकता था, तो कोशिकाओं के दोनों ओर बाएं और दाएं मार्जिन हटा दें। आपने इसे कैसे किया?
एडम कार्टर

1
UITableViewStyle यानी समूहीकृत और सादे के बारे में बातें स्पष्ट करने के लिए बहुत-बहुत धन्यवाद, जो यह तय करता है कि टेबलव्यू के सेक्शन हेडर / पाद लेख चिपचिपे होंगे या नहीं। बहुत बहुत धन्यवाद @ कोलिन बैरेट
धवल एच। नेना

28

मुझे पता है कि यह देर से आता है, लेकिन मुझे निश्चित समाधान मिल गया है!

आप क्या करना चाहते हैं यदि आपके पास 10 अनुभाग हैं, तो डेटा स्रोत को 20 पर वापस आने दें। अनुभाग हेडर के लिए भी संख्याओं का उपयोग करें, और अनुभाग सामग्री के लिए विषम संख्याओं का उपयोग करें। कुछ इस तरह

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    if (section%2 == 0) {
        return 0;
    }else {
        return 5;
    }
}

-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    if (section%2 == 0) {
        return [NSString stringWithFormat:@"%i", section+1];
    }else {
        return nil;
    }
}

देखा! : डी


महान विचार। लेकिन अगर आपके पास अनुभाग अनुक्रमणिका शीर्षक हैं, तो मुझे संदेह है कि यह उन्हें गड़बड़ कर देगा।
14

क्यों? आप अनुभाग शीर्षकों के साथ भी ऐसा कर सकते हैं। बस विषम संख्या के लिए nil याद रखें और सम संख्या के लिए एक शीर्षक।
लोकोमाइक

1
हाँ - यह तरीका बहुत अच्छा काम करता है। यह बहुत अधिक बहीखाता पद्धति थी (शायद मुझे अनुभाग के शीर्षक प्राप्त करने के तरीके के साथ करना है) लेकिन इसने काम किया। चाल यह है कि numberOfRowsInSection और cellForRowAtIndexPath का उपयोग करता है (धारा 2%! = 0 और& अनुभाग! = 0) जबकि शीर्षकफ़ोरहेन्डरइन्सेक्शन और अन्य अनुभाग फ़ंक्शंस का उपयोग करते हैं यदि (अनुभाग% 2 == 0)
roocell

प्रवर्तक को उत्तर के रूप में इसे चुनना चाहिए। यह बहुत अच्छा होगा यदि अनुभाग शीर्षकों को स्वचालित रूप से लंगर करने के लिए उपप्रकार को उपवर्ग करने का एक तरीका था।
16

यह मेरे लिए सबसे अच्छा काम किया। मैंने पहले @ कॉलिन के समाधान की कोशिश की, लेकिन यह उस भारी अनुकूलित के साथ अच्छी तरह से काम नहीं कर पाया UITableViewजिसका मैं उपयोग कर रहा हूं।
कुबि

15

कई चीजें हैं जो इस समस्या को गैर-हैकी तरीके से हल करने के लिए आवश्यक हैं:

  1. तालिका दृश्य शैली सेट करें UITableViewStyleGrouped
  2. तालिका दृश्य सेट backgroundColorकरने के लिए[UIColor clearColor]
  3. backgroundViewप्रत्येक तालिका दृश्य कक्ष पर एक रिक्त दृश्य के साथ सेट करेंbackgroundColor [UIColor clearColor]
  4. यदि आवश्यक हो, तो तालिका दृश्य को rowHeightउचित रूप से सेट करें , या tableView:heightForRowAtIndexPath:यदि अलग-अलग पंक्तियों में अलग-अलग ऊंचाइयां हैं, तो ओवरराइड करें ।

(+1) @ नील, मैंने आपका उत्तर देने की कोशिश की लेकिन दुर्भाग्य से, UITableViewStyleGroupedटेबल की कोशिकाओं के लिए अतिरिक्त मार्जिन है जो हेडर के साथ उनके संरेखण को बदलते हैं। यह एक समस्या है जब आप वास्तव में एक बहु-स्तंभ तालिका का चित्रण करना चाहते हैं और स्तंभ शीर्षकों को दिखाने के लिए शीर्ष लेख का उपयोग करते हैं (और फिर इन शीर्षकों के साथ व्यक्तिगत तालिका प्रविष्टियाँ संरेखित करें)।
ब्रेनजम

15

मूल रूप से यहां पोस्ट किया गया है , आईबी का उपयोग करके एक त्वरित समाधान। वही प्रोग्राम किया जा सकता है हालांकि काफी सरल है।

इसे प्राप्त करने का संभवतः एक आसान तरीका (आईबी का उपयोग करके):

अपने हेडर दृश्य को बनाने के लिए अपने टेबल व्यू पर एक UIView खींचें।

  1. उस शीर्ष लेख दृश्य ऊंचाई को 100px पर सेट करें
  2. तालिका-सामग्री सेट करें। प्रारंभ (शीर्ष) से ​​-100
  3. अनुभाग हेडर अब किसी भी नियमित सेल की तरह स्क्रॉल करेंगे।

कुछ लोगों ने टिप्पणी करते हुए कहा कि यह समाधान पहले शीर्षलेख को छुपाता है, हालांकि मैंने इस तरह के किसी भी मुद्दे पर ध्यान नहीं दिया है। यह मेरे लिए पूरी तरह से काम करता था और अब तक का सबसे सरल समाधान था जो मैंने अब तक देखा है।


ध्यान दें कि आपको क्लीयर कलर के बैकग्राउंड कलर का उपयोग करने के लिए संभवतः दृश्य सेट करना चाहिए, अन्यथा यदि आप शीर्ष को स्क्रॉल करते हैं तो आपको उछाल में सफेद दिखाई देता है।
डॉक

3
यह मेरे पहले हेडर को छुपाता है
लीना

लीना, आईओएस के किस संस्करण पर आप चल रहे हैं? क्या दृश्य UITableViewController है, या इसमें UITableView के साथ एक UIView है? मुझे यकीन नहीं है कि कुछ लोगों के लिए यह समाधान पहले हेडर को छुपाता है इसलिए मैं किसी भी विसंगतियों को खोजने की कोशिश कर रहा हूं।
डॉक्टर

यह समाधान एकदम सही है। मैं एक अनंत शीर्ष और नीचे सेल पृष्ठभूमि उपस्थिति की तलाश में हूँ - यह पूरी तरह से इसे पूरा करता है। अच्छा!
टेलर हॉलिडे

यह समाधान उत्कृष्ट है। इस सूत्र में अन्य उत्तरों की तुलना में आसान है। मेरी राय में, यह स्वीकृत उत्तर होना चाहिए।
जॉन रोजर्स

15

मैं यहाँ वर्णित समाधानों से खुश नहीं था, इसलिए मैंने उन्हें संयोजित करने का प्रयास किया। परिणाम निम्न कोड है, जो @awulf और @cescofry से प्रेरित है। यह मेरे लिए काम करता है क्योंकि मेरे पास कोई वास्तविक टेबल व्यू हैडर नहीं है। यदि आपके पास पहले से ही टेबल व्यू हैडर है, तो आपको ऊंचाई समायोजित करनी पड़ सकती है।

// Set the edge inset
self.tableView.contentInset = UIEdgeInsetsMake(-23.0f, 0, 0, 0);

// Add a transparent UIView with the height of the section header (ARC enabled)
[self.tableView setTableHeaderView:[[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 100.0f, 23.0f)]];

यह एक सरल समाधान था जो मैंने पाया।
जोरावर

इसने मेरे लिए iOS9.2 पर काम किया, इसलिए एक पुराने उत्तर के बावजूद, यह अभी भी मान्य है। और इसने पहले सेक्शन के हेडर को नहीं छिपाया। काम करता है, और पूरी तरह से काम करता है।
idStar

उत्तम। यदि आपके टेबलव्यू में पहले से ही एक हेडर है, तो ऑफसेट द्वारा इसकी ऊंचाई बढ़ाएं, फिर कंटेंट को मूल स्थिति में शिफ्ट करने के लिए हेडर कंटेंट के शीर्ष अवरोध को बढ़ाएं
जेसन

14

बस तालिका दृश्य शैली बदलें:

self.tableview = [[UITableView alloc] initwithFrame:frame style:UITableViewStyleGrouped];

UITableViewStyle प्रलेखन :

UITableViewStylePlain- एक सादा तालिका दृश्य। किसी भी अनुभाग शीर्षलेख या पाद लेख को इनलाइन विभाजक के रूप में प्रदर्शित किया जाता है और तालिका दृश्य स्क्रॉल होने पर तैरता है।

UITableViewStyleGrouped- एक तालिका दृश्य जिसके अनुभाग पंक्तियों के विभिन्न समूहों को प्रस्तुत करते हैं। अनुभाग शीर्ष लेख और पाद लेख फ्लोट नहीं करते हैं।


महान जवाब, मेरे लिए काम किया। आसपास किसी काम की जरूरत नहीं
शम्स अहमद

9

समूहीकृत तालिका दृश्य शैली का चयन करें

स्टोरीबोर्ड में अपने तालिका दृश्य के गुण निरीक्षक से समूहीकृत तालिका दृश्य शैली का चयन करें।


5

अनुभाग दृश्य में हेडर की समान ऊंचाई के साथ पारदर्शी दृश्य के साथ तालिका के शीर्ष लेख देखें। ऐ-फ्रेम के साथ टेबलव्यू को भी देखें।

self.tableview = [[UITableView alloc] initWithFrame:CGRectMake(0, - height, 300, 400)];

UIView *headerView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, width, height)] autorelease];
[self.tableView setTableHeaderView:headerView];

4

मुझे एक वैकल्पिक समाधान मिला, एक वास्तविक हेडर अनुभाग के बजाय प्रत्येक अनुभाग के पहले सेल का उपयोग करें, यह समाधान इतना साफ नहीं दिखाई देता है, लेकिन इतना अच्छा काम करता है, आप अपने हेडर अनुभाग के लिए एक परिभाषित प्रोटोटाइप सेल का उपयोग कर सकते हैं, और विधि सेल में ForRowAndexPath indexPath.row == 0 के लिए पूछें, यदि सही है, तो हेडर सेक्शन प्रोटोटाइप सेल का उपयोग करें, अन्यथा अपने डिफ़ॉल्ट प्रोटोटाइप सेल का उपयोग करें।


यदि आप अभी भी indexPath.row& के साथ काम करना चाहते हैं indexPath.section, तो सुनिश्चित करें कि आप के 0.0fलिए एक ऊँचाई वापस कर दें - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)sectionताकि आपके हेडर अदृश्य हों।
सूप

4

अपनी तालिका दृश्य शैली बदलें:

self.tableview = [[UITableView alloc] initwithFrame:frame style:UITableViewStyleGrouped];

UITableView के लिए सेब प्रलेखन के अनुसार:

UITableViewStylePlain- एक सादा तालिका दृश्य। किसी भी अनुभाग शीर्षलेख या पाद लेख को इनलाइन विभाजक के रूप में प्रदर्शित किया जाता है और तालिका दृश्य स्क्रॉल होने पर तैरता है।

UITableViewStyleGrouped- एक तालिका दृश्य जिसके अनुभाग पंक्तियों के विभिन्न समूहों को प्रस्तुत करते हैं। अनुभाग शीर्ष लेख और पाद लेख फ्लोट नहीं करते हैं। आशा है यह छोटा सा बदलाव आपकी मदद करेगा ।।


2

अब जब समूहीकृत शैली मूल रूप से iOS 7 (सपाट और पृष्ठभूमि के संदर्भ में) में सादे शैली के समान दिखती है, तो हमारे लिए सबसे अच्छा और सबसे आसान (यानी कम से कम हैकी) निर्धारण केवल तालिका दृश्य की शैली को समूहीकृत करने के लिए बदलना था। जब हम शीर्ष पर एक स्क्रॉल-दूर नौसेना बार एकीकृत करते हैं, तो सामग्री के साथ जैकिंग हमेशा एक समस्या थी। एक समूहीकृत तालिका दृश्य शैली के साथ, यह बिल्कुल वैसा ही दिखता है (हमारी कोशिकाओं के साथ) और अनुभाग हेडर स्थिर रहते हैं। कोई स्क्रॉलिंग अजीबता नहीं।


यह सबसे अच्छा समाधान है, खासकर यदि कोशिकाएं कस्टम हैं, तो स्क्रॉल शीर्ष पर हिट होने पर अनुभाग हेडर के "होल्ड" को बस रोकना लगता है।
पुनर्नवीनीकरण स्टील

1

अपने टेबल व्यू में एक नकारात्मक इनसेट असाइन करें। यदि आपके पास 22px हाई सेक्शन हेडर हैं, और आप नहीं चाहते कि आप उन्हें पुनः लोड करें, तो सही होने के बाद आप पुनः लोड करें:

self.tableView.contentInset = UIEdgeInsetsMake(-22, 0, 0, 0); 
self.tableView.contentSize = CGSizeMake(self.tableView.contentSize.width, self.tableView.contentSize.height+22); 

मेरे लिए एक आकर्षण की तरह काम करता है। सेक्शन फुटर्स के लिए भी काम करता है, बस इसके बजाय नीचे की तरफ निगेटिव इनसेट असाइन करें।


यह सिर्फ पहले शीर्ष लेख को काट देता है ??
कैन्यबॉय

मेरे लिए पूरी तरह से काम किया !! साभार
डैनियल

0

मैं एक स्क्रॉल दृश्य में तालिका जोड़ता हूं और यह अच्छी तरह से काम करता है।



0

@ लोकोमाइक के जवाब ने मेरे टेबल व्यू को बेहतरीन तरीके से फिट किया, हालांकि फुटर्स का उपयोग करते समय यह टूट गया। इसलिए, शीर्षकों और पादों का उपयोग करते समय यह सही समाधान है:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return (self.sections.count + 1) * 3;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    if (section % 3 != 1) {
        return 0;
    }
    section = section / 3;
    ...
}

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
    if (section % 3 != 0) {
        return nil;
    }
    section = section / 3;
    ...
}

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    if (section % 3 != 0) {
        return 0;
    }
    section = section / 3;
    ...
}

- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
    if (section % 3 != 2) {
        return 0;
    }
    section = section / 3;
    ...
}

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    if (section % 3 != 0) {
        return nil;
    }
    section = section / 3;
    ...
}

- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
{
    if (section % 3 != 2) {
        return nil;
    }
    section = section / 3;
    ...
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    int section = indexPath.section;
    section = section / 3;
    ...
}

0

@Awulf उत्तर का स्विफ्ट संस्करण, जो बहुत अच्छा काम करता है!

func scrollViewDidScroll(scrollView: UIScrollView) {
    let sectionHeight: CGFloat = 80
    if scrollView.contentOffset.y <= sectionHeight {
        scrollView.contentInset = UIEdgeInsetsMake( -scrollView.contentOffset.y, 0, 0, 0)
    }else if scrollView.contentOffset.y >= sectionHeight {
        scrollView.contentInset = UIEdgeInsetsMake(-sectionHeight, 0, 0, 0)
    }
}

-2

मैंने सीखा है कि बस tableHeaderView गुण सेट करना है, यानी:

 tableView.tableHeaderView = customView;

और बस।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.