Основное перетаскивание в iOS - PullRequest
93 голосов
/ 16 января 2011

Я хочу иметь вид, в котором движутся транспортные средства, которые пользователь также может перетаскивать. Как вы думаете, что является лучшей крупномасштабной стратегией для этого? Лучше всего получать сенсорные события от представлений, представляющих транспортные средства, или от более широкого представления? Есть ли простая парадигма, которую вы использовали для перетаскивания, которая вас устраивает? Каковы недостатки различных стратегий?

Ответы [ 8 ]

126 голосов
/ 17 января 2011

Предположим, у вас есть 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;
}

Для отдельного транспортного средства намного проще справляться со своими собственными перетаскиваниями, чем для управления сценой в целом.

34 голосов
/ 28 июля 2012

В дополнение к ответу ohho, я попробовал аналогичную реализацию, но без проблемы "быстрого" перетаскивания и центрирования для перетаскивания.

Инициализация кнопки ...

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 голосов
/ 08 апреля 2012

У меня был случай, когда я хотел бы перетаскивать uiviews между несколькими другими uiviews.В этом случае я нашел лучшее решение для отслеживания событий панорамирования в супер-представлении, содержащем все зоны перетаскивания и все объекты перетаскивания.Основной причиной НЕ добавления слушателей событий к фактическим перетаскиваемым представлениям было то, что я потерял текущие события панорамирования, как только я изменил суперпредставление для перетаскиваемого представления.

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

Я создал простой пример, который можно увидеть здесь: Перетащите каплюuiviews между несколькими другими uiviews

Если вы решили пойти другим путем, попробуйте использовать uicontrol вместо uibutton.Они объявляют методы addTarget и их гораздо проще расширять - следовательно, они дают пользовательское состояние и поведение.

1 голос
/ 30 марта 2016

Охо, ответ работал хорошо для меня. Если вам нужна версия swift 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
}
1 голос
/ 16 декабря 2015
-(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 голос
/ 17 января 2011

Я бы фактически отслеживал перетаскивание на самом виде транспортного средства , а не на большом виде - если только нет особой причины нет.

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

Наличие перетаскивания дорожки сверху Полагаю, это тоже хорошо, но это делает его немного более грязным, если вы хотите добавить не перетаскиваемые виды, которые по-прежнему взаимодействуют с пользователем, например кнопку.

0 голосов
/ 21 июня 2018

Для Swift 4 Легкий и простой способ.100

Шаг 1: Подключите кнопку из раскадровки для просмотра контроллера.И установить все основные ограничения AutoLayout

 @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")
    }

enter image description here

Добавить Смотреть результат ☝️

0 голосов
/ 07 июня 2017

Вот лучший способ сделать перетаскивание с iOS 11:

https://developer.apple.com/documentation/uikit/drag_and_drop/adopting_drag_and_drop_in_a_custom_view

...