Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Android - How can I register only long clicks using a ClickableSpan

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

like image 659
Victor Grazi Avatar asked Jan 02 '12 15:01

Victor Grazi


People also ask

What is clickable span?

A ClickableSpan for a TextLink. URLSpan. Implementation of the ClickableSpan that allows setting a url string. If an object of this type is attached to the text of a TextView with a movement method of LinkMovementMethod, the affected spans of text can be selected.

How do you set the part of the text view is clickable in Android?

This example demonstrates how do I set the part of the Android textView as clickable. Step 1 − Create a new project in Android Studio, go to File ⇒ New Project and fill all required details to create a new project. Step 2 − Add the following code to res/layout/activity_main. xml.

How do you make text clickable on Android?

Just like Buttons and ImageViews we can add onClickListeners to TextViews by simply adding the attribute android:onClick="myMethod" to your TextView XML tag. The other way, TextView tv = (TextView) this.


2 Answers

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.

like image 154
comodoro Avatar answered Oct 25 '22 15:10

comodoro


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

    }
like image 41
rupps Avatar answered Oct 25 '22 15:10

rupps