Я хочу иметь представление, в котором едут автомобили, которые пользователь также может перетаскивать. Как вы думаете, какая крупномасштабная стратегия для этого лучше всего? Что лучше всего получать события касания из представлений, представляющих автомобили, или из более крупного вида? Есть ли простая парадигма перетаскивания, которая вам нравится? В чем недостатки разных стратегий?
Базовое перетаскивание в iOS
Ответы (7)
Предположим, у вас есть 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;
}
Отдельному транспортному средству намного проще справляться с собственным перетаскиванием, чем управлять сценой в целом.
UIPanGestureRecognizer
. Это не сломается ни при какой скорости сопротивления.
- person tipycalFlow; 03.09.2013
В дополнение к ответу 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, чтобы проверить, подходит ли новое местоположение, поэтому я мог указать с помощью анимации.
Перетаскивание дорожки вид сверху, я думаю, тоже хорошо, но это делает его немного более беспорядочным, если вы хотите добавить не перетаскиваемые представления, которые все еще взаимодействуют с пользователем, например кнопку.
Ответ оххо сработал для меня. Если вам нужна версия 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:
Для Swift 4 Простой и легкий способ. ????
Шаг 1. Подключите кнопку из раскадровки к контроллеру просмотра. И установите все основные ограничения AutoLayout
@IBOutlet weak var cameraButton: UIButton!
Шаг 2. Добавьте жест панорамирования для кнопки в 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")
}
Добавить Посмотреть результат ☝️