java Android 上 TextView 中的多个可点击链接
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28720117/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Multiple Clickable links in TextView on Android
提问by AndroidEnthusiast
I'm trying to add multiple links in a textview similar to what Google & Flipboard has done below with their Terms and conditionsAND Privacy Policyshown in the screen shot below:
我想添加多个链接以类似于谷歌与Flipboard的下面已经与他们做一个TextView条款和条件及隐私政策的屏幕截图如下图所示:
So far I've stumbled on using this approach
到目前为止,我偶然发现了使用这种方法
textView.setText(Html.fromHtml(myHtml); textView.setMovementMethod(LinkMovementMethod.getInstance());
textView.setText(Html.fromHtml(myHtml); textView.setMovementMethod(LinkMovementMethod.getInstance());
where myHtml is a href.
其中 myHtml 是一个 href。
But it doesn't give me control I need e.g to launch a fragment etc.
但这并没有让我控制我需要的控制,例如启动片段等。
Any idea how they achieve this in the two examples below?
知道他们如何在下面的两个示例中实现这一目标吗?
采纳答案by harrane
You can use Linkify(android.text.Spannable,java.util.regex.Pattern,java.lang.String)
您可以使用Linkify(android.text.Spannable、java.util.regex.Pattern、java.lang.String)
String termsAndConditions = getResources().getString(R.string.terms_and_conditions);
String privacyPolicy = getResources().getString(R.string.privacy_policy);
legalDescription.setText(
String.format(
getResources().getString(R.string.message),
termsAndConditions,
privacyPolicy)
);
legalDescription.setMovementMethod(LinkMovementMethod.getInstance());
Pattern termsAndConditionsMatcher = Pattern.compile(termsAndConditions);
Linkify.addLinks(legalDescription, termsAndConditionsMatcher, "terms:");
Pattern privacyPolicyMatcher = Pattern.compile(privacyPolicy);
Linkify.addLinks(legalDescription, privacyPolicyMatcher, "privacy:");
and then you can use the scheme to start an activity for example by adding the scheme in the AndroidManifest:
然后您可以使用该方案来启动一个活动,例如通过在AndroidManifest 中添加该方案:
<intent-filter>
<category android:name="android.intent.category.DEFAULT" />
<action android:name="android.intent.action.VIEW" />
<data android:scheme="terms" />
<data android:scheme="privacy" />
</intent-filter>
If you want to do a custom action, you can set the intent-filter to your current activity, which will have a singleTop launchmode.
如果您想执行自定义操作,您可以将意图过滤器设置为您当前的活动,该活动将具有 singleTop 启动模式。
This will cause onNewIntentto be fired where can make your custom actions:
这将导致onNewIntent在可以进行自定义操作的地方被触发:
@Override
protected void onNewIntent(final Intent intent) {
...
if (intent.getScheme().equals(..)) {
..
}
}
回答by Tushar Gogna
I think that I'm a little late to share this, but I have achieved the same using SpannableStringBuilder.
我想我分享这个有点晚了,但我使用SpannableStringBuilder实现了同样的目标。
Simply initialize the TextView
that you want to add 2 or more listeners and then pass that to the following method that I have created:
只需初始化TextView
要添加 2 个或更多侦听器的对象,然后将其传递给我创建的以下方法:
private void customTextView(TextView view) {
SpannableStringBuilder spanTxt = new SpannableStringBuilder(
"I agree to the ");
spanTxt.append("Term of services");
spanTxt.setSpan(new ClickableSpan() {
@Override
public void onClick(View widget) {
Toast.makeText(getApplicationContext(), "Terms of services Clicked",
Toast.LENGTH_SHORT).show();
}
}, spanTxt.length() - "Term of services".length(), spanTxt.length(), 0);
spanTxt.append(" and");
spanTxt.setSpan(new ForegroundColorSpan(Color.BLACK), 32, spanTxt.length(), 0);
spanTxt.append(" Privacy Policy");
spanTxt.setSpan(new ClickableSpan() {
@Override
public void onClick(View widget) {
Toast.makeText(getApplicationContext(), "Privacy Policy Clicked",
Toast.LENGTH_SHORT).show();
}
}, spanTxt.length() - " Privacy Policy".length(), spanTxt.length(), 0);
view.setMovementMethod(LinkMovementMethod.getInstance());
view.setText(spanTxt, BufferType.SPANNABLE);
}
And in your XML, use android:textColorLink
to add custom link color of your choice. Like this:
在您的 XML 中,用于android:textColorLink
添加您选择的自定义链接颜色。像这样:
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView"
android:textColorLink="#C36241" /> //#C36241 - Rust
And this looks like this:
这看起来像这样:
Hope it helps someone. :)
希望它可以帮助某人。:)
回答by Ahmad Baraka
Here's my solution:
这是我的解决方案:
First we need to have clickable links in our TextView:
首先,我们需要在 TextView 中有可点击的链接:
Here's my TextView in the xml layout, do not add any links handling parameters.
<TextView android:id="@+id/sign_up_privacy" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/terms_and_privacy"/>
In strings file, I added the resource text with html tags
<string name="terms_and_privacy">By signing up you agree to our <a href="terms:">Terms of Service</a> and <a href="privacy:">Privacy Policy.</a></string>
In onCreateView set LinkMovementMethod to the TextView
TextView privacyTextView = (TextView) root.findViewById(R.id.sign_up_privacy); privacyTextView.setMovementMethod(LinkMovementMethod.getInstance());
这是我在 xml 布局中的 TextView,不添加任何链接处理参数。
<TextView android:id="@+id/sign_up_privacy" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/terms_and_privacy"/>
在字符串文件中,我添加了带有 html 标签的资源文本
<string name="terms_and_privacy">By signing up you agree to our <a href="terms:">Terms of Service</a> and <a href="privacy:">Privacy Policy.</a></string>
在 onCreateView 中将 LinkMovementMethod 设置为 TextView
TextView privacyTextView = (TextView) root.findViewById(R.id.sign_up_privacy); privacyTextView.setMovementMethod(LinkMovementMethod.getInstance());
Now the TextView links are clickable.
现在 TextView 链接是可点击的。
Second, We need to Handle these clicks:
其次,我们需要处理这些点击:
In my Manifest file, I added intent-filter for "terms" and "privacy" and Single Instance Launch Mode
<activity android:name=".MyActivity" android:launchMode="singleInstance"> <intent-filter> <category android:name="android.intent.category.DEFAULT"/> <action android:name="android.intent.action.VIEW"/> <data android:scheme="terms"/> <data android:scheme="privacy"/> </intent-filter> </activity>
In MyActivity, override onNewIntent to catch privacy and terms intents
@Override protected void onNewIntent(Intent intent) { if (intent.getScheme().equalsIgnoreCase(getString("terms"))) { //handle terms clicked } else if (intent.getScheme().equalsIgnoreCase(getString("privacy"))) { //handle privacy clicked } else { super.onNewIntent(intent); } }
在我的清单文件中,我为“条款”和“隐私”以及单实例启动模式添加了意图过滤器
<activity android:name=".MyActivity" android:launchMode="singleInstance"> <intent-filter> <category android:name="android.intent.category.DEFAULT"/> <action android:name="android.intent.action.VIEW"/> <data android:scheme="terms"/> <data android:scheme="privacy"/> </intent-filter> </activity>
在 MyActivity 中,覆盖 onNewIntent 以捕获隐私和条款意图
@Override protected void onNewIntent(Intent intent) { if (intent.getScheme().equalsIgnoreCase(getString("terms"))) { //handle terms clicked } else if (intent.getScheme().equalsIgnoreCase(getString("privacy"))) { //handle privacy clicked } else { super.onNewIntent(intent); } }
回答by PH88
With Textoo, this can be achieved like:
使用Textoo,这可以像这样实现:
res/values/strings.xml:
res/values/strings.xml:
<resources>
<string name="str_terms_and_privacy">By signing up you agree to our <a href="terms:">Terms of Service</a> and <a href="privacy:">Privacy Policy.</a></string>
</resources>
res/layout/myActivity.xml:
res/layout/myActivity.xml:
<TextView
android:id="@+id/view_terms_and_privacy"
android:text="@string/str_terms_and_privacy"
/>
java/myPackage/MyActivity.java:
java/myPackage/MyActivity.java:
public class MyActivity extends Activity {
...
protected void onCreate(Bundle savedInstanceState) {
...
TextView termsAndPrivacy = Textoo
.config((TextView) findViewById(R.id.view_terms_and_privacy))
.addLinksHandler(new LinksHandler() {
@Override
public boolean onClick(View view, String url) {
if ("terms:".equals(url)) {
// Handle terms click
return true; // event handled
} else if ("privacy:".equals(url)) {
// Handle privacy click
return true; // event handled
} else {
return false; // event not handled. continue default processing i.e. launch web browser and display the link
}
}
})
.apply();
...
}
...
}
This approach have the advantages that:
这种方法具有以下优点:
- Keep text externalized as string resource. Make it easier to localize your app.
- Can handle the click event directly using
LinksHandler
and no need to define additional intent filter - Simpler and more readable code
- 将文本外部化为字符串资源。更轻松地本地化您的应用程序。
- 可以直接使用处理点击事件
LinksHandler
,无需定义额外的意图过滤器 - 更简单、更易读的代码
回答by techtinkerer
This is working for me :
这对我有用:
in xml :
在 xml 中:
<TextView
android:id="@+id/tv_by_continuing_str"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:textSize="15sp"
tools:text="Test msg 1 2, 3"
android:textColor="@color/translucent_less_white3"
android:textColorLink="@color/white"
android:gravity="center|bottom"
android:layout_above="@+id/btn_privacy_continue" />
In strings.xml
在strings.xml中
< string name="by_continuing_str2">< ! [ CDATA[By continuing to use this app, you agree to our <a href="https://go.test.com" style="color:gray"/> Privacy Statement </a> and <a href="https://go.test.com" style="color:gray"/>Services Agreement.]]>< / string>
in the activity :
在活动中:
TextView tv_by_continuing = (TextView) findViewById(R.id.tv_by_continuing);
tv_by_continuing.setText(Html.fromHtml(getString(R.string.by_continuing_str2)));
tv_by_continuing.setMovementMethod(LinkMovementMethod.getInstance());
回答by Salman khan
The best way to do this is with string file
最好的方法是使用字符串文件
In string.xml
在 string.xml 中
<string name="agree_to_terms">I agree to the %1$s and %2$s</string>
<string name="terms_of_service">Terms of Service</string>
<string name="privacy_policy">Privacy Policy</string>
In onCreateView call below method
在 onCreateView 调用下面的方法
private void setTermsAndCondition() {
String termsOfServicee = getString(R.string.terms_of_service);
String privacyPolicy = getString(R.string.privacy_policy);
String completeString = getString(R.string.agree_to_terms, termsOfServicee,privacyPolicy);
int startIndex = completeString.indexOf(termsOfServicee);
int endIndex = startIndex + termsOfServicee.length();
int startIndex2 = completeString.indexOf(privacyPolicy);
int endIndex2 = startIndex2 + privacyPolicy.length();
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(completeString);
ClickableSpan clickOnTerms = new ClickableSpan() {
@Override
public void onClick(View widget) {
Toast.makeText(this, "click on terms of service", Toast.LENGTH_SHORT).show();
}
@Override
public void updateDrawState(TextPaint ds) {
ds.setColor(ContextCompat.getColor(this, R.color.blue));
}
};
ClickableSpan clickOnPrivacy = new ClickableSpan() {
@Override
public void onClick(View widget) {
Toast.makeText(this, "click on privacy policy", Toast.LENGTH_SHORT).show();
}
@Override
public void updateDrawState(TextPaint ds) {
ds.setColor(ContextCompat.getColor(this, R.color.blue));
}
};
spannableStringBuilder.setSpan(clickOnTerms, startIndex, endIndex, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
spannableStringBuilder.setSpan(clickOnPrivacy, startIndex2, endIndex2, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
yourTextView.setText(spannableStringBuilder);
yourTextView.setMovementMethod(LinkMovementMethod.getInstance());
}
回答by Deutro
An easy fix for this would be to use multiple labels. One for each link and one for the text.
一个简单的解决方法是使用多个标签。每个链接一个,文本一个。
[TermsOfServiceLabel][andLabel][PrivacyPolicy]
Or is it necessary that you only use one label?
还是必须只使用一个标签?