Несколько Clickable ссылок в TextView на Android

Я пытаюсь добавить несколько ссылок в текстовом виде, аналогичном тому, что сделал Google и Flipboard ниже со своими Условиями и условиями И Политика конфиденциальности, показанная на снимке экрана ниже:

До сих пор я наткнулся на использование этого подхода

textView.setText(Html.fromHtml(myHtml);  textView.setMovementMethod(LinkMovementMethod.getInstance());

где myHtml является href.

Но это не дает мне контроля. Мне нужно, например, запустить фрагмент и т.д.

Любая идея, как они достигают этого в двух примерах ниже?

Flipboard terms and conditions view

Google terms and conditions view

Ответ 1

Вы можете использовать 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:");

а затем вы можете использовать схему для запуска действия, например, добавив эту схему в 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>

Если вы хотите выполнить настраиваемое действие, вы можете установить фильтр намерений на свою текущую активность, которая будет иметь одномоментный запуск.

Это приведет к срабатыванию onNewIntent, где вы можете выполнить свои собственные действия:

@Override
protected void onNewIntent(final Intent intent) {
 ...
  if (intent.getScheme().equals(..)) {
    ..
  }
}

Ответ 2

Я думаю, что немного опоздал, чтобы поделиться этим, но я добился того же, используя SpannableStringBuilder.

Просто инициализируйте 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);
    } 

В вашем 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

И это выглядит так:

enter image description here

Надеюсь, это поможет кому-то.:)

Ответ 3

Здесь мое решение:

Сначала нам нужно иметь интерактивные ссылки в нашем TextView:

  • Здесь мой TextView в макете xml, не добавляйте обработку ссылок Параметры.

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

Теперь ссылки TextView можно щелкнуть.

Во-вторых, нам нужно обработать эти клики:

  • В моем файле манифеста я добавил фильтр намерений для "условий" и "конфиденциальности", и режим запуска одного экземпляра

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

Ответ 4

Это работает для меня:

в 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" />

В файле 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>

в действии:

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

Ответ 5

Легким решением для этого было бы использование нескольких меток. Один для каждой ссылки и один для текста.

[TermsOfServiceLabel][andLabel][PrivacyPolicy]

Или необходимо, чтобы вы использовали только одну метку?

Ответ 6

С Textoo это может быть достигнуто, например:

RES/значения/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>

Рез/макет/myActivity.xml:

<TextView
    android:id="@+id/view_terms_and_privacy"
    android:text="@string/str_terms_and_privacy"
    />

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

Этот подход имеет следующие преимущества:

  • Сохранять текст в виде строкового ресурса. Упростите локализацию своего приложения.
  • Может обрабатывать событие click напрямую с помощью LinksHandler и не нужно определять дополнительный фильтр намерения
  • Упрощенный и читаемый код