Основні перетягування в iOS


93

Я хочу мати уявлення про те, в якому автомобілі їздять навколо, що користувач також може перетягувати. Як ви вважаєте, яка найкраща широкомасштабна стратегія для цього? Чи найкраще отримувати контактні події з подань, що представляють транспортні засоби, або з широкого перегляду? Чи є проста парадигма, яку ви використовували для перетягування і яка вас влаштовує? Які недоліки різних стратегій?


Відповіді:


126

Припустимо, у вас є UIViewсцена з фоновим зображенням і безліччю vehicles, ви можете визначити кожен новий транспортний засіб як UIButton(UIImageView, мабуть, теж буде працювати):

UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button addTarget:self action:@selector(imageTouch:withEvent:) forControlEvents:UIControlEventTouchDown];
[button addTarget:self action:@selector(imageMoved:withEvent:) forControlEvents:UIControlEventTouchDragInside];
[button setImage:[UIImage imageNamed:@"vehicle.png"] forState:UIControlStateNormal];
[self.view addSubview:button];

Потім ви можете переміщати транспортний засіб куди завгодно, відповідаючи на UIControlEventTouchDragInsideподію, наприклад:

- (IBAction) imageMoved:(id) sender withEvent:(UIEvent *) event
{
    CGPoint point = [[[event allTouches] anyObject] locationInView:self.view];
    UIControl *control = sender;
    control.center = point;
}

Індивідуальному транспортному засобу набагато простіше обробляти власні перетяжки, порівнюючи керування сценою в цілому.


Виглядає чудово і дуже просто! Я спробую це.
Лука

10
Чи може ця стратегія спричинити розривання перетягування, якби користувач перетягнув кнопку швидше, ніж оновлена ​​анімація? Якщо їх палець потрапив поза коробку, він перестане отримувати зображенняMoved: withEvent: call, правильно?
Тім

Як ви могли знати, якщо зображення перестане тягнутись? Як би ти знав, що пальчик перемістився?
ymutlu

ого - чи можна компенсувати перетягуючий «рукоятку» для зображення чи кнопки, щоб його можна було перетягнути за правий верхній чи верхній лівий кут?
LJ Wilson

коли я намагаюся отримати виняток - [drag_move_textViewController imageTouch: withEvent:]: нерозпізнаний селектор відправлений до екземпляра 0x4b4b1c0
iosDev

34

На додаток до відповіді Охо, я спробував подібну реалізацію, але без проблеми "швидкого" перетягування та центрування для перетягування.

Ініціалізація кнопок ...

UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button addTarget:self action:@selector(imageMoved:withEvent:) forControlEvents:UIControlEventTouchDragInside];
[button addTarget:self action:@selector(imageMoved:withEvent:) forControlEvents:UIControlEventTouchDragOutside];
[button setImage:[UIImage imageNamed:@"vehicle.png"] forState:UIControlStateNormal];
[self.view addSubview:button];

та реалізація методу:

- (IBAction) imageMoved:(id) sender withEvent:(UIEvent *) event
{
    UIControl *control = sender;

    UITouch *t = [[event allTouches] anyObject];
    CGPoint pPrev = [t previousLocationInView:control];
    CGPoint p = [t locationInView:control];

    CGPoint center = control.center;
    center.x += p.x - pPrev.x;
    center.y += p.y - pPrev.y;
    control.center = center;
}

Я не кажу, що це ідеальне рішення для відповіді. Проте я знайшов це найпростішим рішенням для перетягування.


2
У вашому прикладі коду ви визначаєте UIControl * control = sender після його використання - чи не слід це визначати раніше?
Пітер Джонсон

@PeterJohnson: Насправді це не має значення в цьому випадку. Раніше ця змінна не використовувалась з моменту, коли ви згадали :)
JakubKnejzlik

1
Як щодо CGPoint pPrev = [t попередняLocationInView: контроль]; CGPoint p = [t locationInView: контроль]; Ці два попередні рядки, як видається, посилаються на "контроль"?
Пітер Джонсон

О Боже! Як я можу це пропустити? : -О ... я відредагував відповідь.
JakubKnejzlik

я додаю конструктор інтерфейсу форми кнопок, і я використовую авторозкладку для деякого входу, я приховую кнопку і показую її знову, коли я це роблю, щоб повернутися до початкового місця, як запобігти цьому поведінці
Amr Angry

2

У мене був випадок, коли я хотів би перетягувати uiviews між кількома іншими uiviews. У такому випадку я знайшов найкраще рішення простежити події каструлі у надзвичайному вигляді, що містить усі зони падіння та всі об'єкти перетягування. Основною причиною НЕ додавання слухачів подій до фактично перетягнутих поглядів було те, що я втратив поточні події панораму, як тільки змінив перегляд перетягнутого перегляду.

Натомість я реалізував досить загальне рішення для перетягування, яке може бути використане в одній або декількох зонах падіння.

Я створив простий приклад, який можна побачити тут: перетягуйте uiviews краплі між декількома іншими uiview

Якщо ви вирішили піти іншим шляхом, спробуйте використовувати uicontrol замість uibutton. Вони оголошують методи addTarget і їх набагато простіше розширити - отже, надають власний стан і поведінку.


1

Я б насправді відслідковував перетягування самого погляду транспортного засобу , а не великого виду - якщо тільки немає конкретної причини цього не робити.

В одному випадку, коли я дозволяю користувачеві розміщувати елементи, перетягуючи їх на екран. У цьому випадку я експериментував як з видом зверху, так і з дочірніми, які можна перетягнути. Я виявив, що це чистіший код, якщо додати в UIView кілька «перетягуваних» поглядів і вирішити, як їх можна перетягнути. Я використовував простий зворотний дзвінок до батьківського UIView, щоб перевірити, чи підходить нове місцезнаходження чи ні - тому я міг зазначити за допомогою анімації.

Маючи вид зверху доріжки тягне я думаю так само добре, але що робить його трохи більш брудний , якщо ви хотіли б додати , НЕ перетягувати думки , які по- , як і раніше взаємодіяти з користувачем, наприклад кнопки.


1
-(void)funcAddGesture
{ 

 // DRAG BUTTON
        UIPanGestureRecognizer *panGestureRecognizer;
        panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(dragButton:)];
        panGestureRecognizer.cancelsTouchesInView = YES;

        UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
        button.frame = CGRectMake(50, 100, 60, 60);
        [button addTarget:self action:@selector(buttontapEvent) forControlEvents:UIControlEventPrimaryActionTriggered];
        [button setImage:[UIImage imageNamed:@"button_normal.png"] forState:UIControlStateNormal];
        [button addGestureRecognizer:panGestureRecognizer];
        [self.view addSubview:button];
}


- (void)dragButton:(UIPanGestureRecognizer *)recognizer {

    UIButton *button = (UIButton *)recognizer.view;
    CGPoint translation = [recognizer translationInView:button];

    float xPosition = button.center.x;
    float yPosition = button.center.y;
    float buttonCenter = button.frame.size.height/2;

    if (xPosition < buttonCenter)
        xPosition = buttonCenter;
    else if (xPosition > self.view.frame.size.width - buttonCenter)
        xPosition = self.view.frame.size.width - buttonCenter;

    if (yPosition < buttonCenter)
        yPosition = buttonCenter;
    else if (yPosition > self.view.frame.size.height - buttonCenter)
        yPosition = self.view.frame.size.height - buttonCenter;

    button.center = CGPointMake(xPosition + translation.x, yPosition + translation.y);
    [recognizer setTranslation:CGPointZero inView:button];
}


- (void)buttontapEvent {

    NSLog(@"buttontapEvent");
}

1

відповідь оххо мені добре спрацювала. Якщо вам потрібна швидка версія 2.x:

override func viewDidLoad() {

    let myButton = UIButton(type: .Custom)
    myButton.setImage(UIImage(named: "vehicle"), forState: .Normal)

    // drag support
    myButton.addTarget(self, action:#selector(imageMoved(_:event:)), forControlEvents:.TouchDragInside)
    myButton.addTarget(self, action:#selector(imageMoved(_:event:)), forControlEvents:.TouchDragOutside)
}

private func imageMoved(sender: AnyObject, event: UIEvent) {
    guard let control = sender as? UIControl else { return }
    guard let touches = event.allTouches() else { return }
    guard let touch = touches.first else { return }

    let prev = touch.previousLocationInView(control)
    let p = touch.locationInView(control)
    var center = control.center
    center.x += p.x - prev.x
    center.y += p.y - prev.y
    control.center = center
}


0

Для Swift 4 Найпростіший і найпростіший спосіб. 😛

Крок 1: Підключіть свою кнопку з розкадровки до контролера перегляду. І встановити всі основні обмеження автовикладання

 @IBOutlet weak var cameraButton: UIButton!

Крок 2: Додайте жест панорами до кнопки In viewDidLoad ()

self.cameraButton.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(self.panGestureHandler(panGesture:))))

Крок 3:

Додайте panGestureHandler

@objc func panGestureHandler(panGesture recognizer: UIPanGestureRecognizer) {

         let location = recognizer.location(in: view)
        cameraButton.center = location

    }

А тепер ваша дія кнопки

@IBAction func ButtonAction(_ sender: Any) {

        print("This is button Action")
    }

введіть тут опис зображення

Додати Подивитись результат ☝️

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.