ইউআইপিএনগাস্টারআর সনাক্তকারী - কেবল উল্লম্ব বা অনুভূমিক


146

আমার এমন একটি ভিউ রয়েছে যা UIPanGestureRecognizerদেখতে উল্লম্বভাবে টানতে পারে। সুতরাং সনাক্তকারী কলব্যাকে, আমি এটিকে সরাতে কেবল y- স্থানাংক আপডেট করি। এই দর্শনটির তত্ত্বাবধানে এমন একটি রয়েছে UIPanGestureRecognizerযা দর্শনটিকে অনুভূমিকভাবে টেনে আনবে, কেবলমাত্র x- স্থানাঙ্ক আপডেট করে।

সমস্যাটি হ'ল প্রথমটি UIPanGestureRecognizerদৃশ্যটি উল্লম্বভাবে স্থানান্তরিত করার জন্য ইভেন্টটি নিচ্ছে, তাই আমি সুপারভিউ অঙ্গভঙ্গিটি ব্যবহার করতে পারি না।

আমি চেষ্টা করেছি

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
 shouldRecognizeSimultaneouslyWithGestureRecognizer:
                            (UIGestureRecognizer *)otherGestureRecognizer;

এবং উভয়ই কাজ করবে, তবে আমি তা চাই না। আমি চাই আন্দোলনটি স্পষ্টভাবে অনুভূমিক হলেই অনুভূমিকভাবে সনাক্ত করা উচিত। সুতরাং এটি দুর্দান্ত হবে যদি UIPanGestureRecognizerকোনও দিকনির্দেশনা সম্পত্তি থাকে।

আমি কীভাবে এই আচরণটি অর্জন করতে পারি? আমি দস্তাবেজগুলিকে খুব বিভ্রান্তিকর বলে মনে করি, তাই এখানে কেউ আরও ভাল ব্যাখ্যা করতে পারে।


আপনার নিজের প্রশ্নের উত্তর দেওয়া এবং উত্তরটি গ্রহণ করা ঠিক আছে, যদি আপনি সমাধানটি বের করেন।
jtbandes

@ জো ব্লো সত্যিই? সুতরাং, আপনি কি অনুবাদ এবং অঙ্গভঙ্গির বেগ পেতে সোয়াইপ অঙ্গভঙ্গির বিভাগ তৈরি করেছেন?
রোমান ট্রুবা

2
আপনি কি বলছেন তা আমি বুঝতে পারছি না। যদি আপনি একটি অনুভূমিক সোয়াইপ সনাক্ত করতে চান তবে এটি অপারেটিং সিস্টেমটিতে সম্পূর্ণ এবং সম্পূর্ণ অন্তর্নির্মিত । সমস্ত কাজ সম্পূর্ণ এবং সম্পূর্ণ আপনার জন্য সম্পন্ন হয়েছে। তোমার কিছু করা দরকার ... কিছুই না! :) শুধু কোডের দুই লাইন পেস্ট এই উদাহরণে .. stackoverflow.com/a/20988648/294884 নোট আপনি শুধুমাত্র বাম নির্বাচন করতে পারবেন যে "" ডান শুধুমাত্র "বা" উভয় "।
Fattie

উত্তর:


212

উল্লম্ব প্যান অঙ্গভঙ্গি সনাক্তকারীর জন্য এটি করুন, এটি আমার পক্ষে কাজ করে:

- (BOOL)gestureRecognizerShouldBegin:(UIPanGestureRecognizer *)panGestureRecognizer {
    CGPoint velocity = [panGestureRecognizer velocityInView:someView];
    return fabs(velocity.y) > fabs(velocity.x);
}

এবং সুইফ্টের জন্য:

func gestureRecognizerShouldBegin(_ gestureRecognizer: UIPanGestureRecognizer) -> Bool {
    let velocity = gestureRecognizer.velocity(in: someView)
    return abs(velocity.x) > abs(velocity.y)
}

3
এটি চেষ্টা
করেও অনুবাদটি

12
(0,0) সমস্যাটি স্পষ্ট হয় না যখন বেগটিআইভিউ: অনুবাদ-এর পরিবর্তে ব্যবহৃত হয় ইনভিউ :.
সিবিএইচ 2000

1
@ cbh2000 আমি উত্তর ব্যবহার করতে আপডেট velocityInViewপরিবর্তে translationInView
হেজাজি

19
@ জোব্লো একটি ইউআইএসইপইগস্টেকার রিকনগাইজার হ'ল সোয়াইপ অঙ্গভঙ্গির প্রতিক্রিয়া হিসাবে একটি রূপান্তর বন্ধ করার সহজ উপায় তবে এটি একটি স্বতন্ত্র ইঙ্গিত। যদি কেউ কোনও ধারাবাহিক পদ্ধতির সন্ধান করে a যেমন কোনও অঙ্গভঙ্গি দিয়ে কোনও রূপান্তর সঞ্চার করতে পারে — তবে কোনও ইউআইপিএনগাস্টারআর সনাক্তকারীকে যাওয়ার উপায়।
লেভি ম্যাককালাম

এটি চতুর সমাধান
জাকুব ট্রুহলি

79

সাবোক্লাসিং সহ আমি একটি সমাধান তৈরি করেছি যেমন @ লোকোমাইক সরবরাহ করা উত্তরের মতো, তবে @ হেজাজির দেওয়া প্রাথমিক গতির মাধ্যমে আরও কার্যকর সনাক্তকরণ ব্যবস্থা ব্যবহার করেছি। আমি সুইফটও ব্যবহার করছি, তবে ইচ্ছা করলে ওবজ-সিতে অনুবাদ করা সহজ হওয়া উচিত।

অন্যান্য সমাধানগুলির জন্য সুবিধা:

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

কোডটি এখানে:

import UIKit.UIGestureRecognizerSubclass

enum PanDirection {
    case vertical
    case horizontal
}

class PanDirectionGestureRecognizer: UIPanGestureRecognizer {

    let direction: PanDirection

    init(direction: PanDirection, target: AnyObject, action: Selector) {
        self.direction = direction
        super.init(target: target, action: action)
    }

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent) {
        super.touchesMoved(touches, with: event)

        if state == .began {
            let vel = velocity(in: view)
            switch direction {
            case .horizontal where fabs(vel.y) > fabs(vel.x):
                state = .cancelled
            case .vertical where fabs(vel.x) > fabs(vel.y):
                state = .cancelled
            default:
                break
            }
        }
    }
}

ব্যবহারের উদাহরণ:

let panGestureRecognizer = PanDirectionGestureRecognizer(direction: .horizontal, target: self, action: #selector(handlePanGesture(_:)))
panGestureRecognizer.cancelsTouchesInView = false
self.view.addGestureRecognizer(panGestureRecognizer)

func handlePanGesture(_ pan: UIPanGestureRecognizer) {
    let percent = max(pan.translation(in: view).x, 0) / view.frame.width

    switch pan.state {
    case .began:
    ...
}

4
এটি একেবারে সেরা উত্তর। এটি খুব খারাপ যে অ্যাপল এর মত কার্যকারিতা যুক্ত করে নি UIPanGestureRecognizer
NRitH

আপনি একটি ব্যবহার উদাহরণ প্রদান করতে পারেন?
ব্যবহারকারী 82395214

এটি খুবই সুন্দর! ধন্যবাদ! উভয় অনুভূমিক এবং উল্লম্ব স্ট্যাকিং করার সময় পুরোপুরি কাজ করে: let horizontalPanRecognizer = PanDirectionGestureRecognizer(direction: .horizontal, target: self, action: #selector(handleHorizontalPanGesture(recognizer:))) self.view?.addGestureRecognizer(horizontalPanRecognizer); let verticalPanRecognizer = PanDirectionGestureRecognizer(direction: .vertical, target: self, action: #selector(handleVerticalPanGesture(recognizer:))) self.view?.addGestureRecognizer(verticalPanRecognizer);
হান

ওহ এই দুর্দান্ত! ধন্যবাদ!
বরণ এমরে

51

আমি এটি ইউআইপিএনজেচারআরকনগাইজারের একটি সাবক্লাস তৈরি করে খুঁজে পেয়েছি

DirectionPanGestureRecognizer:

#import <Foundation/Foundation.h>
#import <UIKit/UIGestureRecognizerSubclass.h>

typedef enum {
    DirectionPangestureRecognizerVertical,
    DirectionPanGestureRecognizerHorizontal
} DirectionPangestureRecognizerDirection;

@interface DirectionPanGestureRecognizer : UIPanGestureRecognizer {
    BOOL _drag;
    int _moveX;
    int _moveY;
    DirectionPangestureRecognizerDirection _direction;
}

@property (nonatomic, assign) DirectionPangestureRecognizerDirection direction;

@end

DirectionPanGestureRecognizer.m:

#import "DirectionPanGestureRecognizer.h"

int const static kDirectionPanThreshold = 5;

@implementation DirectionPanGestureRecognizer

@synthesize direction = _direction;

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    [super touchesMoved:touches withEvent:event];
    if (self.state == UIGestureRecognizerStateFailed) return;
    CGPoint nowPoint = [[touches anyObject] locationInView:self.view];
    CGPoint prevPoint = [[touches anyObject] previousLocationInView:self.view];
    _moveX += prevPoint.x - nowPoint.x;
    _moveY += prevPoint.y - nowPoint.y;
    if (!_drag) {
        if (abs(_moveX) > kDirectionPanThreshold) {
            if (_direction == DirectionPangestureRecognizerVertical) {
                self.state = UIGestureRecognizerStateFailed;
            }else {
                _drag = YES;
            }
        }else if (abs(_moveY) > kDirectionPanThreshold) {
            if (_direction == DirectionPanGestureRecognizerHorizontal) {
                self.state = UIGestureRecognizerStateFailed;
            }else {
                _drag = YES;
            }
        }
    }
}

- (void)reset {
    [super reset];
    _drag = NO;
    _moveX = 0;
    _moveY = 0;
}

@end

এটি কেবলমাত্র অঙ্গভঙ্গিটি ট্রিগার করবে যদি ব্যবহারকারী নির্বাচিত আচরণে টানা শুরু করে। সঠিক মানের দিকে দিকের সম্পত্তিটি সেট করুন এবং আপনি সমস্ত প্রস্তুত।


আমি মনে করি প্রাথমিকভাবে 'রিসেট' কল হচ্ছে না। একটি initWithTarget:action:পদ্ধতি যুক্ত করেছে এবং রিসেট নামে ডাকা হয়েছে এবং সবকিছু ঠিকঠাক ছিল।
কলিন্টা

5
বর্তমান বাস্তবায়নে DirectionPanGestureRecognizerদ্রুত ড্রাগগুলি উপেক্ষা করা হবে, যদি আপনি সেট না করেন kDirectionPanThreshold = 20বা না করেন, তবে এটি ক্ষেত্রে মিথ্যা অ্যালার্ম দিতে পারে। আমি abs(_moveX) > abs(_moveY)পরিবর্তে abs(_moveX) > kDirectionPanThresholdঅনুভূমিক কেস পরিবর্তে স্থাপন এবং পরিবর্তন করার পরামর্শ দিই ।
ডেনিস ক্রুট

2
আমার এটি যুক্ত করা উচিত এটি আমার জন্যও সহায়ক ছিল, তবে প্যানের অঙ্গভঙ্গি সনাক্তকারীকে ট্রিগার করতে আমার যা যুক্ত করতে হয়েছিল তা যদি অন্য লাইনে ছিল, _drag = YESআমি যে লাইনের সাথে যুক্ত করেছিself.state = UIGestureRecognizerStateChanged;
বলনাড

13

আমি ইউআইপিএনগাস্টারআর সনাক্তকারী সাথে বৈধ অঞ্চলটি অনুভূমিকভাবে সীমাবদ্ধ করার চেষ্টা করেছি।

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
    if ([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]]) {

        UIPanGestureRecognizer *panGesture = (UIPanGestureRecognizer *)gestureRecognizer;
        CGPoint velocity = [panGesture velocityInView:panGesture.view];

        double radian = atan(velocity.y/velocity.x);
        double degree = radian * 180 / M_PI;

        double thresholdAngle = 20.0;
        if (fabs(degree) > thresholdAngle) {
            return NO;
        }
    }
    return YES;
}

তারপরে, কেবলমাত্র প্রান্তিকআঙ্গলের ডিগ্রির মধ্যে অনুভূমিকভাবে সোয়াইপ করা এই প্যানের অঙ্গভঙ্গিটি ট্রিগার করতে পারে।


2
দুর্দান্ত উত্তর। আমি যখন ইউআইএসক্রোলভিউ অঙ্গভঙ্গি এবং নিয়মিত অঙ্গভঙ্গির মিশ্রিত করি তখন এটি সত্যই আমাকে সাহায্য করেছিল। আমি মনে করি উদাহরণটির অর্থ "সক্রিয় থ্রেশহোল্ড" এর পরিবর্তে "থ্রেশহোল্ডএঙ্গেল" বলা হয়েছিল। এবং আপনার কদাচিৎ কখনও এটান () ব্যবহার করা উচিত কারণ এটি একটি এনএন উত্পাদন করতে পারে। পরিবর্তে atan2 () ব্যবহার করুন।
ব্রেইনওয়্যার

9

সুইফট ৩.০ উত্তর: উল্লম্ব অঙ্গভঙ্গিটি কেবল হ্যান্ডলগুলি করে

    override func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
    if let pan = gestureRecognizer as? UIPanGestureRecognizer {
        let velocity = pan.velocity(in: self)
        return fabs(velocity.y) > fabs(velocity.x)
    }
    return true

}

6

নিম্নলিখিত সমাধানটি আমার সমস্যার সমাধান করেছে:

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

এটি আসলে কেবল প্যানটি প্রধান দর্শন বা টেবিলভিউতে চলছে কিনা তা পরীক্ষা করে দেখুন।


3
কেন কল করুন- একুয়াল: দুটি মতামত একই হলে তুলনা করতে? একটি সাধারণ পরিচয় যাচাইয়ের জন্য যথেষ্ট। অঙ্গভঙ্গি সনাক্তকারী.ভিউ == স্ব.ভিউ
ওপেনফ্রোগ

6

অলসতার জন্য লির উত্তরটির সুইফ্ট 3 সংস্করণ

import UIKit
import UIKit.UIGestureRecognizerSubclass

enum PanDirection {
    case vertical
    case horizontal
}

class UIPanDirectionGestureRecognizer: UIPanGestureRecognizer {

    let direction : PanDirection

    init(direction: PanDirection, target: AnyObject, action: Selector) {
        self.direction = direction
        super.init(target: target, action: action)
    }

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent) {
        super.touchesMoved(touches, with: event)

        if state == .began {

            let vel = velocity(in: self.view!)
            switch direction {
            case .horizontal where fabs(vel.y) > fabs(vel.x):
                state = .cancelled
            case .vertical where fabs(vel.x) > fabs(vel.y):
                state = .cancelled
            default:
                break
            }
        }
    }
}

4

আমি নেন লি Goodrich এর উত্তর এবং এটি বাড়ানো হিসাবে আমি বিশেষভাবে একটি একক দিক প্যান প্রয়োজন ছিল। এটি এর মতো ব্যবহার করুন:let pan = PanDirectionGestureRecognizer(direction: .vertical(.up), target: self, action: #selector(handleCellPan(_:)))

আমি আসলে কী সিদ্ধান্ত নেওয়া হচ্ছে তা একটু পরিষ্কার করার জন্য কিছু মন্তব্য যুক্ত করেছি।

import UIKit.UIGestureRecognizerSubclass

enum PanVerticalDirection {
    case either
    case up
    case down
}

enum PanHorizontalDirection {
    case either
    case left
    case right
}

enum PanDirection {
    case vertical(PanVerticalDirection)
    case horizontal(PanHorizontalDirection)
}

class PanDirectionGestureRecognizer: UIPanGestureRecognizer {

    let direction: PanDirection

    init(direction: PanDirection, target: AnyObject, action: Selector) {
        self.direction = direction
        super.init(target: target, action: action)
    }

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent) {
        super.touchesMoved(touches, with: event)

        if state == .began {
            let vel = velocity(in: view)
            switch direction {

            // expecting horizontal but moving vertical, cancel
            case .horizontal(_) where fabs(vel.y) > fabs(vel.x):
                state = .cancelled

            // expecting vertical but moving horizontal, cancel
            case .vertical(_) where fabs(vel.x) > fabs(vel.y):
                state = .cancelled

            // expecting horizontal and moving horizontal
            case .horizontal(let hDirection):
                switch hDirection {

                    // expecting left but moving right, cancel
                    case .left where vel.x > 0: state = .cancelled

                    // expecting right but moving left, cancel
                    case .right where vel.x < 0: state = .cancelled
                    default: break
                }

            // expecting vertical and moving vertical
            case .vertical(let vDirection):
                switch vDirection {
                    // expecting up but moving down, cancel
                    case .up where vel.y > 0: state = .cancelled

                    // expecting down but moving up, cancel
                    case .down where vel.y < 0: state = .cancelled
                    default: break
                }
            }
        }
    }
}

ত্রুটি override func touchesMoved- Method does not override any method from its superclass
আনবিস

@ আঞ্জানউইন আপনাকে "আমদানি ইউআইকিট.উইজিস্টচাররনকনাইজারসুব্লাস" ব্যবহার করতে হবে
শ্যাজনিকোল

ঠিক আছে. আমি এটা সম্পর্কে অবগত ছিল না। আমি ভেবেছিলাম ইউআইকিট স্বয়ংক্রিয়ভাবে এটি আমদানি করবে। আমি এটা চেষ্টা করে দেখব.
অ্যানবিসউ

2

আপনি অভিমুখ উপর টেনে জানতে পারেন UIViewমাধ্যমে UIPanGestureRecognizer। দয়া করে কোডটি অনুসরণ করুন।

 - (void)viewDidLoad {
    [super viewDidLoad];
    flipFoward = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(doFlipForward:)];
    [flipFoward setMaximumNumberOfTouches:1];
    [flipFoward setMinimumNumberOfTouches:1];
    [flipFoward setDelegate:self];
    [self.view addGestureRecognizer:flipFoward];
    flipBack = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(doFlipBack:)];
    [flipBack setMaximumNumberOfTouches:1];
    [flipBack setMinimumNumberOfTouches:1];
    [flipBack setDelegate:self];
    [self.view addGestureRecognizer:flipBack];
}

#pragma mark -
#pragma mark RESPONDER

-(void)doFlipForward:(UIGestureRecognizer *)aGestureRecognizer{
    NSLog(@"doFlipForward");
    if([(UIPanGestureRecognizer*)aGestureRecognizer state] == UIGestureRecognizerStateBegan) {
        NSLog(@"UIGestureRecognizerStateBegan");
    }
    if([(UIPanGestureRecognizer*)aGestureRecognizer state] == UIGestureRecognizerStateChanged) {
        NSLog(@"UIGestureRecognizerStateChanged");
    }
    if([(UIPanGestureRecognizer*)aGestureRecognizer state] == UIGestureRecognizerStateEnded) {
        NSLog(@"UIGestureRecognizerStateEnded");
    }
}

-(void)doFlipBack:(UIGestureRecognizer *)aGestureRecognizer{
    NSLog(@"doFlipBack");
    if([(UIPanGestureRecognizer*)aGestureRecognizer state] == UIGestureRecognizerStateBegan) {
        NSLog(@"UIGestureRecognizerStateBegan1");
    }
    if([(UIPanGestureRecognizer*)aGestureRecognizer state] == UIGestureRecognizerStateChanged) {
        NSLog(@"UIGestureRecognizerStateChanged1");
    }
    if([(UIPanGestureRecognizer*)aGestureRecognizer state] == UIGestureRecognizerStateEnded) {
        NSLog(@"UIGestureRecognizerStateEnded1");
    }
}

#pragma mark -
#pragma mark DELEGATE

-(BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{
    CGSize size = [self.view bounds].size;
    CGFloat touchX = [gestureRecognizer locationInView:self.view].x;
    if((gestureRecognizer == flipFoward) 
       && touchX >= (size.width - 88.0f))
    {
        return YES;
    }
    if((gestureRecognizer == flipBack)
       && touchX <= 88.0f)
    {
        return YES;
    }
    return NO;
}

বাস্তবে এটি ভাল সমাধান নয় কারণ কেবল বাম দিক থেকে 88 পয়েন্ট প্যান করতে সক্ষম।
বোরুত তোমাজিন

2

সুইফট 4.2

সমাধানটি কেবল অনুভূমিক হিসাবে সমানভাবে প্যান অঙ্গভঙ্গি সমর্থন করার জন্য।

let pan = UIPanGestureRecognizer(target: self, action: #selector(test1))
pan.cancelsTouchesInView = false
panView.addGestureRecognizer(pan)

সমাধান 1 :

@objc func panAction(pan: UIPanGestureRecognizer) {

        let velocity = pan.velocity(in: panView)
        guard abs(velocity.y) > abs(velocity.x) else {
            return
        }
}

সমাধান 2:

  [UISwipeGestureRecognizer.Direction.left, .right].forEach { direction in
        let swipe = UISwipeGestureRecognizer(target: self, action: #selector(swipeAction))
        swipe.direction = direction
        panView.addGestureRecognizer(swipe)
        pan.require(toFail: swipe)
    }

তারপরে সোয়াইপ ইশারা প্যানের অঙ্গভঙ্গি গ্রাস করবে। অবশ্যই, আপনাকে কিছু করার দরকার নেই swipeAction


1

এখানে আমি কীভাবে সমাধান করেছি:

প্রথমে আমি একযোগে PanGesture স্বীকৃতি সক্ষম করেছি।

-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {

return YES;

তারপরে আমি অনুভূমিক এবং উল্লম্ব প্যান অঙ্গভঙ্গিগুলি পৃথক করে (সংগ্রহকারীটি এনএসমিটেবলআরাই সম্পত্তি):

- (void)verticalPan :(UIPanGestureRecognizer *) sender {

CGPoint touch  = [sender translationInView:self];
NSValue *value = [NSValue valueWithCGPoint:touch];
[accumulator addObject:value];

int firstXObjectValue = (int)[[accumulator objectAtIndex:0] CGPointValue].x ;
int lastXObjectValue =  (int)[[accumulator lastObject] CGPointValue].x;

int firstYObjectValue = (int)[[accumulator objectAtIndex:0] CGPointValue].y;
int lastYObjectValue =  (int)[[accumulator lastObject] CGPointValue].y;

if (abs(lastYObjectValue - firstYObjectValue) < 4 && abs(lastXObjectValue - firstXObjectValue) > 4) {
    NSLog(@"Horizontal Pan");

    //do something here
}
else if (abs(lastYObjectValue - firstYObjectValue) > 4 && abs(lastXObjectValue - firstXObjectValue) < 4){
    NSLog(@"Vertical Pan");

    //do something here
}

if (accumulator.count > 3)
    [accumulator removeAllObjects];

আমি এখানে একটি উদাহরণ ঠেলা:

স্ক্রোলভিউতে কাস্টম প্যান যুক্ত করুন


1
let pangesture = UIPanGestureRecognizer(target: self, action: "dragview:")
yourview.addGestureRecognizer(pangesture)


func dragview(panGestureRecognizer:UIPanGestureRecognizer)
{
    let touchlocation = panGestureRecognizer.locationInView(parentview)
    yourview.center.y = touchlocation.y //x for horizontal 
}

1

আপনি সহজ ব্যবহার করতে পারেন panGestureRecognizer। ব্যবহার pandirectionregognizerবা স্টাফ করার দরকার নেই । translationInview কেবলমাত্র উপরে এবং নীচে নীচের কোড মুভ ড্র্যাগ ভিউয়ের y মান ব্যবহার করুন

- (void)gesturePan_Handle:(UIPanGestureRecognizer *)gesture {
    if (gesture.state == UIGestureRecognizerStateChanged) {
        CGPoint translation = [gesture translationInView:gesture.view];
        recognizer.view.center = CGPointMake(recognizer.view.center.x, recognizer.view.center.y + translation.y);
        [gesture setTranslation:CGPointMake(0, 0) inView:gesture.view];
    }
}

এই কোডটি সহজেই ভিউটি প্যান করে। কোনও দিকনির্দেশক লক প্রয়োগ করা হয়নি।
জাকিশাহীন

1
- (void)dragAction:(UIPanGestureRecognizer *)gesture{
      UILabel *label = (UILabel *)gesture.view;
      CGPoint translation = [gesture translationInView:label];
     label.center = CGPointMake(label.center.x + translation.x,
                             label.center.y + 0);
    [gesture setTranslation:CGPointZero inView:label];}

আমি অবজেক্টের জন্য PanGestureRecognizer @ নির্বাচনকারী ক্রিয়া পদ্ধতি তৈরি করেছি যার জন্য কেবল অনুভূমিক স্ক্রোলিংয়ের প্রয়োজন।

 UIPanGestureRecognizer *gesture = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(smileyDragged:)];
    [buttonObject addGestureRecognizer:gesture];

1

দ্রুত পথ

override func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
    if let panGestureRecognizer = gestureRecognizer as? UIPanGestureRecognizer {
        return isVerticalGesture(panGestureRecognizer)
    }
    return false
}

private func isVerticalGesture(_ recognizer: UIPanGestureRecognizer) -> Bool {
    let translation = recognizer.translation(in: superview!)
    if fabs(translation.y) > fabs(translation.x) {
        return true
    }
    return false
}

0

আপনি যে সকল সুইফ্ট ব্যবহারকারীদের বাইরে রয়েছেন, তাদের পক্ষে এটি কাজ করবে :)

import Foundation
import UIKit.UIGestureRecognizerSubclass


class DirectionPanGestureRecognizer: UIPanGestureRecognizer {

let kDirectionPanThreshold = CGFloat(5)
var drag = true
var moveX = CGFloat(0)
var moveY = CGFloat(0)

override init(target: AnyObject, action: Selector) {
    super.init(target: target, action: action)
}

override func touchesMoved(touches: NSSet, withEvent event: UIEvent) {
    super.touchesMoved(touches, withEvent: event)
    if state == .Failed {
        return
    }

    let nowPoint = touches.anyObject()?.locationInView(view)
    let prevPoint = touches.anyObject()?.previousLocationInView(view)
    moveX += prevPoint!.x - nowPoint!.x
    moveY += prevPoint!.y - nowPoint!.y
    if !drag {
        if abs(moveX) > kDirectionPanThreshold {
            state = .Failed
        } else {
            drag = true
        }

    }

}

 override func reset() {
    super.reset()
    moveX = 0
    moveY = 0
    drag = false
}




}

0

আমি লি গুডরিচের একটি দুর্দান্ত উত্তর নিয়েছি এবং সুইফট 3-এ পোর্ট করেছি

import UIKit
import UIKit.UIGestureRecognizerSubclass

enum PanDirection {
    case vertical
    case horizontal
}

class PanDirectionGestureRecognizer: UIPanGestureRecognizer {

    let direction : PanDirection

    init(direction: PanDirection, target: AnyObject, action: Selector) {
        self.direction = direction
        super.init(target: target, action: action)
    }

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent) {

        super.touchesMoved(touches, with: event)

        if state == .began {

            let vel = velocity(in: self.view!)

            switch direction {

            case .horizontal where fabs(vel.y) > fabs(vel.x):
                state = .cancelled

            case .vertical where fabs(vel.x) > fabs(vel.y):
                state = .cancelled

            default:
                break

            }

        }
    }
}

0

আমি আমার দৃষ্টিভঙ্গিটি ভাগ করে নিতে চাই কারণ অন্য সমস্ত পদ্ধতির হয় UIGestureRecognizerDelegateবা সাবক্লাসিংয়ের উপর ভিত্তি করে UIPanGestureRecognizer

আমার পদ্ধতির রানটাইম এবং সুইজলিংয়ের উপর ভিত্তি করে। আমি এই পদ্ধতির বিষয়ে 100% নিশ্চিত নই, তবে আপনি নিজেই এটি পরীক্ষা করে উন্নত করতে পারেন।

UIPanGestureRecognizerকোডের এক লাইনের সাথে কোনওটির দিকনির্দেশ সেট করুন :

UITableView().panGestureRecognizer.direction = UIPanGestureRecognizer.Direction.vertical

ব্যবহার pod 'UIPanGestureRecognizerDirection'বা কোড:

public extension UIPanGestureRecognizer {

    override open class func initialize() {
        super.initialize()
        guard self === UIPanGestureRecognizer.self else { return }
        func replace(_ method: Selector, with anotherMethod: Selector, for clаss: AnyClass) {
            let original = class_getInstanceMethod(clаss, method)
            let swizzled = class_getInstanceMethod(clаss, anotherMethod)
            switch class_addMethod(clаss, method, method_getImplementation(swizzled), method_getTypeEncoding(swizzled)) {
            case true:
                class_replaceMethod(clаss, anotherMethod, method_getImplementation(original), method_getTypeEncoding(original))
            case false:
                method_exchangeImplementations(original, swizzled)
            }
        }
        let selector1 = #selector(UIPanGestureRecognizer.touchesBegan(_:with:))
        let selector2 = #selector(UIPanGestureRecognizer.swizzling_touchesBegan(_:with:))
        replace(selector1, with: selector2, for: self)
        let selector3 = #selector(UIPanGestureRecognizer.touchesMoved(_:with:))
        let selector4 = #selector(UIPanGestureRecognizer.swizzling_touchesMoved(_:with:))
        replace(selector3, with: selector4, for: self)
    }

    @objc private func swizzling_touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
        self.swizzling_touchesBegan(touches, with: event)
        guard direction != nil else { return }
        touchesBegan = true
    }

    @objc private func swizzling_touchesMoved(_ touches: Set<UITouch>, with event: UIEvent) {
        self.swizzling_touchesMoved(touches, with: event)
        guard let direction = direction, touchesBegan == true else { return }
        defer {
            touchesBegan = false
        }
        let forbiddenDirectionsCount = touches
            .flatMap({ ($0.location(in: $0.view) - $0.previousLocation(in: $0.view)).direction })
            .filter({ $0 != direction })
            .count
        if forbiddenDirectionsCount > 0 {
            state = .failed
        }
    }
}

public extension UIPanGestureRecognizer {

    public enum Direction: Int {

        case horizontal = 0
        case vertical
    }

    private struct UIPanGestureRecognizerRuntimeKeys {
        static var directions = "\(#file)+\(#line)"
        static var touchesBegan = "\(#file)+\(#line)"
    }

    public var direction: UIPanGestureRecognizer.Direction? {
        get {
            let object = objc_getAssociatedObject(self, &UIPanGestureRecognizerRuntimeKeys.directions)
            return object as? UIPanGestureRecognizer.Direction
        }
        set {
            let policy = objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC
            objc_setAssociatedObject(self, &UIPanGestureRecognizerRuntimeKeys.directions, newValue, policy)
        }
    }

    fileprivate var touchesBegan: Bool {
        get {
            let object = objc_getAssociatedObject(self, &UIPanGestureRecognizerRuntimeKeys.touchesBegan)
            return (object as? Bool) ?? false
        }
        set {
            let policy = objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC
            objc_setAssociatedObject(self, &UIPanGestureRecognizerRuntimeKeys.touchesBegan, newValue, policy)
        }
    }
}

fileprivate extension CGPoint {

    var direction: UIPanGestureRecognizer.Direction? {
        guard self != .zero else { return nil }
        switch fabs(x) > fabs(y) {
        case true:  return .horizontal
        case false: return .vertical
        }
    }

    static func -(lhs: CGPoint, rhs: CGPoint) -> CGPoint {
        return CGPoint(x: lhs.x - rhs.x, y: lhs.y - rhs.y)
    }
}

0

আমি এটি চেষ্টা করেছি: যা প্রশ্নের বিবরণ অনুসারে আমার পক্ষে কাজ করেছে

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
    if gestureRecognizer is UIPanGestureRecognizer {
        return true
    } else {
        return false
    }
}

0

সুইফট 4.2

আমি আরও এগিয়ে গিয়ে একটি দিক প্যান অঙ্গভঙ্গি করলাম:

enum PanDirection {
    case up
    case left
    case right
    case down
}

class PanDirectionGestureRecognizer: UIPanGestureRecognizer {
    
    fileprivate let direction: PanDirection
    
    init(direction: PanDirection, target: AnyObject, action: Selector) {
        self.direction = direction
        super.init(target: target, action: action)
    }
    
    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent) {
        super.touchesMoved(touches, with: event)
        
        guard state != .failed else { return }

        let vel = velocity(in: view)

        let velocities: [PanDirection: CGFloat]
            = [.up: -vel.y,
               .left: -vel.x,
               .right: vel.x,
               .down: vel.y]

        let sortedKeys = velocities.sorted { $0.1 < $1.1 }

        if let key = sortedKeys.last?.key,
            key != direction {
            state = .cancelled
        }
    }
}

(ব্যবহৃত: https://github.com/fastred/SloppySwiper এবং https://stackoverflow.com/a/30607392/5790492 )


0

সুইফট 5 এ এখানে একটি কাস্টম প্যান অঙ্গভঙ্গি দেওয়া আছে

ইউ এর দিক এবং সর্বাধিক কোণটি সীমাবদ্ধ করতে পারে, আপনি দিকটিতে এটির সর্বনিম্ন গতিও সীমাবদ্ধ করতে পারেন।

enum PanDirection {
    case vertical
    case horizontal
}

struct Constaint {
    let maxAngle: Double
    let minSpeed: CGFloat

    static let `default` = Constaint(maxAngle: 50, minSpeed: 50)
}


class PanDirectionGestureRecognizer: UIPanGestureRecognizer {

    let direction: PanDirection

    let constraint: Constaint


    init(direction orientation: PanDirection, target: AnyObject, action: Selector, constraint limits: Constaint = Constaint.default) {
        direction = orientation
        constraint = limits
        super.init(target: target, action: action)
    }

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent) {
        super.touchesMoved(touches, with: event)
        let tangent = tan(constraint.maxAngle * Double.pi / 180)
        if state == .began {
            let vel = velocity(in: view)
            switch direction {
            case .horizontal where abs(vel.y)/abs(vel.x) > CGFloat(tangent) || abs(vel.x) < constraint.minSpeed:
                state = .cancelled
            case .vertical where abs(vel.x)/abs(vel.y) > CGFloat(tangent) || abs(vel.y) < constraint.minSpeed:
                state = .cancelled
            default:
                break
            }
        }
    }
}

এভাবে কল করুন:

    let pan = PanDirectionGestureRecognizer(direction: .vertical, target: self, action: #selector(self.push(_:)))
    view.addGestureRecognizer(pan)

    @objc func push(_ gesture: UIPanGestureRecognizer){
        if gesture.state == .began{
            // command for once
        }
    }

অথবা

    let pan = PanDirectionGestureRecognizer(direction: .horizontal, target: self, action: #selector(self.push(_:)), constraint: Constaint(maxAngle: 5, minSpeed: 80))
    view.addGestureRecognizer(pan)

-1

PanGestureRecognizer ইন্টারফেসের নিম্নলিখিত সংজ্ঞা রয়েছে:

unsigned int    _canPanHorizontally:1;
unsigned int    _canPanVertically:1;

আমি এটি চেক করিনি, তবে সম্ভবত এটি সাবক্লাসের মাধ্যমে অ্যাক্সেসযোগ্য।


3
প্রতিশ্রুতিবদ্ধ দেখায়, কিন্তু সেই API প্রকাশিত হয় নি। প্রাইভেট API গুলি ব্যবহারের ফলে সাধারণত অ্যাপল প্রত্যাখ্যান করে।
উইলিয়াম ডেনিস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.