In Android - How can I register only long clicks u

2019-02-04 18:18发布

问题:

I would like to register clicks on a text wrapped in a ClickableSpan only if they are clicked for over say 1 second. Is there any way to do this? If not, capturing a double click would also be fine.

It would be great if the onClick method captured an event that had some meta data about the click - then I could say ignore if the click length was short.

Any advice?

Thanks, Victor

回答1:

In case anyone needs it, I found it on this place

    package leeon.mobile.BBSBrowser;

    import android.text.Layout;
    import android.text.Selection;
    import android.text.Spannable;
    import android.text.method.LinkMovementMethod;
    import android.text.method.MovementMethod;
    import android.view.MotionEvent;
    import android.widget.TextView;

    public class LongClickLinkMovementMethod extends LinkMovementMethod {

      private Long lastClickTime = 0l;
      private int lastX = 0;
      private int lastY = 0;
      @Override
        public boolean onTouchEvent(TextView widget, Spannable buffer,
                                    MotionEvent event) {
            int action = event.getAction();

            if (action == MotionEvent.ACTION_UP ||
                action == MotionEvent.ACTION_DOWN) {
                int x = (int) event.getX();
                int y = (int) event.getY();
                lastX = x;
                lastY = y;
                int deltaX = Math.abs(x-lastX);
                int deltaY = Math.abs(y-lastY);

                x -= widget.getTotalPaddingLeft();
                y -= widget.getTotalPaddingTop();

                x += widget.getScrollX();
                y += widget.getScrollY();

                Layout layout = widget.getLayout();
                int line = layout.getLineForVertical(y);
                int off = layout.getOffsetForHorizontal(line, x);

                LongClickableSpan[] link = buffer.getSpans(off, off, LongClickableSpan.class);

                if (link.length != 0) {
                    if (action == MotionEvent.ACTION_UP) {
                      if (System.currentTimeMillis() - lastClickTime < 1000)
                        link[0].onClick(widget);
                      else if (deltaX < 10 && deltaY < 10)
                        link[0].onLongClick(widget);
                    } else if (action == MotionEvent.ACTION_DOWN) {
                        Selection.setSelection(buffer,
                                               buffer.getSpanStart(link[0]),
                                               buffer.getSpanEnd(link[0]));
                        lastClickTime = System.currentTimeMillis();
                    }
                    return true;
                }
            }

            return super.onTouchEvent(widget, buffer, event);
        }


        public static MovementMethod getInstance() {
            if (sInstance == null)
                sInstance = new LongClickLinkMovementMethod();

            return sInstance;
        }

        private static LongClickLinkMovementMethod sInstance;
    }


      [1]: http://java2s.com/Open-Source/Java/SSH/brick-leeon/leeon/mobile/BBSBrowser/LongClickLinkMovementMethod.java.htm

LongClickableSpan in the same place:

    package leeon.mobile.BBSBrowser;

    import android.text.style.ClickableSpan;
    import android.view.View;

    public abstract class LongClickableSpan extends ClickableSpan {

      abstract public void onLongClick(View view);

    }


回答2:

I want to do the same, the only method that comes to mind is custom MovementMethod class replacing LinkMovementMethod and a replacement for ClickableSpan that adds a long click abstract method. It is actually quite simple:

  1. Download Android source and locate the LinkMovementMethod and ClickableSpan classes
  2. Create MyCustomClickableSpan class from ClickableSpan with added abstract method onLongClick()
  3. Create MyCustomLinkMovementMethod class from LinkMovementMethod where onTouchEvent is customized so that it calls MyCustomClickableSpan's onLongClick() in the right place
  4. Use the new classes in your code instead of LinkMovementMethod and ClickableSpan

EDIT: Works like a charm. I've made some stupid mistakes like downloading LinkMovementMethod from different Android version and not using the new ClickableSpan class in setSpan(), but nothing serious.