android maps: How to Long Click a Map?

后端 未结 8 1816
遥遥无期
遥遥无期 2020-12-02 12:41

How do I long click on a mapview so that a place marker appears at that point on the map?

I tried a couple ways without success:

1) Using setOnLongCl

8条回答
  •  生来不讨喜
    2020-12-02 13:17

    This works with your MapActivity and will allow you to:

    1. Set your own time threshold for what constitutes a long press on the map (0.8 seconds is good for me).
    2. Not interpret a scroll, multi-touch, or non-multi-touch event as a long press. It also let's you set a tolerance for someone's finger to ever so slightly move on the screen as they are holding down a long press.

    This solution is based on Roger Kristiansen's solution. I added x and y point detection so that scrolling is not seen as a long press. This solution is not as elegant as Roger's because I use class variables and put the code in my existing MapActivity instead of extending MapView and creating a listener like he did. But if you want to stick with his code but have better non-multi-touch support, just take the x and y point stuff out of mine and add it to his.


    Class variables set at the top of my MapActivity:

    //variable for determining long press and then automatically adding a pin to the map
    private int minMillisecondThresholdForLongClick = 800;
    private long startTimeForLongClick = 0;
    private float xScreenCoordinateForLongClick;
    private float yScreenCoordinateForLongClick;
    private float xtolerance=10;//x pixels that your finger can be off but still constitute a long press
    private float ytolerance=10;//y pixels that your finger can be off but still constitute a long press
    private float xlow; //actual screen coordinate when you subtract the tolerance
    private float xhigh; //actual screen coordinate when you add the tolerance
    private float ylow; //actual screen coordinate when you subtract the tolerance
    private float yhigh; //actual screen coordinate when you add the tolerance
    

    Add this function in your MapActivity:

        @Override
        public boolean dispatchTouchEvent(MotionEvent ev) {
            /* We want to capture the place the user long pressed on the map and add a marker (pin) on the map at that lat/long.
             * This solution:
             *  1. Allows you to set the time threshold for what constitutes a long press
             *  2. Doesn't get fooled by scrolling, multi-touch, or non-multi-touch events
    
             * Thank you Roger Kind Kristiansen for the main idea
             */     
    
            //get the action from the MotionEvent: down, move, or up
            int actionType = ev.getAction();
    
            if (actionType == MotionEvent.ACTION_DOWN) {
                //user pressed the button down so let's initialize the main variables that we care about:
                // later on when the "Action Up" event fires, the "DownTime" should match the "startTimeForLongClick" that we set here  
                // the coordinate on the screen should not change much during the long press
                startTimeForLongClick=ev.getEventTime();
                xScreenCoordinateForLongClick=ev.getX();
                yScreenCoordinateForLongClick=ev.getY();
    
            } else if (actionType == MotionEvent.ACTION_MOVE) {
                //For non-long press actions, the move action can happen a lot between ACTION_DOWN and ACTION_UP                    
                if (ev.getPointerCount()>1) {
                    //easiest way to detect a multi-touch even is if the pointer count is greater than 1
                    //next thing to look at is if the x and y coordinates of the person's finger change.
                    startTimeForLongClick=0; //instead of a timer, just reset this class variable and in our ACTION_UP event, the DownTime value will not match and so we can reset.                        
                } else {
                    //I know that I am getting to the same action as above, startTimeForLongClick=0, but I want the processor
                    //to quickly skip over this step if it detects the pointer count > 1 above
                    float xmove = ev.getX(); //where is their finger now?                   
                    float ymove = ev.getY();
                    //these next four values allow you set a tiny box around their finger in case
                    //they don't perfectly keep their finger still on a long click.
                    xlow = xScreenCoordinateForLongClick - xtolerance;
                    xhigh= xScreenCoordinateForLongClick + xtolerance;
                    ylow = yScreenCoordinateForLongClick - ytolerance;
                    yhigh= yScreenCoordinateForLongClick + ytolerance;
                    if ((xmove xhigh) || (ymove yhigh)){
                        //out of the range of an acceptable long press, reset the whole process
                        startTimeForLongClick=0;
                    }
                }
    
            } else if (actionType == MotionEvent.ACTION_UP) {
                //determine if this was a long click:
                long eventTime = ev.getEventTime();
                long downTime = ev.getDownTime(); //this value will match the startTimeForLongClick variable as long as we didn't reset the startTimeForLongClick variable because we detected nonsense that invalidated a long press in the ACTION_MOVE block
    
                //make sure the start time for the original "down event" is the same as this event's "downTime"
                if (startTimeForLongClick==downTime){ 
                    //see if the event time minus the start time is within the threshold
                    if ((eventTime-startTimeForLongClick)>minMillisecondThresholdForLongClick){ 
                        //make sure we are at the same spot where we started the long click
                        float xup = ev.getX();                  
                        float yup = ev.getY();
                        //I don't want the overhead of a function call:
                        xlow = xScreenCoordinateForLongClick - xtolerance;
                        xhigh= xScreenCoordinateForLongClick + xtolerance;
                        ylow = yScreenCoordinateForLongClick - ytolerance;
                        yhigh= yScreenCoordinateForLongClick + ytolerance;
                        if ((xup>xlow && xupylow && yup

提交回复
热议问题