İOS'ta Temel Sürükle ve Bırak


93

Kullanıcının sürükleyip bırakabileceği, etrafta dolaşan araçların olduğu bir görünüme sahip olmak istiyorum. Bunu yapmak için en iyi büyük ölçekli strateji sizce nedir? Dokunma olaylarını araçları temsil eden görünümlerden mi yoksa daha geniş görünümden mi almak en iyisidir? Sürükle ve bırak için kullandığınız, memnun olduğunuz basit bir paradigma var mı? Farklı stratejilerin sakıncaları nelerdir?


Yanıtlar:


126

UIViewArka plan görüntüsü olan bir sahneniz olduğunu varsayalım ve birçok vehiclesyeni aracı bir UIButton(UIImageView muhtemelen de çalışacaktır) olarak tanımlayabilirsiniz :

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

Ardından UIControlEventTouchDragInsideolaya yanıt vererek aracı istediğiniz yere hareket ettirebilirsiniz , örneğin:

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

Sahneyi bir bütün olarak yönetmeye kıyasla, tek bir aracın kendi sürüklenmeleriyle başa çıkması çok daha kolaydır.


Harika ve çok basit görünüyor! Bunu deneyeceğim.
Luke

10
Bu strateji, kullanıcı düğmeyi güncellenen animasyondan daha hızlı sürüklerse sürüklemenin bozulmasına neden olur mu? Parmakları kutunun dışına çıkarsa, imageMoved: withEvent: çağrılarını almayı durdurur, doğru mu?
Tim

Resmin sürüklenip durmayacağını nasıl bilebilirsin? Parmağın dışarı çıktığını nasıl anlarsın?
ymutlu

ohho - bir resmin veya düğmenin sürükleme "tutamacını", sağ üst veya sol üst köşeden sürüklenecek şekilde kaydırmak mümkün mü?
LJ Wilson

istisna almaya çalıştığımda - [drag_move_textViewController imageTouch: withEvent:]: 0x4b4b1c0 örneğine gönderilen tanınmayan seçici
iosDev

34

Ohho'nun cevabına ek olarak, benzer bir uygulamayı denedim, ancak sürüklemek için "hızlı" sürükleme ve ortalama problemi olmadan.

Düğme başlatma ...

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

ve yöntem uygulaması:

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

Bunun cevap için mükemmel bir çözüm olduğunu söylemiyorum. Yine de bunu sürüklemek için en kolay çözüm buldum.


2
Örnek kodunuzda, kullanıldıktan sonra UIControl * control = göndereni tanımlarsınız - bu daha önce tanımlanmamalı mı?
Peter Johnson,

@PeterJohnson: Aslında bu durumda önemli değil. Bahsettiğiniz satırdan beri bu değişkenin daha önceki bir kullanımı yok :)
JakubKnejzlik

1
Peki ya CGPoint pPrev = [t previousLocationInView: control]; CGPoint p = [t locationInView: denetim]; Bu iki önceki satırın her ikisi de "kontrol" anlamına mı geliyor?
Peter Johnson

Tanrım! Bunu nasıl gözden kaçırabilirim? : -O ... Cevabı düzenledim.
JakubKnejzlik

düğme formu arayüz oluşturucuyu ekliyorum ve bazı girişler için otomatik düzen kullanıyorum, düğmeyi gizleyip tekrar gösteriyorum, bunu yaptığımda orijinal yerine geri dönüyor, bu bitişi nasıl önleyeceğimi
Amr Angry

2

Diğer görünümleri birden çok görünüm arasında sürükleyip bırakmak istediğim bir durum vardı. Bu durumda, tüm bırakma bölgelerini ve tüm sürükleme üçgen nesnelerini içeren bir süper görünümde pan olaylarını izlemek için en iyi çözümü buldum. Olay dinleyicilerini gerçek sürüklenen görünümlere EKLEMEMENİN birincil nedeni, sürüklenen görünüm için denetim görünümünü değiştirir değiştirmez devam eden pan olaylarını kaybetmemdi.

Bunun yerine, tekli veya çoklu bırakma bölgelerinde kullanılabilecek oldukça genel bir sürükle bırak çözümü uyguladım.

Burada görülebilecek basit bir örnek oluşturdum: Diğer birden çok uiview arasına açılan bir uiview sürükleyin

Diğer tarafa gitmeye karar verirseniz, uibutton yerine uicontrol kullanmayı deneyin. AddTarget yöntemlerini bildirirler ve genişletmeleri çok daha kolaydır - bu nedenle özel durum ve davranış verirler.


1

Aslında , büyük görünümden ziyade araç görünümünün kendisinde sürüklemeyi izlerdim - bunun için özel bir neden yoksa.

Kullanıcının öğeleri ekrana sürükleyerek yerleştirmesine izin verdiğim bir durumda. Bu durumda, hem üstten görünüme hem de sürüklenebilir alt görüntülere sahip olmayı denedim. UIView'a birkaç "sürüklenebilir" görünüm eklerseniz ve nasıl sürüklenebileceklerini ele alırsanız, daha temiz bir kod buldum. Yeni konumun uygun olup olmadığını kontrol etmek için ana UIView'a basit bir geri arama kullandım - böylece animasyonlarla belirtebildim.

Having üstten görünüm sanırım sürükleyerek parçayı iyi olarak, ancak olmayan sürüklenebilir görüşlerini eklemek istiyorum eğer biraz daha pis bir hale getirdiğini hala etkileşim düğme gibi kullanıcı ile.


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

ohho'nun cevabı benim için iyi çalıştı. Hızlı 2.x sürümüne ihtiyacınız olması durumunda:

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 için Kolay ve en kolay yol. 😛

Adım 1: Denetleyiciyi Görüntülemek İçin Düğmenizi Storyboard'dan Bağlayın. Ve Tüm Temel Otomatik Yerleşim Kısıtlamalarını Ayarlayın

 @IBOutlet weak var cameraButton: UIButton!

Adım 2: in viewDidLoad () düğmeniz için Pan Hareketi ekleyin

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

Aşama 3:

PanGestureHandler ekleyin

@objc func panGestureHandler(panGesture recognizer: UIPanGestureRecognizer) {

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

    }

Ve Şimdi Düğme İşleminiz

@IBAction func ButtonAction(_ sender: Any) {

        print("This is button Action")
    }

görüntü açıklamasını buraya girin

Ekle Sonucu Gör ☝️

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.