简体   繁体   中英

disable setMovementMethod(LinkMovementMethod.getInstance()) on android

I'm using setMovementMethod(LinkMovementMethod.getInstance()) for EditText view in my android app. Links inside EditText works fine but in some situations I need programly disable this method (for reason of enable copy item in longClick menu). How to do it? I need something like "removeMovementMethod()".

Can you help me?

Thank you!

After facing the same issue as well, please consider, there seems to be a certain sequence of setting the methods.

  1. Get the 'TextView'
final TextView tv = new TextView(getContext());
  1. Set all necessary layout parameter
tv.setLayoutParams(lp_tv);
  1. Set the Linkify to mark all links in the text as Link
tv.setAutoLinkMask(Linkify.ALL);
  1. Set the content of the TextView (after the setAutoLinkMask )
tv.setText("MyText")
tv.setText(Html.fromHtml("<big>MyText</big>");
  1. Now you can attach the LinkMovementMethod . If the method is attached earlier, it will call the default behavior and open the system browser. I use a TextViewLinkHandler class to do the job as individual behavior. The standard behavior is:
tv.setLinkMovementMethod(new LinkMovementMethod.getInstance());

I use the TextViewLinkHandler to do some other stuff if the user clicks a link (eg opening an individual Intent to process the URL)

 tv.setMovementMethod(new TextViewLinkHandler() {
// do my stuff ... 
// if left blank, nothing will happen on click at the link, so leave it blank to do nothing
});

With the mentioned TextViewLinkHandler()

public abstract class TextViewLinkHandler extends LinkMovementMethod {

        public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) {
            if (event.getAction() != MotionEvent.ACTION_UP)
                return super.onTouchEvent(widget, buffer, event);

            int x = (int) event.getX();
            int y = (int) event.getY();

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

            URLSpan[] link = buffer.getSpans(off, off, URLSpan.class);
            if (link.length != 0) {
                onLinkClick(link[0].getURL());
            }
            return true;
        }

        abstract public void onLinkClick(String url);
    }

After setMovementMethod(null) longClick menu will disable. Therefore better use this method:

setMovementMethod(ArrowKeyMovementMethod.getInstance())
setMovementMethod(null)

would set the textview's movementmethod to null. This could of course cause a NullPointerException if your code wants to handle the MovementMethod in some way.

Like @lubart commented in one of the answers, setting setMovementMethod(null) will not work. You would need to save the previous MovementMethod before setting LinkMovementMethod and restore it again when you do not want to use LinkMovementMethod.

One important thing I want to highlight is that you would have to set AutoLinkMask=0 when restoring back to previous MovementMethod otherwise the links will not go away, the caret will not show and the copy/paste context menu will not appear.

Also, after using setMovementMethod, set the text again in EditText/TextView in order to apply the movement method.

Algorithms (Not the code):

To set link movement method -

previousMovementMethod = editText.MovementMethod;

editText.autoLinkMask = All;
editText.MovementMethod = LinkMovementMethod.GetInstance();
editText.SetText(editText.GetText());

To remove link movement method -

editText.autoLinkMask = 0;
editText.MovementMethod = previousMovementMethod;
editText.SetText(editText.GetText());

Try it :- add this class in your project

import android.text.Layout;
import android.text.Selection;
import android.text.Spannable;
import android.text.method.ArrowKeyMovementMethod;
import android.text.method.MovementMethod;
import android.text.style.ClickableSpan;
import android.view.MotionEvent;
import android.widget.TextView;

/**
 * Created by Nishu on 20-08-2015.
 */
public class MyMovementMethod extends ArrowKeyMovementMethod {

private static MyMovementMethod sInstance;

public static MovementMethod getInstance() {
if (sInstance == null) {
    sInstance = new MyMovementMethod ();
    }
     return sInstance;
    }

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

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

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

    if (link.length != 0) {
        if (action == MotionEvent.ACTION_UP) {
            link[0].onClick(widget);
        }
        else if (action == MotionEvent.ACTION_DOWN) {
            Selection.setSelection(buffer, buffer.getSpanStart(link[0]),   buffer.getSpanEnd(link[0]));
        }

        return true;
    }
    /*else {
        that's the line we need to remove
        Selection.removeSelection(buffer);
    }*/
  }

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

}

now add below line of code with your EditText

YourEditText.setMovementMethod(MyMovementMethod.getInstance());

and remove all type of setMovementMethods from editText Thats it :)

As user5211136 said you can use custom ArrowKeyMovementMethod. Then the text will be selectable and hyperlinks will work too. But the using of class of user5211136 called error

"Actvity was not found for intent, Intent { act=android.intent.action.VIEW dat= https://... (has extras) }"

for me.

That's why I used this class:

public class CustomArrowKeyMovementMethod extends ArrowKeyMovementMethod {

    public static MovementMethod getInstance(){
        return new CustomArrowKeyMovementMethod();
    }

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

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

            if (link.length != 0) {
                if (action == MotionEvent.ACTION_UP) {
                    String url = link[0].getURL().trim();
                    if(url.startsWith("www")) {
                        url = "http://" + url;
                    }
                    if (url.startsWith("https://") || url.startsWith("http://") || url.startsWith("tel:") || url.startsWith("mailto:")) {
                        try {
                            Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
                            widget.getContext().startActivity(browserIntent);
                        } catch (Exception e) {
                            Toast.makeText(widget.getContext(), "Couldn't open url", Toast.LENGTH_LONG).show();
                        }
                    }
                } else {
                    Selection.setSelection(buffer, buffer.getSpanStart(link[0]), buffer.getSpanEnd(link[0]));
                }
                return true;
            }
        }
        return super.onTouchEvent(widget, buffer, event);
    }
}

And called it as:

textView.setMovementMethod();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM