2012-11-19 13 views
8

में मैं प्रत्येक कोशिका में UIImageView के साथ एक UICollectionView है, अब मैं Photos.app में कॉपी कॉल आउट जोड़ने के लिए, की तरह हैं:कॉपी कॉलआउट UICollectionView

enter image description here

मैं UICollectionViewDelegate में इस विधि देखा:

- (BOOL)collectionView:(UICollectionView *)collectionView shouldShowMenuForItemAtIndexPath:(NSIndexPath *)indexPath { 
    return YES; 
} 

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

क्या मैं सही रास्ते पर हूं? आप इस सुविधा को कैसे कार्यान्वित कर सकते हैं?

उत्तर

9

यह पूर्ण समाधान है:

- (BOOL)collectionView:(UICollectionView *)collectionView shouldShowMenuForItemAtIndexPath:(NSIndexPath *)indexPath { 
     return YES; 
    } 

- (BOOL)collectionView:(UICollectionView *)collectionView canPerformAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender { 
     if ([NSStringFromSelector(action) isEqualToString:@"copy:"]) 
      return YES; 
     else 
      return NO; 
    } 

- (void)collectionView:(UICollectionView *)collectionView performAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender { 
     if ([NSStringFromSelector(action) isEqualToString:@"copy:"]) { 
      UIPasteboard *pasteBoard = [UIPasteboard pasteboardWithName:UIPasteboardNameGeneral create:NO]; 
      pasteBoard.persistent = YES; 
      NSData *capturedImageData = UIImagePNGRepresentation([_capturedPhotos objectAtIndex:indexPath.row]); 
      [pasteBoard setData:capturedImageData forPasteboardType:(NSString *)kUTTypePNG]; 
     } 
    } 

मेरे मामले में, मैं अपने CollectionView में केवल प्रति सुविधा की इजाजत दी कर रहा हूँ, और अगर प्रति दबाया जाता है, मैं छवि के अंदर है कि कॉपी करने कर रहा हूँ पेस्टबोर्ड पर सेल।

+0

हाँ आप केवल इन 3 तरीकों की जरूरत है (इस विधि अपने कस्टम कार्रवाई के लिए कहा जाता है नहीं है, मैं सिर्फ uicollectionview अस्तित्व के लिए जाँच करता है लगता है)। कुछ और अनावश्यक है। –

+0

धन्यवाद, मैंने आपको समाधान की कोशिश की, जबकि UIMenuItem * menuItem = [[UIMenuItem alloc] initWithTitle: @ "संपादित करें" कार्रवाई: @selector (editPlate :)]; हालांकि, मुझे एक विधि संपादन प्लेलेट की आवश्यकता है लेकिन मैं performAction का उपयोग करना चाहता हूं, इसलिए मैं सेल आईडी जान सकता हूं। आप मेनू आइटम का पता कैसे लगाते हैं? – Dejell

18

हाँ आप सही रास्ते पर हैं। आप इस तकनीक का उपयोग कर कट, कॉपी, पेस्ट से परे कस्टम क्रियाओं को भी कार्यान्वित कर सकते हैं।

Custom actions for the UICollectionView

// ViewController.h 
@interface ViewController : UICollectionViewController 

// ViewController.m 
-(void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    self.collectionView.delegate = self; 

    UIMenuItem *menuItem = [[UIMenuItem alloc] initWithTitle:@"Custom Action" 
                 action:@selector(customAction:)]; 
    [[UIMenuController sharedMenuController] setMenuItems:[NSArray arrayWithObject:menuItem]]; 

} 

#pragma mark - UICollectionViewDelegate methods 
- (BOOL)collectionView:(UICollectionView *)collectionView 
     canPerformAction:(SEL)action 
    forItemAtIndexPath:(NSIndexPath *)indexPath 
      withSender:(id)sender { 
    return YES; // YES for the Cut, copy, paste actions 
} 

- (BOOL)collectionView:(UICollectionView *)collectionView 
shouldShowMenuForItemAtIndexPath:(NSIndexPath *)indexPath { 
    return YES; 
} 

- (void)collectionView:(UICollectionView *)collectionView 
     performAction:(SEL)action 
    forItemAtIndexPath:(NSIndexPath *)indexPath 
      withSender:(id)sender { 
    NSLog(@"performAction"); 
} 

#pragma mark - UIMenuController required methods 
- (BOOL)canBecomeFirstResponder { 
    // NOTE: The menu item will on iOS 6.0 without YES (May be optional on iOS 7.0) 
    return YES; 
} 

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender { 
    NSLog(@"canPerformAction"); 
    // The selector(s) should match your UIMenuItem selector 
    if (action == @selector(customAction:)) { 
     return YES; 
    } 
    return NO; 
} 

#pragma mark - Custom Action(s) 
- (void)customAction:(id)sender { 
    NSLog(@"custom action! %@", sender); 
} 

नोट: iOS 7.0 परिवर्तन व्यवहार

  1. अपने UICollectionViewCell उपवर्ग में आप कस्टम क्रिया विधियों को जोड़ने के लिए, या कुछ भी नहीं की आवश्यकता होगी दिखाई देगा।

    // Cell.m 
    #import "Cell.h" 
    
    @implementation Cell 
    
    - (id)initWithFrame:(CGRect)frame { 
        self = [super initWithFrame:frame]; 
        if (self) { 
         // custom logic 
        } 
        return self; 
    } 
    
    - (void)customAction:(id)sender { 
        NSLog(@"Hello"); 
    
        if([self.delegate respondsToSelector:@selector(customAction:forCell:)]) { 
         [self.delegate customAction:sender forCell:self]; 
        } 
    } 
    @end 
    
  2. आप एक प्रतिनिधि प्रोटोकॉल बना सकते हैं और हर सेल पर सेट वापस UIController कि आपके UICollectionView का कहना है करने के लिए कॉल करने के लिए की आवश्यकता होगी। ऐसा इसलिए है क्योंकि सेल को आपके मॉडल के बारे में कुछ भी नहीं होना चाहिए, क्योंकि यह केवल सामग्री प्रदर्शित करने में शामिल है।

    // Cell.h 
    #import <UIKit/UIKit.h> 
    
    @class Cell; // Forward declare Custom Cell for the property 
    
    @protocol MyMenuDelegate <NSObject> 
    @optional 
    - (void)customAction:(id)sender forCell:(Cell *)cell; 
    @end 
    
    @interface Cell : UICollectionViewCell 
    
    @property (strong, nonatomic) UILabel* label; 
    @property (weak, nonatomic) id<MyMenuDelegate> delegate; 
    @end 
    
  3. अपने ViewController या UICollectionViewController के उपवर्ग आप प्रोटोकॉल के अनुरूप और नई विधि को लागू करने की आवश्यकता होगी में

    // ViewController.m 
    @interface ViewController() <MyMenuDelegate> 
    @end 
    
    // @implementation ViewController ... 
    
    - (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath; 
    { 
        Cell *cell = [cv dequeueReusableCellWithReuseIdentifier:@"MY_CELL" forIndexPath:indexPath]; 
        cell.delegate = self; 
        return cell; 
    } 
    // ... 
    
    // Delegate method for iOS 7.0 to get action from UICollectionViewCell 
    - (void)customAction:(id)sender forCell:(Cell *)cell { 
        NSLog(@"custom action! %@", sender); 
    } 
    

    Custom longpress action menu for UICollectionView

  4. वैकल्पिक: अपने UIView उपवर्ग में आप डिफ़ॉल्ट कट, कॉपी ओवरराइड कर सकते हैं, पेस्ट करें यदि आप बल्कि UIViewController की तुलना में यहां विधि canPerformAction लागू,। अन्यथा व्यवहार आपके कस्टम तरीकों से पहले डिफ़ॉल्ट विधियों को दिखाएगा।

    // Cell.m 
    - (BOOL)canPerformAction:(SEL)action withSender:(id)sender { 
        NSLog(@"canPerformAction"); 
        // The selector(s) should match your UIMenuItem selector 
    
        NSLog(@"Sender: %@", sender); 
        if (action == @selector(customAction:)) { 
         return YES; 
        } 
        return NO; 
    } 
    

    Custom Action from UICell canPerformAction

+3

कस्टम एक्शन में, प्रेषक UIMenuController है। आप उस से सेल के संदर्भ कैसे प्राप्त करते हैं? – drhr

+0

@drhr क्या आपको इसके लिए कोई समाधान मिला? – Dejell

+0

@Odelya मुझे लगता है कि आप कार्रवाई का अनुरोध करने वाले अंतिम सेल को स्टोर करने के लिए विधि का उपयोग कर सकते हैं। - (बूल) संग्रह दृश्य: (यूआईसीओलेक्शन व्यू *) संग्रह दृश्य चाहिएशोमेनूफोरइटम एट इंडेक्सपैथ: (एनएसआईएनएक्सएक्सपीएथ *) इंडेक्सपाथ आप वहां इंडेक्स पा सकते हैं। –

5

हो सकता है कि थोड़ी देर हो चुकी है लेकिन मैं शायद उन लोगों के लिए एक बेहतर समाधान है जो अभी भी इस के लिए खोज रहे हैं पाया:

अपने मद अपनी UICollectionViewController का जोड़ viewDidLoad में:

UIMenuItem *menuItem = [[UIMenuItem alloc] initWithTitle:@"Title" action:@selector(action:)]; 
[[UIMenuController sharedMenuController] setMenuItems:[NSArray arrayWithObject:menuItem]]; 

निम्नलिखित प्रतिनिधि विधियां जोड़ें:

//This method is called instead of canPerformAction for each action (copy, cut and paste too) 
- (BOOL)collectionView:(UICollectionView *)collectionView canPerformAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender { 
     if (action == @selector(action:)) { 
      return YES; 
     } 
     return NO; 
    } 
    //Yes for showing menu in general 
    - (BOOL)collectionView:(UICollectionView *)collectionView shouldShowMenuForItemAtIndexPath:(NSIndexPath *)indexPath { 
     return YES; 
    } 

उपclass UICollectionViewCell यदि आप पहले से नहीं थे। आपके आइटम के लिए निर्दिष्ट विधि जोड़ें:

- (void)action:(UIMenuController*)menuController { 

} 

इस तरह आपको किसी भी बनने की आवश्यकता नहीं है फर्स्ट रेस्पॉन्डर या अन्य विधियों। आपके पास एक ही स्थान पर सभी क्रियाएं हैं और यदि आप पैरामीटर के रूप में सेल के साथ एक सामान्य विधि को कॉल करते हैं तो आप आसानी से विभिन्न कक्षों को संभाल सकते हैं।

संपादित करें: किसी भी तरह uicollectionview इस विधि के अस्तित्व की जरूरत है

- (void)collectionView:(UICollectionView *)collectionView performAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender { 

} 
+0

संपादन के लिए धन्यवाद! – Nilz11

+0

@TinkBonobo आपकी टिप्पणी के लिए धन्यवाद लेकिन असल में यह मेरा संपादन था, उसने अभी अंग्रेजी में सुधार किया ;-)। – Nilz11

+0

मुझे यह जवाब विशेष रूप से सहायक पाया गया।हालांकि, मुझे अभी भी एक प्रतिनिधि बनाने का अंत करना पड़ा जो संग्रह नियंत्रक को वापस संदर्भित करता था ताकि मैं संग्रह नियंत्रक को रीफ्रेश कर सकूं। इसके अलावा, संपादन पर ध्यान दें। वह खाली प्रदर्शन क्रिया वर्ग की आवश्यकता है। – ThinkBonobo