[iphone] iOS의 기본 드래그 앤 드롭

사용자가 드래그 앤 드롭 할 수있는 차량이 주변을 돌아 다니는 뷰를 갖고 싶습니다. 이를위한 최고의 대규모 전략은 무엇이라고 생각하십니까? 차량을 나타내는보기 또는 더 큰보기에서 터치 이벤트를 얻는 것이 가장 좋습니까? 드래그 앤 드롭에 사용한 간단한 패러다임이 만족 스럽습니까? 다른 전략의 단점은 무엇입니까?



답변

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;
}

나는 이것이 답을위한 완벽한 해결책이라고 말하지 않습니다. 그럼에도 불구하고 나는 이것이 드래그를위한 가장 쉬운 해결 책임을 발견했습니다.


답변

여러 다른 uiview간에 uiview를 드래그 / 드롭하려는 경우가있었습니다. 이 경우 모든 드롭 존과 모든 드래그 게이블 오브젝트가 포함 된 수퍼 뷰에서 팬 이벤트를 추적하는 최상의 솔루션을 찾았습니다. 실제 드래그 된 뷰에 이벤트 리스너를 추가하지 않은 주된 이유는 드래그 된 뷰에 대한 수퍼 뷰를 변경하자마자 진행중인 팬 이벤트를 잃었 기 때문입니다.

대신 단일 또는 다중 드롭 영역에서 사용할 수있는 다소 일반적인 드래그 드롭 솔루션을 구현했습니다.

여기에서 볼 수있는 간단한 예제를 만들었습니다. 다른 여러 uiview간에 드롭 uiviews를 드래그합니다.

다른 방향으로 가기로 결정했다면 uibutton 대신 uicontrol을 사용해보십시오. 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");
}


답변

오호의 답변이 잘 맞았습니다. 신속한 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