android - चाल के बीच अंतर कैसे करें और onTouchEvent() में क्लिक करें?




event-handling android-event (7)

ACTION_DOWN होने के लिए ACTION_MOVE होने के बिना यह बहुत मुश्किल है। स्क्रीन पर अपनी उंगली की थोड़ी सी चिकनाई एक दूसरे स्थान पर जहां से पहले स्पर्श हुआ था, उस स्थान पर चले गए घटना को ट्रिगर किया जाएगा। इसके अलावा, मेरा मानना ​​है कि उंगली के दबाव में परिवर्तन भी घटना को गति देगा। मैं Action_Move विधि में एक if स्टेटमेंट का उपयोग दूरी को निर्धारित करने की कोशिश करने के लिए करता हूं, मूल गति से गति से होने वाली चाल यदि यह कदम कुछ सेट त्रिज्या के बाहर होता है, तो आपका चलना होगा। यह शायद सबसे अच्छा, संसाधन कुशल तरीका है जो आपकी कोशिश कर रहा है लेकिन यह काम करना चाहिए।

मेरे आवेदन में, मुझे दोनों चाल को संभालना और इवेंट्स पर क्लिक करना होगा।

एक क्लिक एक ACTION_DOWN कार्रवाई का एक अनुक्रम है, कई ACTION_MOVE कार्रवाइयां और एक ACTION_UP कार्रवाई सिद्धांत रूप में, यदि आप एक ACTION_DOWN ईवेंट प्राप्त करते हैं और फिर एक ACTION_UP ईवेंट - इसका मतलब है कि उपयोगकर्ता ने अभी आपके दृश्य पर क्लिक किया है

लेकिन व्यवहार में, यह अनुक्रम कुछ उपकरणों पर काम नहीं करता है। मेरे सैमसंग गैलेक्सी जीओ पर मुझे केवल मेरे दृश्य पर क्लिक करते समय ACTION_DOWN, कई बार ACTION_MOVE, उसके बाद ACTION_UP मिलते हैं I यानी मुझे ACTION_MOVE कार्रवाई कोड के साथ कुछ अप्रत्याशित OnTouchEvent फायरिंग मिलती है I मैं कभी भी (या लगभग कभी नहीं) अनुक्रम ACTION_DOWN प्राप्त -> ACTION_UP

मैं भी OnClickListener का उपयोग नहीं कर सकता क्योंकि यह क्लिक की स्थिति नहीं देता है तो मैं कैसे क्लिक ईवेंट का पता लगा सकता हूं और इसे स्थानांतरित करने से अलग कर सकता हूं?


नीचे कोड आपकी समस्या का समाधान करेगा

    @Override
        public boolean onTouchEvent(MotionEvent event) {
            switch(event.getAction()) {
                case(MotionEvent.ACTION_DOWN):
                    x1 = event.getX();
                    y1 = event.getY();
                    break;
                case(MotionEvent.ACTION_UP): {
                    x2 = event.getX();
                    y2 = event.getY();
                    dx = x2-x1;
                    dy = y2-y1;

                if(Math.abs(dx) > Math.abs(dy)) 
                {
                    if(dx>0) move(1); //right
                    else if (dx == 0) move(5); //click
                    else move(2); //left
                } 
                else 
                {
                    if(dy>0) move(3); // down
                    else if (dy == 0) move(5); //click
                    else move(4); //up
                }
                }
            }
            return true;
        }


यहाँ एक और समाधान है जो बहुत आसान है और आपको उंगली को स्थानांतरित करने के बारे में चिंता करने की आवश्यकता नहीं है। यदि आप बस एक क्लिक के आधार के आधार पर स्थित हैं, तो आप एक क्लिक और एक लंबे क्लिक को कैसे अलग कर सकते हैं।

आप इसमें और अधिक स्मर्ट लगा सकते हैं और दूरी को स्थानांतरित कर सकते हैं, लेकिन एक उदाहरण के दौरान जब मैं एक क्लिक के विरोध में एक उपयोगकर्ता 200 मिलीसेकंड में स्थानांतरित कर सकता है, तो एक कदम का गठन होना चाहिए।

setOnTouchListener(new OnTouchListener() {
    private static final int MAX_CLICK_DURATION = 200;
    private long startClickTime;

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN: {
                startClickTime = Calendar.getInstance().getTimeInMillis();
                break;
            }
            case MotionEvent.ACTION_UP: {
                long clickDuration = Calendar.getInstance().getTimeInMillis() - startClickTime;
                if(clickDuration < MAX_CLICK_DURATION) {
                    //click event has occurred
                }
            }
        }
        return true;
    }
});

यदि आप केवल क्लिक पर प्रतिक्रिया करना चाहते हैं, तो इसका उपयोग करें:

if (event.getAction() == MotionEvent.ACTION_UP) {

}

गिल एसएच उत्तर का उपयोग करते हुए, मैंने इसे onSingleTapUp() बजाय onSingleTapUp() कार्यान्वित करके बेहतर किया यह बहुत तेज़ है और खींचें / स्थानांतरित होने पर दृश्य पर क्लिक नहीं करेंगे

GestureTap:

public class GestureTap extends GestureDetector.SimpleOnGestureListener {
    @Override
    public boolean onSingleTapUp(MotionEvent e) {
        button.performClick();
        return true;
    }
}

इसे पसंद करें:

final GestureDetector gestureDetector = new GestureDetector(getApplicationContext(), new GestureTap());
button.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        gestureDetector.onTouchEvent(event);
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                return true;
            case MotionEvent.ACTION_UP:
                return true;
            case MotionEvent.ACTION_MOVE:
                return true;
        }
        return false;
    }
});

मुझे ध्यान में रखते हुए सर्वोत्तम परिणाम मिला:

  1. मुख्य रूप से, दूरी ACTION_DOWN और ACTION_UP ईवेंट के बीच चली गई। मैं विभिन्न स्क्रीनों का बेहतर समर्थन करने के लिए पिक्सल के बजाय घनत्व-इंडेपेंन्ट पिक्सल में अधिकतम अनुमत दूरी निर्दिष्ट करना चाहता हूं। उदाहरण के लिए, 15 डीपी
  2. दूसरे, घटनाओं के बीच की अवधि एक सेकंड अच्छा अधिकतम लग रहा था (कुछ लोग "काफी" "थोरौगली" पर क्लिक करते हैं, यानी धीरे-धीरे, मैं अब भी इसे पहचानना चाहता हूं।)

उदाहरण:

/**
 * Max allowed duration for a "click", in milliseconds.
 */
private static final int MAX_CLICK_DURATION = 1000;

/**
 * Max allowed distance to move during a "click", in DP.
 */
private static final int MAX_CLICK_DISTANCE = 15;

private long pressStartTime;
private float pressedX;
private float pressedY;

@Override
public boolean onTouchEvent(MotionEvent e) {
     switch (e.getAction()) {
        case MotionEvent.ACTION_DOWN: {
            pressStartTime = System.currentTimeMillis();                
            pressedX = e.getX();
            pressedY = e.getY();
            break;
        }
        case MotionEvent.ACTION_UP: {
            long pressDuration = System.currentTimeMillis() - pressStartTime;
            if (pressDuration < MAX_CLICK_DURATION && distance(pressedX, pressedY, e.getX(), e.getY()) < MAX_CLICK_DISTANCE) {
                // Click event has occurred
            }
        }     
    }
}

private static float distance(float x1, float y1, float x2, float y2) {
    float dx = x1 - x2;
    float dy = y1 - y2;
    float distanceInPx = (float) Math.sqrt(dx * dx + dy * dy);
    return pxToDp(distanceInPx);
}

private static float pxToDp(float px) {
    return px / getResources().getDisplayMetrics().density;
}

यहां पर विचार मणि के समाधान के समान है , इन अंतरों के साथ:

  • यह दो अंकों के बीच वास्तविक युक्लिडियन दूरी की गणना करता है।
  • यह पीएक्स के बजाय डीपी का उपयोग करता है

अपडेट (2015): इसके बारे में गेब्रियल के ठीक-ठीक संस्करण देखें


डिटेक्टर का उपयोग करें, यह काम करता है, और यह खींचने के मामले में उठाना नहीं होगा

खेत:

private GestureDetector mTapDetector;

प्रारंभ:

mTapDetector = new GestureDetector(context,new GestureTap());

आंतरिक वर्ग:

class GestureTap extends GestureDetector.SimpleOnGestureListener {
    @Override
    public boolean onDoubleTap(MotionEvent e) {

        return true;
    }

    @Override
    public boolean onSingleTapConfirmed(MotionEvent e) {
        // TODO: handle tap here
        return true;
    }
}

छूने पर:

@Override
public boolean onTouch(View v, MotionEvent event) {
    mTapDetector.onTouchEvent(event);
    return true;
}

का आनंद लें :)





android-event