我有以下TextView定义:
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:text="@string/txtCredits"
android:autoLink="web" android:id="@+id/infoTxtCredits"
android:layout_centerInParent="true"
android:linksClickable="true"/>
其中@string/txtCredits是一个字符串资源,包含<a href="some site">链接文本</a>。
Android正在突出显示TextView中的链接,但它们不响应单击。我做错了什么?我必须在我的活动中为TextView设置一个onClickListener像这样简单吗?
它看起来和我定义字符串资源的方式有关。
这行不通:
<string name="txtCredits"><a href="http://www.google.com">Google</a></string>
但这确实是:
<string name="txtCredits">www.google.com</string>
这是一个遗憾,因为我宁愿显示一个文本链接,而不是显示完整的URL。
在API演示中,我找到了问题的解决方案:
文件Link.java:
// text2 has links specified by putting <a> tags in the string
// resource. By default these links will appear but not
// respond to user input. To make them active, you need to
// call setMovementMethod() on the TextView object.
TextView t2 = (TextView) findViewById(R.id.text2);
t2.setMovementMethod(LinkMovementMethod.getInstance());
我删除了我的TextView上的大部分属性,以匹配演示中的内容。
<TextView
android:id="@+id/text2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/txtCredits"/>
这就解决了问题。它很难发现和修复。
重要:不要忘记删除autoLink="web"如果你正在调用setMovementMethod()。
上面的解决方案对我没用,但是下面的解决方案对我有用(而且看起来更简洁)。
首先,在字符串资源中,使用HTML实体编码定义标签开头的v形符号,即:
<a href="http://www.google.com">Google</a>
而不是:
<a href="http://www.google.com">Google</a>
一般来说,像这样编码字符串中的所有v形符号。顺便说一下,链接必须以http://开头
然后(正如这里所建议的)在你的TextView上设置这个选项:
android:linksClickable="true"
最后,在代码中,执行以下操作:
((TextView) findViewById(R.id.your_text_view)).setMovementMethod(LinkMovementMethod.getInstance());
((TextView) findViewById(R.id.your_text_view)).setText(Html.fromHtml(getResources().getString(R.string.string_with_links)));
就是这样。不需要正则表达式或其他手工操作。
我注意到使用android:autoLink="web"因此
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:autoLink="web"/>
对于url来说工作得很好,但是因为我有一个电子邮件地址和电话号码,我想要链接,我最终使用这一行android:autoLink="all"像这样
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:autoLink="all"/>
而且效果很好。
我不得不在几个地方寻找这个,但我最终得到了这个版本的代码。
文件strings.xml:
<string name="name1"><a href="http://www.google.com">link text1</a></string>
<string name="name2"><a href="http://www.google.com">link text2</a></string>
文件myactivity.xml:
<TextView
android:id="@+id/textview1"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_marginTop="5dp" />
<TextView
android:id="@+id/textview2"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_marginTop="5dp" />
文件myactivity .java(在onCreate()):
TextView tv1 = (TextView)findViewById(R.id.textview1);
TextView tv2 = (TextView)findViewById(R.id.textview2);
tv1.setText(Html.fromHtml(getResources().getString(R.string.name1)));
tv2.setText(Html.fromHtml(getResources().getString(R.string.name2)));
tv1.setMovementMethod(LinkMovementMethod.getInstance());
tv2.setMovementMethod(LinkMovementMethod.getInstance());
这将创建两个可点击的超链接,文本链接text1和链接text2将用户重定向到谷歌。
理查德,下次,你应该在布局XML的TextView下添加这段代码。
android:autoLink="all"
应该是这样的。
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/txtCredits"
android:id="@+id/infoTxtCredits"
android:autoLink="all"
android:linksClickable="true">
</TextView>
您不需要使用此代码(t2.setMovementMethod(LinkMovementMethod.getInstance());)来使链接可单击。
另外,这里有一个事实:只要你设置了autoLink和linksClickable,不要忘记在String.xml文件中添加这个,这样可点击的链接就可以工作了。
<string name="txtCredits"><a href="http://www.google.com">Google</a></string>
在花了一段时间之后,我发现:
android:autoLink="web"工作,如果你有完整的链接在你的HTML。以下内容将以蓝色高亮显示,并可点击:
Some text <a href="http://www.google.com">http://www.google.com</a> .
一些文字http://www.google.com
view.setMovementMethod (LinkMovementMethod.getInstance ());将与以下工作(将突出显示和可点击):
Some text <a href="http://www.google.com">http://www.google.com</a> .
一些文字http://www.google.com
一些文本<a href="http://www.google.com">转到谷歌</a>
注意,第三个选项有一个超链接,但是链接的描述(标签之间的部分)本身并不是链接。android:autoLink="web"不工作与这样的链接。
android:autoLink="web"如果在XML中设置将覆盖view.setMovementMethod(LinkMovementMethod.getInstance());(即。第三类链接将被突出显示,但不能点击)。
这个故事的寓意是使用view.setMovementMethod(LinkMovementMethod.getInstance());在你的代码中,确保你没有android:autoLink="web"在你的XML布局中,如果你想要所有的链接都是可点击的。
我添加了这一行到TextView: android:autoLink="web"
下面是布局文件中的一个使用示例。
layout.xml
<TextView
android:id="@+id/txtLostpassword"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:autoLink="email"
android:gravity="center"
android:padding="20px"
android:text="@string/lostpassword"
android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
android:id="@+id/txtDefaultpassword"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:autoLink="web"
android:gravity="center"
android:padding="20px"
android:text="@string/defaultpassword"
android:textAppearance="?android:attr/textAppearanceSmall" />
string.xml
<string name="lostpassword">If you lost your password please contact <a href="mailto:support@cleverfinger.com.au?Subject=Lost%20Password" target="_top">support@cleverfinger.com.au</a></string>
<string name="defaultpassword">User Guide <a href="http://www.cleverfinger.com.au/user-guide/">http://www.cleverfinger.com.au/user-guide/</a></string>
我使用自动链接来“自动下划线”文本,但我只是做了一个“onClick”来管理它(我自己遇到了这个问题)。
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
android:textSize="18dp"
android:autoLink="all"
android:text="@string/twitter"
android:onClick="twitter"/>
public void twitter (View view)
{
try
{
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://twitter.com/onaclovtech"));
startActivity(browserIntent);
}
finally
{
}
}
它不需要任何权限,因为你将意图传递给管理这些资源的应用程序(即浏览器)。
这对我来说很管用。
我只是浪费了很多时间来弄清楚你必须使用getText(R.string.whatever)而不是getString(R.string.whatever)…
总之,我是这么做的。在同一个文本视图中也有多个超链接。
TextView termsTextView = (TextView) getActivity().findViewById(R.id.termsTextView);
termsTextView.append("By registering your account, you agree to our ");
termsTextView.append(getText(R.string.terms_of_service));
termsTextView.append(", ");
termsTextView.append(getText(R.string.fees));
termsTextView.append(", and the ");
termsTextView.append(getText(R.string.stripe_connected_account_agreement));
termsTextView.setMovementMethod(LinkMovementMethod.getInstance());
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/termsTextView"/>
字符串的例子:
<string name="stripe_connected_account_agreement"><a href="https://stripe.com/connect/account-terms">Stripe Connected Account Agreement</a></string>
由于数据绑定是出来的,我想分享我的解决方案数据绑定TextViews支持HTML标签与可点击的链接。
为了避免检索每个textview并使用From.html为他们提供html支持,我们扩展了textview并将逻辑放在setText()中
public class HtmlTextView extends TextView {
public HtmlTextView(Context context) {
super(context);
}
public HtmlTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public HtmlTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public void setText(CharSequence text, BufferType type) {
super.setText(Html.fromHtml(text.toString()), type);
this.setMovementMethod(LinkMovementMethod.getInstance());
}
}
我已经做了一个主旨,也显示了使用这个实体和视图的例子。
我的代码是这样的:
<TextView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/link"
android:text="@string/forgot"
android:layout_marginTop="16dp"
android:gravity="center"
android:linksClickable="true"/>
我的Java代码是这样的:
/*TextView action*/
TextView textView = (TextView) findViewById(R.id.link);
textView.setMovementMethod(LinkMovementMethod.getInstance());
textView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(LoginActivity.this,forgot.class));
}
});
这只是将链接指向另一个活动。但这个链接是可点击的,而且工作流畅。在Android Studio 1.5中测试(预览)
接受的答案是正确的,但这意味着电话号码、地图、电子邮件地址和常规链接(例如,没有href标记的http://google.com)将不再是可点击的,因为您不能在XML内容中具有自动链接。
我所发现的唯一完整的解决方案是:
Spanned text = Html.fromHtml(myString);
URLSpan[] currentSpans = text.getSpans(0, text.length(), URLSpan.class);
SpannableString buffer = new SpannableString(text);
Linkify.addLinks(buffer, Linkify.ALL);
for (URLSpan span : currentSpans) {
int end = text.getSpanEnd(span);
int start = text.getSpanStart(span);
buffer.setSpan(span, start, end, 0);
}
textView.setText(buffer);
textView.setMovementMethod(LinkMovementMethod.getInstance());
TextView不应该有android:autolink。没有必要android:linksClickable="true";默认情况下是正确的。
以下内容应该适用于在Android应用程序中寻找文本和超链接组合的任何人。
在string.xml:
<string name="applink">Looking for Digital Visiting card?
<a href="https://play.google.com/store/apps/details?id=com.themarkwebs.govcard">Get it here</a>
</string>
现在你可以在任何给定的视图中使用这个字符串,就像这样:
<TextView
android:id="@+id/getapp"
android:layout_width="match_parent"
android:layout_height="50dp"
android:gravity="center"
android:textColor="@color/main_color_grey_600"
android:textSize="15sp"
android:text="@string/applink"/>
现在,在您的活动或片段中,执行以下操作:
TextView getapp =(TextView) findViewById(R.id.getapp);
getapp.setMovementMethod(LinkMovementMethod.getInstance());
到目前为止,你不需要设置android:autoLink="web"或android:linksClickable="true"使用这种方法。
[预棒棒糖测试以及棒棒糖及以上测试]
您可以从后端或资源文件中获取HTML字符串。
如果你把文本作为资源字符串,请确保添加CDATA标签:
<string name="your_text">![CDATA[...<a href="your_link">Link Title</a> ...]]</string>
然后在代码中,你需要获取字符串并将其赋值为HTML,并设置一个链接移动方法:
String yourText = getString(R.string.your_text);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
textView.setText(Html.fromHtml(yourText, Html.FROM_HTML_MODE_COMPACT));
} else {
textView.setText(Html.fromHtml(yourText));
}
try {
subtext.setMovementMethod(LinkMovementMethod.getInstance());
} catch (Exception e) {
//This code seems to crash in some Samsung devices.
//You can handle this edge case base on your needs.
}
在SpannableString上创建一个扩展方法:
private fun SpannableString.setLinkSpan(text: String, url: String) {
val textIndex = this.indexOf(text)
setSpan(
object : ClickableSpan() {
override fun onClick(widget: View) {
Intent(Intent.ACTION_VIEW).apply { data = Uri.parse(url) }.also { startActivity(it) }
}
},
textIndex,
textIndex + text.length,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
)
}
使用它使字符串在你的TextView可点击:
myTextView.apply {
movementMethod = LinkMovementMethod.getInstance()
val googleUrl = "http://www.google.com"
val microsoftUrl = "http://www.microsoft.com"
val google = "Google"
val microsoft = "Microsoft"
val message = SpannableString("$google & $microsoft").apply {
setLinkSpan(google, googleUrl)
setLinkSpan(microsoft, microsoftUrl)
}
text = message
}
享受吧!
用这个:
package com.stackoverflow.java.android;
import android.content.Context;
import android.text.method.LinkMovementMethod;
import android.text.method.MovementMethod;
import android.util.AttributeSet;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatTextView;
public class HyperlinkTextView extends AppCompatTextView {
public HyperlinkTextView(Context context) {
super(context);
}
public HyperlinkTextView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public HyperlinkTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
/**
* Set default movement method to {@link LinkMovementMethod}
* @return Link movement method as the default movement method
*/
@Override
protected MovementMethod getDefaultMovementMethod() {
return LinkMovementMethod.getInstance();
}
}
现在,简单地使用com.stackoverflow.java.android.HyperlinkTextView而不是TextView在你的布局文件将解决你的问题。
你可以简单地添加链接到你的TextView与Android的Linkify库。
添加到你的strings.xml
<string name="text_legal_notice">By continuing, you confirm that you have read, understood and agreed to our %1$s and %2$s.</string>
<string name="text_terms_conditions">Terms & Conditions</string>
<string name="text_privacy_policy">Privacy Policy</string>
加入到你的活动中
final String termsConditionsText = getString(R.string.text_terms_conditions);
final String privacyPolicyText = getString(R.string.text_privacy_policy);
final String legalText = getString(
R.string.text_legal_notice,
termsConditionsText,
privacyPolicyText
);
viewBinding.textViewLegalNotice.setText(legalText);
Linkify.addLinks(
viewBinding.textViewLegalNotice,
Pattern.compile(termsConditionsText),
null,
null,
(match, url) -> "https://policies.google.com/terms"
);
Linkify.addLinks(
viewBinding.textViewLegalNotice,
Pattern.compile(privacyPolicyText),
null,
null,
(match, url) -> "https://policies.google.com/privacy"
);
我并不是要把它打得死死的,但下面是在Linkfy等人的被窝里发生的事情。您将注意到setText()接受CharSequence。Linkify等将字符串转换为span,并添加span。Spannable间接继承CharSequence,就像String一样,所以它与setText()一起工作。使用Spannables,你可以混合和匹配跨度,做各种有趣的事情。这里有一个简单的例子。
val textView = findViewById<TextView>(R.id.myTextView)
val span = SpannableStringBuilder(getString(R.string.linkText))
textView [0, textView .length] = URLSpan("https://myWebiste.com/")
textView.text = span
textView.movementMethod = LinkMovementMethod.getInstance()
需要注意的是,Kotlin语法非常流畅,但它混淆了Spannable.setSpan()调用,这就是魔术发生的地方。