如何在不同单词上点击或触摸TextView文本?

21

如何通过单击带有两个不同单词的文本视图来切换到另一个视图。这是我正在使用的字符串。

By clicking Sign Up, you are indicating that you have read and agree to the 
Term of Use and Privacy Policy.

我想让这两个词(使用条款,隐私政策)显示不同的颜色并可点击。

我知道如何为特定单词设置颜色,但我也想让它们可以被点击。


你好,如何移除这个“widget”,并刷新edittext。ssb.setSpan(new ClickableSpan() {@Override public void onClick(View widget) { // 如何移除这个“widget”,并刷新edittext。 }}, idx1, idx2, 0); - Sakthivel Appavu
5个回答

60

我终于想出如何在TextView中实现多个可点击的部分。

重要的是,它们都必须有自己的ClickableSpan!这是我第一次测试时犯的错误。如果它们具有相同的ClickableSpan实例,则只有最后设置的span被记住。

我创建了一个由"["和"]"包围所需可点击区域的字符串。

String sentence = "this is [part 1] and [here another] and [another one]";

这里是设置TextView的部分,设置setMovementMethod也是必须的:

textView.setMovementMethod(LinkMovementMethod.getInstance());
textView.setText(addClickablePart(sentence), BufferType.SPANNABLE);
我已经创建了这个函数,它将处理可点击区域的创建:
private SpannableStringBuilder addClickablePart(String str) {
    SpannableStringBuilder ssb = new SpannableStringBuilder(str);

    int idx1 = str.indexOf("[");
    int idx2 = 0;
    while (idx1 != -1) {
        idx2 = str.indexOf("]", idx1) + 1;

        final String clickString = str.substring(idx1, idx2);
        ssb.setSpan(new ClickableSpan() {

            @Override
            public void onClick(View widget) {
                Toast.makeText(getView().getContext(), clickString,
                        Toast.LENGTH_SHORT).show();
            }
        }, idx1, idx2, 0);
        idx1 = str.indexOf("[", idx2);
    }

    return ssb;
}

2
这很好,但显示的 sentence 字符串有 [],它们不应该包含在显示的字符串中吗? - Compaq LE2202x
你可以自行决定是否需要这样做,只需将源代码更改为您喜欢的方式即可... - Boy
有时候它会出现错误......比如当点击“这里另一个”时,它会显示“另一个”的 toast 消息。 - Narendra Singh
@DroidWormNarendra也许需要在while循环中每次初始化ssb,而不是在外部仅初始化一次? - Boy
好的,@Boy 我有一个稍微不同的需求......假设我有一个动态词列表,我只需要使整个textview中那些单词可点击。如何实现? - Narendra Singh
显示剩余4条评论

15

根据Boy的回复(感谢您的回复,帮了我很多),这是我实现它的另一种方式,使用内部类来描述可点击的单词,而不使用'['和']'字符:

import java.util.List;

import android.content.Context;
import android.text.SpannableStringBuilder;
import android.text.method.LinkMovementMethod;
import android.text.style.ClickableSpan;
import android.util.AttributeSet;
import android.widget.TextView;

/**
 * Defines a TextView widget where user can click on different words to see different actions
 *
 */
public class ClickableTextView extends TextView {

    public ClickableTextView(Context context) {
        super(context);
    }

    public ClickableTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public ClickableTextView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public void setTextWithClickableWords(String text, List<ClickableWord> clickableWords) {
        setMovementMethod(LinkMovementMethod.getInstance());
        setText(addClickablePart(text, clickableWords), BufferType.SPANNABLE);
    }

    private SpannableStringBuilder addClickablePart(String str, List<ClickableWord> clickableWords) {
        SpannableStringBuilder ssb = new SpannableStringBuilder(str);

        for (ClickableWord clickableWord : clickableWords) {
            int idx1 = str.indexOf(clickableWord.getWord());
            int idx2 = 0;
            while (idx1 != -1) {
                idx2 = idx1 + clickableWord.getWord().length();
                ssb.setSpan(clickableWord.getClickableSpan(), idx1, idx2, 0);
                idx1 = str.indexOf(clickableWord.getWord(), idx2);
            }
        }

        return ssb;
    }

    public static class ClickableWord {
        private String word;
        private ClickableSpan clickableSpan;

        public ClickableWord(String word, ClickableSpan clickableSpan) {
            this.word = word;
            this.clickableSpan = clickableSpan;
        }

        /**
         * @return the word
         */
        public String getWord() {
            return word;
        }

        /**
         * @return the clickableSpan
         */
        public ClickableSpan getClickableSpan() {
            return clickableSpan;
        }
    }
}

希望这可以帮助到某些人

编辑:如何更改链接颜色并去掉下划线:

创建并使用自己的ClickableSpan实现,如下所示:

//a version of ClickableSpan without the underline
public static class NoUnderlineClickableSpan extends ClickableSpan {
    private int color = -1;

    public void setColor(int color) {
        this.color = color;
    }

    @Override
    public void updateDrawState(TextPaint ds) {
        ds.setUnderlineText(false);
        if (this.color != -1) {
            ds.setColor(this.color);
        }
    }
}

太好了!很高兴能帮助你解决这个问题...我想我将再次在我的项目中使用你的类 :) - Boy
谢谢,@Boy,工作得很完美。单词看起来被下划线和蓝色标记了。我该如何设置样式? - Göksel Güren
你必须定义一个自定义的 ClickableSpan 以在 ClickableWord 中使用。我将编辑我的响应并添加它。 - phyzalis
我不知道。如果我想以不同的样式进行设计,现在可能会创建自己的自定义视图来处理它。不过我不确定。写这个已经过了几年了 :) - Boy
1
看看我在编辑后的回复中编写的NoUnderlineClickableSpan类。我没有找到其他下划线的方法。 - phyzalis
1
谢谢,这真的帮了我很多。 - Lorensius W. L. T

8

在TextView中使用HTML链接比创建多个TextView、处理布局、监听器等要简单得多。

在您的Activity或Fragment中:

    TextView mText = (TextView) findViewById(R.id.text_linkified);
    mText.setText(Html.fromHtml("Open <a href='myapp://my-activity'>My Activity</a> or" +
            " <a href='myapp://other-activity'>Other Activity</a>"));
    mText.setMovementMethod(LinkMovementMethod.getInstance());

在清单文件中

    <activity android:name=".MyActivity">
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.DEFAULT"/>
            <data android:scheme="myapp" android:host="my-activity"/>
        </intent-filter>
    </activity>
    <activity android:name=".MyOtherActivity">
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.DEFAULT"/>
            <data android:scheme="myapp" android:host="other-activity" />
        </intent-filter>
    </activity>

1
我这里没有使用URL,只是想通过点击文本打开新的活动。 - RajaReddy PolamReddy
如果文本没有改变,例如它在strings.xml中声明了,那么这就是解决方法。只需将“可点击”的文本声明为具有指向您活动的操作的URL。结果,您将获得只能在单击时打开新活动的文本,取决于您单击的文本的哪个部分。 - pawelzieba
我已编辑答案,因为有人在恶意投票。 - pawelzieba
如果你想将 Parcelable 对象传递给新的 Activity 呢? - phyzalis

3
我推荐这个库:https://github.com/klinker24/Android-TextView-LinkBuilder,它非常适合您的要求。
快速概述: enter image description here 从项目的自述文件中复制而来: - 指定 TextView 中特定单词的长按和短按动作 - 当用户触摸文本时,通过突出显示文本提供用户反馈 - 匹配单个字符串或使用正则表达式将可点击链接设置为与该模式相符的任何文本 - 更改链接文本的颜色 - 修改用户触摸时文本高亮的透明度 - 设置是否要在文本下面画线
与 TextView 的自动链接功能相比,使用此库的主要优点是可以链接任何东西,而不仅仅是网址、电子邮件和电话号码。它还提供了颜色自定义和触摸反馈。

0
在ClickableTextView的实现中,如果字符串中有一个重复的单词会发生什么? 例如,假设字符串是“I'm clickable and also this is clickable”,那么这两个字符串都应该被更改为Spannable字符串,但在这种情况下会失败,只有一个会被更改为Spannable字符串。

你可以看一下我的答案,它会循环遍历所有的单词。 - phyzalis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接