Я хочу иметь представление, в котором едут автомобили, которые пользователь также может перетаскивать. Как вы думаете, какая крупномасштабная стратегия для этого лучше всего? Что лучше всего получать события касания из представлений, представляющих автомобили, или из более крупного вида? Есть ли простая парадигма перетаскивания, которая вам нравится? Какие недостатки у разных стратегий?
93
Ответы:
Предположим, у вас есть
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; }
Отдельному транспортному средству намного проще справляться с собственным перетаскиванием, чем управлять сценой в целом.
источник
В дополнение к ответу 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; }
Я не говорю, что это идеальное решение для ответа. Тем не менее я нашел это самым простым решением для перетаскивания.
источник
У меня был случай, когда я хотел перетаскивать uiviews между несколькими другими uiviews. В этом случае я нашел лучшее решение для отслеживания событий панорамирования в суперпредставлении, содержащем все зоны перетаскивания и все объекты перетаскивания. Основная причина, по которой НЕ добавлялись слушатели событий к фактическим перетаскиваемым представлениям, заключалась в том, что я потерял текущие события панорамирования, как только я изменил супервизор для перетаскиваемого представления.
Вместо этого я реализовал довольно общее решение перетаскивания, которое можно было использовать в одной или нескольких зонах перетаскивания.
Я создал простой пример, который можно увидеть здесь: Перетащите перетаскивание uiviews между несколькими другими uiviews
Если вы решите пойти другим путем, попробуйте использовать uicontrol вместо uibutton. Они объявляют методы addTarget и их намного проще расширять - следовательно, они дают настраиваемое состояние и поведение.
источник
На самом деле я бы отслеживал перетаскивание самого вида транспортного средства , а не большого вида - если нет особой причины «нет».
В одном случае, когда я разрешаю пользователю размещать элементы, перетаскивая их на экран. В этом случае я экспериментировал с перетаскиванием видов сверху и дочерних элементов. Я обнаружил, что это более чистый код, если вы добавите несколько «перетаскиваемых» представлений в UIView и определите, как их можно перетаскивать. Я использовал простой обратный вызов родительскому UIView, чтобы проверить, подходит ли новое местоположение, поэтому я мог указать с помощью анимации.
Перетаскивание дорожки вида сверху, я думаю, тоже хорошо, но это делает его немного более беспорядочным, если вы хотите добавить не перетаскиваемые представления, которые все еще взаимодействуют с пользователем, например кнопку.
источник
-(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"); }
источник
Ответ оххо сработал для меня. Если вам нужна версия 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 }
источник
Вот лучший способ перетаскивания в iOS 11:
https://developer.apple.com/documentation/uikit/drag_and_drop/adopting_drag_and_drop_in_a_custom_view
источник
Для Swift 4 Простой и легкий способ. 😛
Шаг 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") }
Добавить Посмотреть результат ☝️
источник