IOS में बेसिक ड्रैग एंड ड्रॉप


93

मैं एक ऐसा दृश्य रखना चाहता हूं जिसमें ऐसे वाहन हों जिनके आसपास उपयोगकर्ता भी खींच कर छोड़ सकें। आपको क्या लगता है कि ऐसा करने के लिए सबसे बड़ी बड़े पैमाने पर रणनीति है? क्या वाहनों का प्रतिनिधित्व करने वाले विचारों से, या बड़े दृष्टिकोण से स्पर्श घटनाओं को प्राप्त करना सबसे अच्छा है? क्या एक साधारण प्रतिमान है जिसे आपने ड्रैग और ड्रॉप के लिए उपयोग किया है जिससे आप संतुष्ट हैं? विभिन्न रणनीतियों की कमियां क्या हैं?


जवाबों:


126

मान लें कि आपके पास 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;
}

व्यक्तिगत वाहन के लिए अपने ड्रग्स को संभालना बहुत आसान है, इस दृश्य को संपूर्ण रूप से प्रबंधित करना।


बहुत अच्छा और बहुत सरल लगता है! मैं यह कोशिश करूँगा।
ल्यूक

10
यदि उपयोगकर्ता ने एनीमेशन अपडेट की तुलना में बटन को तेजी से खींच लिया तो क्या यह रणनीति टूटने का कारण होगी? यदि उनकी उंगली बॉक्स के बाहर मिली, तो यह छवि को प्राप्त करना बंद कर देगा: पीछे हटना: कॉल, सही?
टिम

अगर छवि को खींचना बंद करो तो आप कैसे जान सकते हैं? आपको कैसे पता चलेगा कि उंगली बाहर निकल गई है?
ymutlu

ओहो - क्या किसी छवि या बटन के लिए "हैंडल" को खींचना संभव है ताकि इसे ऊपरी दाएं या ऊपरी बाएं कोने से खींचा जा सके?
एलजे विल्सन

जब मैं अपवाद प्राप्त करने की कोशिश कर रहा हूँ - [drag_move_textViewController imageTouch: withEvent:]: अपरिचित चयनकर्ता को 0x4b4b1c0 पर भेजा गया
iosDev

34

ओहो के जवाब के अलावा, मैंने इसी तरह के कार्यान्वयन की कोशिश की है, लेकिन "तेज" खींचें और खींचने के लिए केंद्रित होने की समस्या के बिना।

बटन आरंभीकरण है ...

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
आपके उदाहरण कोड में, आप UIControl * control = भेजने वाले को परिभाषित करने के बाद इसका उपयोग करते हैं- क्या इसे पहले परिभाषित नहीं किया जाना चाहिए?
पीटर जॉनसन

@PeterJohnson: वास्तव में यह इस मामले में कोई फर्क नहीं पड़ता। आपके द्वारा उल्लिखित लाइन के बाद से इस चर का कोई पूर्व उपयोग नहीं है :)
JakubKnejzlik

1
CGPoint pPrev के बारे में क्या = [t पिछलेLocationInView: नियंत्रण]; CGPoint p = [t locationInView: नियंत्रण]; ये दो पहले वाली रेखाएं दोनों "नियंत्रण" को संदर्भित करती हैं?
पीटर जॉन्सन

हे भगवान! मैं कैसे चूक सकता हूं? : -ओ ... मैंने उत्तर संपादित कर लिया है।
JakubKnejzlik

मैं बटन फॉर्म इंटरफ़ेस बिल्डर जोड़ता हूं और मैं कुछ लॉगिन के लिए ऑटोलेयूट का उपयोग करता हूं मैं बटन छिपाता हूं और फिर से दिखाता हूं जब मैं ऐसा करता हूं तो यह मूल स्थान पर वापस आ जाता है कि इस बीवर को कैसे रोका जाए
अमृत ​​एंग्री

2

मेरे पास एक मामला था जहां मैं कई अन्य uiviews के बीच uiviews को खींचना / छोड़ना चाहूंगा। उस मामले में मुझे एक सुपर व्यू में सभी ड्रॉप जोन और सभी ड्रैग गैबल ऑब्जेक्ट्स में पैन घटनाओं का पता लगाने का सबसे अच्छा समाधान मिला। ईवेंट श्रोताओं को वास्तविक ड्रैग किए गए दृश्यों में शामिल नहीं करने का प्राथमिक कारण यह था कि जैसे ही मैं ड्रैग किए गए दृश्य के लिए सुपरविजन बदल रहा था, मैंने चल रहे पैन ईवेंट खो दिए।

इसके बजाय मैंने एक बल्कि सामान्य ड्रैग ड्रॉप समाधान लागू किया जो एकल या एकाधिक ड्रॉप ज़ोन पर इस्तेमाल किया जा सकता है।

मैंने एक सरल उदाहरण बनाया है जिसे यहाँ देखा जा सकता है: एक ड्रॉप uiviews को कई अन्य uiviews के बीच खींचें

यदि आप दूसरे रास्ते पर जाने का फैसला करते हैं, तो यूइबटन के बजाय यूइकंट्रोल का उपयोग करने का प्रयास करें। वे addTarget विधियों की घोषणा करते हैं और विस्तार करने के लिए बहुत आसान होते हैं - इसलिए कस्टम स्थिति और व्यवहार दें।


1

मैं वास्तव में वाहन दृश्य पर बड़े पैमाने पर देखने के बजाय - जब तक कि कोई विशेष कारण नहीं है, तब तक खींचने पर नज़र रखेगा ।

एक मामले में जहां मैं उपयोगकर्ता को स्क्रीन पर खींचकर आइटम रखने की अनुमति देता हूं। उस मामले में मैंने शीर्ष दृश्य और दोनों के साथ प्रयोग किया बच्चे के विचारों को खींचने योग्य । मैंने पाया कि यह क्लीनर कोड है यदि आप UIView को कुछ "ड्रैग करने योग्य" दृश्य जोड़ते हैं और संभालते हैं कि उन्हें कैसे खींचा जा सकता है। मैंने नए स्थान के उपयुक्त होने या न होने की जाँच करने के लिए मूल UIView को एक साधारण कॉलबैक का उपयोग किया - इसलिए मैं एनिमेशन के साथ संकेत दे सकता था।

बीत रहा है शीर्ष दृश्य खींच मुझे लगता है कि ट्रैक अच्छा के रूप में है, लेकिन अगर आप गैर खींचने योग्य विचारों को जोड़ना चाहते हैं कि यह थोड़ा और अधिक गंदा करता है कि अभी भी इस तरह एक बटन के रूप में उपयोगकर्ता, के साथ सहभागिता करते हैं।


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

ओहो के जवाब ने मेरे लिए अच्छा काम किया। मामले में आपको स्विफ्ट 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
}


0

स्विफ्ट 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")
    }

यहां छवि विवरण दर्ज करें

परिणाम देखें ☝️

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.