public class

LinkMovementMethodCompat

extends LinkMovementMethod

 java.lang.Object

↳LinkMovementMethod

↳androidx.core.text.method.LinkMovementMethodCompat

Gradle dependencies

compile group: 'androidx.core', name: 'core', version: '1.15.0-alpha02'

  • groupId: androidx.core
  • artifactId: core
  • version: 1.15.0-alpha02

Artifact androidx.core:core:1.15.0-alpha02 it located at Google repository (https://maven.google.com/)

Androidx artifact mapping:

androidx.core:core com.android.support:support-compat

Overview

Backwards compatible version of which fixes the issue that links can be triggered for touches outside of line bounds before Android V.

Summary

Methods
public static LinkMovementMethodCompatgetInstance()

Retrieves the singleton instance of LinkMovementMethodCompat.

public booleanonTouchEvent(TextView widget, Spannable buffer, MotionEvent event)

from java.lang.Objectclone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

Methods

public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event)

public static LinkMovementMethodCompat getInstance()

Retrieves the singleton instance of LinkMovementMethodCompat.

Returns:

the singleton instance of LinkMovementMethodCompat

Source

/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package androidx.core.text.method;

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

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.OptIn;
import androidx.core.os.BuildCompat;

/**
 * Backwards compatible version of {@link LinkMovementMethod} which fixes the issue that links can
 * be triggered for touches outside of line bounds before Android V.
 */
public class LinkMovementMethodCompat extends LinkMovementMethod {
    private static LinkMovementMethodCompat sInstance;

    private LinkMovementMethodCompat() {}

    @OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class)
    @Override
    public boolean onTouchEvent(@Nullable TextView widget, @Nullable Spannable buffer,
            @Nullable MotionEvent event) {
        if (!BuildCompat.isAtLeastV()) {
            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();
                boolean isOutOfLineBounds;
                if (y < 0 || y > layout.getHeight()) {
                    isOutOfLineBounds = true;
                } else {
                    int line = layout.getLineForVertical(y);
                    isOutOfLineBounds = x < layout.getLineLeft(line)
                            || x > layout.getLineRight(line);
                }

                if (isOutOfLineBounds) {
                    Selection.removeSelection(buffer);

                    // The same as super.onTouchEvent() in LinkMovementMethod.onTouchEvent(), i.e.
                    // ScrollingMovementMethod.onTouchEvent().
                    return Touch.onTouchEvent(widget, buffer, event);
                }
            }
        }

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

    /**
     * Retrieves the singleton instance of {@link LinkMovementMethodCompat}.
     *
     * @return the singleton instance of {@link LinkMovementMethodCompat}
     */
    @NonNull
    public static LinkMovementMethodCompat getInstance() {
        if (sInstance == null) {
            sInstance = new LinkMovementMethodCompat();
        }

        return sInstance;
    }
}