ইউআইসিএল্লেশনভিউসেল-তে দীর্ঘ প্রেসের অঙ্গভঙ্গি


108

আমি ভাবছিলাম কীভাবে একটি ইউআইসিওলিকেশনভিউতে (উপক্লাসের) একটি দীর্ঘ প্রেস অঙ্গভঙ্গি সনাক্তকারী যুক্ত করব to আমি ডকুমেন্টেশনে পড়েছি যে এটি ডিফল্টরূপে যুক্ত হয়েছে, তবে কীভাবে তা আমি বুঝতে পারি না।

আমি যা করতে চাই তা হ'ল: একটি ঘরে দীর্ঘক্ষণ চাপ দিন ( আমার কাছে গিথুব থেকে একটি ক্যালেন্ডার জিনিস রয়েছে ), কোন ঘরটি ট্যাপ করা আছে তা পান এবং তারপরে এটি স্টাফ করুন। আমার জানা দরকার কোষটি দীর্ঘস্থায়ী। এই বিস্তৃত প্রশ্নের জন্য দুঃখিত, তবে আমি গুগল বা এসও এর চেয়ে ভাল কিছু খুঁজে পাচ্ছি না

উত্তর:


220

উদ্দেশ্য গ

আপনার myCollectionViewController.hফাইলে UIGestureRecognizerDelegateপ্রোটোকল যুক্ত করুন

@interface myCollectionViewController : UICollectionViewController<UIGestureRecognizerDelegate>

আপনার myCollectionViewController.mফাইলে:

- (void)viewDidLoad
{
    // attach long press gesture to collectionView
    UILongPressGestureRecognizer *lpgr 
       = [[UILongPressGestureRecognizer alloc]
                     initWithTarget:self action:@selector(handleLongPress:)];
    lpgr.delegate = self;
    lpgr.delaysTouchesBegan = YES;
    [self.collectionView addGestureRecognizer:lpgr];
}

-(void)handleLongPress:(UILongPressGestureRecognizer *)gestureRecognizer
{
    if (gestureRecognizer.state != UIGestureRecognizerStateEnded) {
        return;
    }
    CGPoint p = [gestureRecognizer locationInView:self.collectionView];

    NSIndexPath *indexPath = [self.collectionView indexPathForItemAtPoint:p];
    if (indexPath == nil){
        NSLog(@"couldn't find index path");            
    } else {
        // get the cell at indexPath (the one you long pressed)
        UICollectionViewCell* cell =
        [self.collectionView cellForItemAtIndexPath:indexPath];
        // do stuff with the cell
    }
}

দ্রুতগতি

class Some {

    @objc func handleLongPress(gesture : UILongPressGestureRecognizer!) {
        if gesture.state != .Ended {
            return
        }
        let p = gesture.locationInView(self.collectionView)

        if let indexPath = self.collectionView.indexPathForItemAtPoint(p) {
            // get the cell at indexPath (the one you long pressed)
            let cell = self.collectionView.cellForItemAtIndexPath(indexPath)
            // do stuff with the cell
        } else {
            print("couldn't find index path")
        }
    }
}

let some = Some()
let lpgr = UILongPressGestureRecognizer(target: some, action: #selector(Some.handleLongPress))

সুইফট 4

class Some {

    @objc func handleLongPress(gesture : UILongPressGestureRecognizer!) {
        if gesture.state != .ended { 
            return 
        } 

        let p = gesture.location(in: self.collectionView) 

        if let indexPath = self.collectionView.indexPathForItem(at: p) { 
            // get the cell at indexPath (the one you long pressed) 
            let cell = self.collectionView.cellForItem(at: indexPath) 
            // do stuff with the cell 
        } else { 
            print("couldn't find index path") 
        }
    }
}

let some = Some()
let lpgr = UILongPressGestureRecognizer(target: some, action: #selector(Some.handleLongPress))

1
এটি ইতিমধ্যে উত্তরে রয়েছে: এখানেUICollectionViewCell* cell = [self.collectionView cellForItemAtIndexPath:indexPath]; রেফারেন্স আশা করি এই সমস্তই সঠিক উত্তর পুরষ্কারের যোগ্যতা: ডি
অ্যাবুড

10
(কমপক্ষে) আইওএস 7 এর জন্য আপনাকে প্রথমে ট্রিগার হওয়া lpgr.delaysTouchesBegan = YES;এড়াতে যুক্ত করতে হবে didHighlightItemAtIndexPath
ডায়নামিকডান

7
আপনি যুক্ত করলেন কেন lpgr.delegate = self;? এটি প্রতিনিধি ছাড়াই দুর্দান্ত কাজ করে, যা আপনি সরবরাহ করেন নি।
ইয়েভেন ডাবিনিন

3
উত্তরটি উত্তরটি কার্যকর করে তবে লম্বা প্রেস শনাক্তকারী সক্রিয় থাকাকালীন আমি কালেকশন ভিউতে (অন্য একটি আঙুল ব্যবহার করে) উপরে এবং নীচে স্ক্রোল করতে পারি না। কি দেয়?
পাতুর ইনগি এগিলসন

4
ব্যক্তিগতভাবে, আমি করতাম UIGestureRecognizerStateBegan, সুতরাং ভঙ্গিমাটি যখন স্বীকৃত হয় তখন ব্যবহার করা হয়, যখন ব্যবহারকারী তাদের আঙুলটি প্রকাশ করে না।
জেফরি সান

28

সুইফটের জন্য একই কোড @ অ্যাবডের কোড:

ভিউডিডলয়েডে:

let lpgr : UILongPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: "handleLongPress:")
lpgr.minimumPressDuration = 0.5
lpgr.delegate = self
lpgr.delaysTouchesBegan = true
self.collectionView?.addGestureRecognizer(lpgr)

এবং ফাংশন:

func handleLongPress(gestureRecognizer : UILongPressGestureRecognizer){

    if (gestureRecognizer.state != UIGestureRecognizerState.Ended){
        return
    }

    let p = gestureRecognizer.locationInView(self.collectionView)

    if let indexPath : NSIndexPath = (self.collectionView?.indexPathForItemAtPoint(p))!{
        //do whatever you need to do
    }

}

প্রতিনিধি ভুলে যাবেন না UIGestureRecognizerDelegate


3
দুর্দান্ত কাজ করেছেন, কেবলমাত্র একটি নোট যে "হ্যান্ডেললংপ্রেস:" # সিলেক্টারে পরিবর্তিত হওয়া উচিত (আপনার ভিউকন্ট্রোলআরহ্যান্ডললংপ্রেস (_ :))
জোসেফ জেরঘাটি

16
ভাল কাজ করে, তবে UIGestureRecognizerState.Endedআপনি UIGestureRecognizerState.Beganযদি নূন্যতম সময়সীমাটি শেষ হয়ে যাওয়ার পরে কেবল কোডটি চালিত করতে চান তবে তা পরিবর্তন করুন , যখন ব্যবহারকারী তার আঙুলটি তুলে রাখে না কেবল।
ক্র্যাশলোট

11

ইউআইসিকলিকেশনভিউয়ের প্রতিনিধি ব্যবহার করুন দীর্ঘ প্রেস ইভেন্ট পান

আপনাকে অবশ্যই নীচে 3 পদ্ধতি প্রয়োগ করতে হবে।

//UICollectionView menu delegate
- (BOOL)collectionView:(UICollectionView *)collectionView shouldShowMenuForItemAtIndexPath:(NSIndexPath *)indexPath{

   //Do something

   return YES;
}
- (BOOL)collectionView:(UICollectionView *)collectionView canPerformAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(nullable id)sender{
    //do nothing
    return NO;
}

- (void)collectionView:(UICollectionView *)collectionView performAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(nullable id)sender{
    //do nothing
}

দ্রষ্টব্য: আপনি যদি শোমেনুফোর্সআইটেমএন্টেক্সপথের জন্য মিথ্যা ফিরিয়ে দেন তবে ডডসিলিটটেমটিঅ্যাট ইন্ডেক্সপথটিও লাথি মেরে ফেলা হবে। লং প্রেস বনাম সিঙ্গল প্রেসের জন্য যখন দুটি ভিন্ন ক্রিয়া চেয়েছিলাম তখন এটি আমার জন্য সমস্যাযুক্ত হয়ে ওঠে।
শ্যাননস

এটি এখনের জন্য অবচিত পদ্ধতি, আপনি ব্যবহার করতে পারেন - (ইউআইসিসটেক্সটমেনু কনফিগারেশন *) সংগ্রহটি দেখুন: (ইউআইকোলিকেশনভিউ *) সংগ্রহ দেখুন প্রসঙ্গমেনু কনফিগারেশনফর্ম আইটেমটিডেক্সপথ: (ননাল এনএসআইন্ডেক্সপথ *) সূচকপথ: (সিজিপিয়েন্ট) পয়েন্ট;
ভিক্টর গল্টভিয়ানিতসা

8

এখানে উত্তর একটি কাস্টম longpress অঙ্গভঙ্গি শনাক্তকারী সঠিক যোগ করার জন্য কিন্তু ডকুমেন্টেশন অনুযায়ী এখানে : এর পিতা বা মাতা বর্গ UICollectionViewবর্গ একটি ইনস্টল default long-press gesture recognizerস্ক্রলিং পারস্পরিক ক্রিয়ার হ্যান্ডেল করতে যাতে আপনি আপনার সংগ্রহ দৃশ্য সঙ্গে যুক্ত ডিফল্ট শনাক্তকারী আপনার কাস্টম আলতো চাপা অঙ্গভঙ্গির শনাক্তকারী লিঙ্ক করতে হবে।

নিম্নলিখিত কোডটি আপনার কাস্টম অঙ্গভঙ্গি সনাক্তকারীকে ডিফল্টর সাথে হস্তক্ষেপ করতে এড়াবে:

UILongPressGestureRecognizer* longPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPressGesture:)];

longPressGesture.minimumPressDuration = .5; //seconds
longPressGesture.delegate = self;

// Make the default gesture recognizer wait until the custom one fails.
for (UIGestureRecognizer* aRecognizer in [self.collectionView gestureRecognizers]) {
   if ([aRecognizer isKindOfClass:[UILongPressGestureRecognizer class]])
      [aRecognizer requireGestureRecognizerToFail:longPressGesture];
} 

আপনি যা বলছেন তা আমি দেখতে পাচ্ছি, তবে এটি কালো এবং সাদা নয়, ডকুমেন্টেশন বলছে: The parent class of UICollectionView class installs a default tap gesture recognizer and a default long-press gesture recognizer to handle scrolling interactions. You should never try to reconfigure these default gesture recognizers or replace them with your own versions.সুতরাং ডিফল্ট দীর্ঘ-প্রেস শনাক্তকারীটি স্ক্রোলিংয়ের জন্য তৈরি করা হয়েছে .. যা বোঝায় যে এটি একটি উল্লম্ব আন্দোলনের সাথে থাকতে হবে .. ওপি জিজ্ঞাসা করছে না সে ধরনের আচরণ সম্পর্কে বা তিনি এটি প্রতিস্থাপনের চেষ্টা করছেন না
abbood

ডিফেন্সিভ শোনার জন্য দুঃখিত, তবে আমি কয়েক মাস ধরে আমার আইওএস অ্যাপের সাহায্যে উপরের কোডটি ব্যবহার করছি .. একসময় কোনও ত্রুটি ঘটতে ভাবতে পারে না
অ্যাবড

@ আবদু ঠিক আছে তৃতীয় পক্ষের ক্যালেন্ডার উপাদানটি পিও ব্যবহার করছে তা আমি জানি না তবে আমি মনে করি যে এই
সমস্যাটি

যদি আপনাকে অবশ্যই ডিফল্ট শনাক্তকারীর ব্যর্থ হওয়ার জন্য অপেক্ষা করতে হবে তবে তার অর্থ এই নয় যে কোনও বিলম্ব হবে?
ক্র্যাশলোট

2
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];

[cell addGestureRecognizer:longPress];

এবং এই পদ্ধতিটি যুক্ত করুন।

- (void)longPress:(UILongPressGestureRecognizer*)gesture
{
    if ( gesture.state == UIGestureRecognizerStateEnded ) {

        UICollectionViewCell *cellLongPressed = (UICollectionViewCell *) gesture.view;
    }
}

2

বাহ্যিক অঙ্গভঙ্গি শনাক্তকারী থাকতে এবং ইউআইকোলিকেশনভিউতে অভ্যন্তরীণ অঙ্গভঙ্গি সনাক্তকারীদের সাথে দ্বন্দ্ব না করার জন্য আপনার প্রয়োজন:

আপনার অঙ্গভঙ্গি শনাক্তকারী যুক্ত করুন, এটি সেট আপ করুন এবং এর জন্য কোথাও একটি রেফারেন্স ক্যাপচার করুন (আপনি ইউআইকোলিকেশনভিউটি সাবক্ল্যাশড করে দিলে সর্বোত্তম বিকল্পটি আপনার সাবক্লাসে রয়েছে)

@interface UICollectionViewSubclass : UICollectionView <UIGestureRecognizerDelegate>    

@property (strong, nonatomic, readonly) UILongPressGestureRecognizer *longPressGestureRecognizer;   

@end

ওভাররাইড ডিফল্ট আরম্ভের পদ্ধতি initWithFrame:collectionViewLayout:এবং initWithCoder:এবং জন্য আপনাকে দীর্ঘ প্রেস অঙ্গভঙ্গি শনাক্তকারী পদ্ধতি সেট আপ যোগ

@implementation UICollectionViewSubclass

-(instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout
{
    if (self = [super initWithFrame:frame collectionViewLayout:layout]) {
        [self setupLongPressGestureRecognizer];
    }
    return self;
}

-(instancetype)initWithCoder:(NSCoder *)aDecoder
{
    if (self = [super initWithCoder:aDecoder]) {
        [self setupLongPressGestureRecognizer];
    }
    return self;
}

@end

আপনার সেটআপ পদ্ধতিটি লিখুন যাতে এটি দীর্ঘ প্রেস অঙ্গভঙ্গি সনাক্তকারীকে তাত্ক্ষণিকভাবে সেট করে, এটি প্রতিনিধি সেট করে, ইউআইকোলিকেশনভিউ অঙ্গভঙ্গি সনাক্তকারীর সাথে সেটআপ নির্ভরতা (সুতরাং এটি মূল অঙ্গভঙ্গি হবে এবং অন্যান্য অঙ্গভঙ্গিগুলি সেই অঙ্গভঙ্গিটি স্বীকৃত হওয়ার আগে ব্যর্থ হওয়া পর্যন্ত অপেক্ষা করবে) এবং দৃশ্যে অঙ্গভঙ্গি যুক্ত করুন

-(void)setupLongPressGestureRecognizer
{
    _longPressGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self
                                                                                action:@selector(handleLongPressGesture:)];
    _longPressGestureRecognizer.delegate = self;

    for (UIGestureRecognizer *gestureRecognizer in self.collectionView.gestureRecognizers) {
        if ([gestureRecognizer isKindOfClass:[UILongPressGestureRecognizer class]]) {
            [gestureRecognizer requireGestureRecognizerToFail:_longPressGestureRecognizer];
        }
    }

    [self.collectionView addGestureRecognizer:_longPressGestureRecognizer];
}

এছাড়াও UIGestureRecognizerDelegate পদ্ধতিগুলি প্রয়োগ করতে ভুলবেন না যা সেই অঙ্গভঙ্গিটি ব্যর্থ করে এবং একই সাথে স্বীকৃতি দেয় (এটি আপনাকে প্রয়োগ করতে হবে বা নাও হতে পারে, এটি আপনার অন্যান্য অঙ্গভঙ্গি সনাক্তকারীদের উপর নির্ভর করে বা অভ্যন্তরীণ অঙ্গভঙ্গি সনাক্তকারীদের সাথে নির্ভরতা)

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
    if ([self.longPressGestureRecognizer isEqual:gestureRecognizer]) {
        return NO;
    }

    return NO;
}

এর শংসাপত্রগুলি LXReorderable CollectionsViewFlowLayout এর অভ্যন্তরীণ বাস্তবায়নে যায়


এটি আমার স্ন্যাপচ্যাট ক্লোনটির জন্য একই নৃত্য। আহ আহ সত্য ভালবাসা।
বেনজামিনহলক

1

সুইফট 5:

private func setupLongGestureRecognizerOnCollection() {
    let longPressedGesture = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress(gestureRecognizer:)))
    longPressedGesture.minimumPressDuration = 0.5
    longPressedGesture.delegate = self
    longPressedGesture.delaysTouchesBegan = true
    collectionView?.addGestureRecognizer(longPressedGesture)
}

@objc func handleLongPress(gestureRecognizer: UILongPressGestureRecognizer) {
    if (gestureRecognizer.state != .began) {
        return
    }

    let p = gestureRecognizer.location(in: collectionView)

    if let indexPath = collectionView?.indexPathForItem(at: p) {
        print("Long press at item: \(indexPath.row)")
    }
}

এছাড়াও ইউআইজিস্টারআরকিগনাইজারডেলিগেট বাস্তবায়ন করতে এবং ভিজিডলড থেকে বা যেখানেই আপনার যেখানে কল করতে হবে সেখান থেকে সেটআপলংগ্রেচাররেকগনিজারঅনেকলেশন কল করতে ভুলবেন না।


0

সম্ভবত, ইউআইএলংপ্রেসজেস্টাররেকগনিজার ব্যবহার করা সর্বাধিক বিস্তৃত সমাধান। তবে আমি এর সাথে দুটি বিরক্তিকর সমস্যার মুখোমুখি হয়েছি:

  • কখনও কখনও যখন আমরা আমাদের স্পর্শটি সরিয়ে রাখি তখন এই সনাক্তকারীটি ভুল উপায়ে কাজ করে;
  • সনাক্তকারী অন্যান্য স্পর্শ ক্রিয়াকে বাধা দেয় যাতে আমরা আমাদের ইউআইকোলিকেশনভিউয়ের হাইলাইট কলব্যাকগুলি সঠিক উপায়ে ব্যবহার করতে পারি না।

আমাকে কিছুটা ব্রুটফোর্স পরামর্শ দিন, তবে এটির মতো পরামর্শের প্রয়োজন হিসাবে কাজ করছেন:

আমাদের সেলটিতে দীর্ঘ ক্লিকের জন্য কলব্যাকের বিবরণ ঘোষণা করা:

typealias OnLongClickListener = (view: OurCellView) -> Void

ভেরিয়েবলগুলির সাথে ইউআইকোলিকেশনভিউসেল প্রসারিত করা হচ্ছে (উদাহরণস্বরূপ আমরা এটি আওয়ারসেলভিউর নাম দিতে পারি):

/// To catch long click events.
private var longClickListener: OnLongClickListener?

/// To check if we are holding button pressed long enough.
var longClickTimer: NSTimer?

/// Time duration to trigger long click listener.
private let longClickTriggerDuration = 0.5

আমাদের সেল শ্রেণিতে দুটি পদ্ধতি যুক্ত করা:

/**
 Sets optional callback to notify about long click.

 - Parameter listener: A callback itself.
 */
func setOnLongClickListener(listener: OnLongClickListener) {
    self.longClickListener = listener
}

/**
 Getting here when long click timer finishs normally.
 */
@objc func longClickPerformed() {
    self.longClickListener?(view: self)
}

এবং এখানে ওভাররাইডিং স্পর্শ ইভেন্টগুলি:

/// Intercepts touch began action.
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
    longClickTimer = NSTimer.scheduledTimerWithTimeInterval(self.longClickTriggerDuration, target: self, selector: #selector(longClickPerformed), userInfo: nil, repeats: false)
    super.touchesBegan(touches, withEvent: event)
}

/// Intercepts touch ended action.
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
    longClickTimer?.invalidate()
    super.touchesEnded(touches, withEvent: event)
}

/// Intercepts touch moved action.
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
    longClickTimer?.invalidate()
    super.touchesMoved(touches, withEvent: event)
}

/// Intercepts touch cancelled action.
override func touchesCancelled(touches: Set<UITouch>?, withEvent event: UIEvent?) {
    longClickTimer?.invalidate()
    super.touchesCancelled(touches, withEvent: event)
}

তারপরে কোথাও আমাদের সংগ্রহের নিয়ন্ত্রণের মধ্যে কলব্যাক শ্রোতা ঘোষণা করে:

let longClickListener: OnLongClickListener = {view in
    print("Long click was performed!")
}

এবং অবশেষে সেলফোরআইটেমএন্টেক্সপথটিতে আমাদের সেলগুলির জন্য কলব্যাক সেটিং করা হয়েছে:

/// Data population.
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCellWithReuseIdentifier("Cell", forIndexPath: indexPath)
    let castedCell = cell as? OurCellView
    castedCell?.setOnLongClickListener(longClickListener)

    return cell
}

এখন আমরা আমাদের কোষগুলিতে দীর্ঘ ক্লিকের ক্রিয়াগুলি বাধা দিতে পারি।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.