2009-12-22 14 views
13

क्या किसी ने आईफोन के लिए "एग्रीजन" (शायद "एनिमेटेड रूपरेखा" कहा जाता है) के कार्यान्वयन को देखा है? मुझे कोको के लिए एक उदाहरण प्रोजेक्ट मिला, लेकिन एक बंदरगाह की कोशिश करने से पहले, मैं उम्मीद कर रहा था कि किसी ने पहले ही पहिया का आविष्कार किया है।आईफोन एसडीके ऐप के लिए एग्रीजन व्यू कैसे कार्यान्वित करें?

इसे स्पष्ट करने के लिए, एक UIView में, अनुभागों का एक ढेर, प्रत्येक में एक शीर्षलेख, और फिर कुछ सामग्री पर विचार करें। जब उपयोगकर्ता हेडर को छूता है (या कुछ संदेश/घटना के माध्यम से), यदि अनुभाग पहले से खुला है => इसे बंद करें; अगर अनुभाग बंद है => इसे खोलें और किसी भी अन्य खुले खंड को बंद करें। JQuery में एक उदाहरण इस तरह दिखता है: http://docs.jquery.com/UI/Accordion

मेरे मामले में, मैं प्रत्येक अनुभाग में कोई भी UIView सामग्री डाल सकता हूं।

मुझे कुछ वास्तविक ऐप्स देखने में दिलचस्पी होगी जिन्होंने इसे कार्यान्वित किया है - बस यह जानना संभव है!

+3

कुछ भी संभव है! –

+0

@Jacob सबकुछ संभव नहीं है! Http://stackoverflow.com/questions/4962539/creating-generic-method-names-in-generic-class देखें। ;) – jakev

+0

https://github.com/nacho4d/Accordion पर एक नज़र डालें यह आईपैड के लिए एकॉर्डन-स्टाइल नेविगेशन लागू करता है, वहां आप देख सकते हैं कि सब कुछ कैसे काम करता है! – myell0w

उत्तर

18

मैं सिर्फ यूआईटीबल व्यू का उपयोग करता हूं, प्रत्येक सेल की ऊंचाई इस पर निर्भर करता है कि यह "खुला" है या नहीं और फिर वहां से जाएं। पंक्तियों का आकार बदलना आसान है और आप संयुक्त कोशिकाओं के लिए कुल ऊंचाई UITableView में उपलब्ध ऊंचाई हो सकते हैं ताकि यह केवल एक तालिका से अधिक accordion जैसा दिखता हो।

यह एक त्वरित हैक कि काम करना चाहिए है, लेकिन अपने UITableViewController उपवर्ग के ज फ़ाइल में:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 
    return 1; 
} 

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 
    return 4; 
} 

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { 
    if (sectionopen[indexPath.row]) { 
     return 240;///it's open 
    } else { 
     return 45;///it's closed 
    } 

} 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
    UITableViewCell *mycell = [[[UITableViewCell alloc] init] autorelease]; 
    mycell.textLabel.text= @"Section Name"; 
    return mycell; 
} 


- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 
    ///turn them all off 
    sectionopen[0]=NO; 
    sectionopen[1]=NO; 
    sectionopen[2]=NO; 
    sectionopen[3]=NO; 

    ///open this one 
    sectionopen[indexPath.row]=YES; 

    ///animate the opening and expand the row 
    [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationFade]; 
} 

यह मूलतः ले जाएगा:

bool sectionopen[4]; ///or some other way of storing the sections expanded/closed state 

और .m फ़ाइल में की तरह कुछ डाल 4 पंक्तियों और उन्हें ढहने वाले वर्गों में बदल दें जहां एक पंक्ति का चयन 240 पिक्सल तक बढ़ाएगा और अन्य सभी पंक्तियों को 40 तक गिर जाएगी। आप उन सभी संख्याओं को बदल सकते हैं और अनुभागों को समझ सकते हैं और जो कुछ भी आप चाहते हैं उसे कर सकते हैं।

मैंने इसे आजमाया है और यह काम करता है। इसके बाद आप किसी भी अनुभाग को जोड़ने के लिए अन्य सेल सामग्री कोड को जोड़कर इसे पूरा कर सकते हैं (संभवतः एक स्क्रॉलिंग UITextView सहित यदि आप चाहें)।

2

मैं बस इस पर ठोकर खाई और mjdth का समाधान बहुत सीधे आगे और सहायक पाया। हालांकि, अगर आप propoesed reloadSections विधि के बजाय

[self.tableView reloadRowsAtIndexPaths: paths withRowAnimation:UITableViewRowAnimationBottom]; 

उपयोग करने के लिए के रूप में फिर से लोड पंक्तियों आप अधिक सहज संक्रमण देता है चाहते हो सकता है।

1

यहां CollapsingTableViewDelegate कक्षा है जिसे मैं वर्तमान में ऐसा करने के लिए काम कर रहा हूं। यह केवल स्थिर तालिका सामग्री के साथ काम करता है।

आप इस कक्षा में CollapsingTableCellDelegate कार्यान्वयन की आपूर्ति करते हैं, जो प्रत्येक पंक्ति के ध्वस्त और विस्तारित आकारों की गणना करने के लिए और प्रत्येक पंक्ति के लिए UIView कैसे बनाएं, यह जानना चाहिए। दृश्य वही रहता है चाहे वह ध्वस्त हो या विस्तारित हो, ताकि प्रत्येक पंक्ति के दृश्य का शीर्ष स्लीवर उस पंक्ति के क्लिक करने योग्य शीर्षलेख के रूप में कार्य करता हो।

फिर आप इस कक्षा को डेटास्रोत और UITableView के लिए प्रतिनिधि बनाते हैं।

हैडर फ़ाइल CollapsingTableViewDelegate.h:

#import <UIKit/UIKit.h> 

@protocol CollapsingTableCellDelegate<NSObject> 

@required 
- (CGFloat)collapsingCellHeightForRow:(int)row expanded:(BOOL)expanded; 
- (UIView *)collapsingCellViewForRow:(int)row; 

@optional 
- (BOOL)collapsingCellAllowCollapse:(int)row; 

@end 

struct cell; 

@interface CollapsingTableViewDelegate : NSObject <UITableViewDelegate, UITableViewDataSource> { 
    id<CollapsingTableCellDelegate> cellDelegate; 
    int numCells; 
    int currentSelection; 
    struct cell *cells; 
} 

@property (nonatomic, retain, readonly) id<CollapsingTableCellDelegate> cellDelegate; 
@property (nonatomic, assign, readonly) int numCells; 
@property (nonatomic, assign) int currentSelection; 
@property (nonatomic, assign, readonly) struct cell *cells; 

- (CollapsingTableViewDelegate *)initWithCellDelegate:(id<CollapsingTableCellDelegate>)delegate numCells:(int)numCells; 
- (void)tableView:(UITableView *)tableView touchRow:(int)newSelection; 

@end 

और स्रोत फ़ाइल CollapsingTableViewDelegate.m:

#import "CollapsingTableViewDelegate.h" 

@implementation CollapsingTableViewDelegate 

struct cell { 
    u_char expanded; 
    u_char collapsable; 
}; 

@synthesize cellDelegate; 
@synthesize currentSelection; 
@synthesize cells; 
@synthesize numCells; 

#pragma mark - 
#pragma mark Setup and Teardown 

- (CollapsingTableViewDelegate *)initWithCellDelegate:(id<CollapsingTableCellDelegate>)delegate numCells:(int)num { 
    if ([super init] == nil) 
     return nil; 
    if ((cells = calloc(num, sizeof(*cells))) == NULL) { 
     [self autorelease]; 
     return nil; 
    } 
    cellDelegate = [delegate retain]; 
    numCells = num; 
    for (int row = 0; row < self.numCells; row++) { 
     struct cell *const cell = &self.cells[row]; 

     cell->collapsable = ![self.cellDelegate respondsToSelector:@selector(collapsingCellAllowCollapse:)] 
      || [self.cellDelegate collapsingCellAllowCollapse:row]; 
     cell->expanded = !cell->collapsable; 
    } 
    currentSelection = -1; 
    return self; 
} 

- (void)dealloc { 
    [cellDelegate release]; 
    free(cells); 
    [super dealloc]; 
} 

- (void)tableView:(UITableView *)tableView reloadRow:(int)row fade:(BOOL)fade { 
    [tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:row inSection:0]] 
        withRowAnimation:fade ? UITableViewRowAnimationFade : UITableViewRowAnimationNone]; 
} 

- (void)tableView:(UITableView *)tableView touchRow:(int)newSelection { 

    // Sanity check 
    if (newSelection < -1 || newSelection >= self.numCells) { 
     NSLog(@"CollapsingTableViewDelegate: invalid row %d not in the range [-1..%d)", newSelection, self.numCells); 
     return; 
    } 

    // Gather info 
    int oldSelection = self.currentSelection; 
    BOOL sameCellSelected = newSelection == oldSelection; 
    struct cell *const oldCell = oldSelection != -1 ? &self.cells[oldSelection] : NULL; 
    struct cell *const newCell = newSelection != -1 ? &self.cells[newSelection] : NULL; 

    // Mark old cell as collapsed and new cell as expanded 
    if (newCell != NULL) 
     newCell->expanded = TRUE; 
    if (oldCell != NULL) 
     oldCell->expanded = FALSE; 
    self.currentSelection = sameCellSelected ? -1 : newSelection; 

    // Update table view 
    if (oldSelection >= newSelection) { 
     if (oldSelection != -1) 
      [self tableView:tableView reloadRow:oldSelection fade:sameCellSelected]; 
     if (newSelection != -1 && !sameCellSelected) 
      [self tableView:tableView reloadRow:newSelection fade:TRUE]; 
    } else { 
     if (newSelection != -1 && !sameCellSelected) 
      [self tableView:tableView reloadRow:newSelection fade:TRUE]; 
     if (oldSelection != -1) 
      [self tableView:tableView reloadRow:oldSelection fade:sameCellSelected]; 
    } 

    // If expanding a cell, scroll it into view 
    if (newSelection != -1 && !sameCellSelected) { 
     [tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:newSelection inSection:0] 
         atScrollPosition:UITableViewScrollPositionTop 
           animated:TRUE]; 
    } 
} 

#pragma mark - 
#pragma mark Table view data source 

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 
    return 1; 
} 

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 
    return self.numCells; 
} 

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { 
    int row = [indexPath row]; 
    struct cell *const cell = &self.cells[row]; 
    return [self.cellDelegate collapsingCellHeightForRow:row expanded:cell->expanded]; 
} 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
    int row = [indexPath row]; 
    UIView *cellView = [self.cellDelegate collapsingCellViewForRow:row]; 
    [cellView removeFromSuperview]; 
    UITableViewCell *tvcell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil] autorelease]; 
    [tvcell.contentView addSubview:cellView]; 
    tvcell.clipsToBounds = TRUE; 
    tvcell.selectionStyle = UITableViewCellSelectionStyleNone; 
    return tvcell; 
} 

#pragma mark - 
#pragma mark Table view delegate 

- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath { 
    int row = [indexPath row]; 
    struct cell *const cell = &self.cells[row]; 
    return cell->collapsable ? indexPath : nil; 
} 

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)newSelection { 
    [tableView deselectRowAtIndexPath:newSelection animated:TRUE]; 
    [self tableView:tableView touchRow:[newSelection row]]; 
} 

@end 

नहीं पूर्णता, लेकिन मूल रूप से मेरे लिए काम करने लगता है।

16

हर समाधान है कि मैं UITableView, जो मेरे लिए काम नहीं किया उपयोग कर रहा था, क्योंकि मैं तालिका डेटा प्रदर्शित नहीं किया था मिल गया। यही कारण है कि मैंने AccordionView नियंत्रण बनाया। प्रयोग बिल्कुल स्पष्ट है:

AccordionView *accordion = [[AccordionView alloc] initWithFrame:CGRectMake(0, 0, 320, 420)]; 
[self addSubview:accordion]; 

// Only height is taken into account, so other parameters are just dummy 
UIButton *header1 = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 0, 30)]; 
[header1.titleLabel setText:@"First row"]; 

UIView *view1 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, 200)]; 
// ... add subviews to view1 

[accordion addHeader:header1 withView:view1]; 

// ... add more panels 

[accordion setSelectedIndex:0]; 

वास्तविक जीवन में यह इस तरह दिखता है:

enter image description here

काले सलाखों हेडर रहे हैं और आप उन सब को आप चाहते हैं (मैं three20 उपयोग कर रहा हूँ) अनुकूलित कर सकते हैं।

+0

हाय सुदा, नियंत्रण के लिए धन्यवाद। मैंने इसका उपयोग करने में एक छोटा सा झटका मारा है। मैंने प्रोजेक्ट के गिथब पर एक मुद्दा [यहां] (https://github.com/appsome/AccordionView/issues/11) खोला है। क्या आप कृपया एक नज़र डालें? – Isuru

+0

निश्चित रूप से, मैं अभी जवाब दे रहा हूं :) – suda

+0

हाय सुदा, आपके काम के लिए बहुत बहुत धन्यवाद। यहां मैंने एक छोटी सी समस्या खोली है। कृपया एक नज़र डालें। https://github.com/appsome/AccordionView/issues/23 –

4

मैं इस कोड मिला: अकॉर्डियन का एक सरल कार्यान्वयन ..

https://github.com/kuon/ios-example-accordion

मुझे आशा है कि यह कुछ एक में मदद मिलेगी ..

संबंधित मुद्दे