web-dev-qa-db-fra.com

Plusieurs liens cliquables dans TextView sur Android

J'essaie d'ajouter plusieurs liens dans une vue en texte similaire à ce que Google et Flipboard ont fait ci-dessous avec leur Conditions générales AND Règles de confidentialité affiché dans la capture d'écran ci-dessous:

Jusqu'à présent, je suis tombé sur l'utilisation de cette approche

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

où myHtml est un href.

Mais cela ne me donne pas le contrôle, il me faut par exemple lancer un fragment, etc.

Avez-vous une idée de la façon dont ils y parviennent dans les deux exemples ci-dessous?

Flipboard terms and conditions view

Google terms and conditions view

13
AndroidEnthusiast

Vous pouvez utiliser 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:");

et vous pouvez ensuite utiliser le schéma pour démarrer une activité, par exemple, en l'ajoutant dans le 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>

Si vous souhaitez effectuer une action personnalisée, vous pouvez définir le filtre d'intention sur votre activité actuelle, qui aura un mode de lancement singleTop.

Cela entraînera onNewIntent à être renvoyé où peut effectuer vos actions personnalisées:

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

Je pense que je suis un peu en retard pour partager cela, mais j’ai obtenu le même résultat avec SpannableStringBuilder .

Initialisez simplement la TextView à laquelle vous voulez ajouter 2 écouteurs ou plus, puis transmettez-la à la méthode suivante que j'ai créée:

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

Et dans votre XML, utilisez Android:textColorLink pour ajouter la couleur de lien personnalisée de votre choix. Comme ça:

   <TextView
     Android:id="@+id/textView1"
     Android:layout_width="wrap_content"
     Android:layout_height="wrap_content"
     Android:text="TextView"
     Android:textColorLink="#C36241" />  //#C36241 - Rust

Et cela ressemble à ceci:

enter image description here

J'espère que ça aide quelqu'un. :)

69
Tushar Gogna

Voici ma solution:

Nous devons d’abord avoir des liens cliquables dans notre TextView:

  1. Voici ma TextView dans la mise en page XML, ne pas ajouter de liens manipulant des paramètres .

    <TextView
            Android:id="@+id/sign_up_privacy"
            Android:layout_width="wrap_content"
            Android:layout_height="wrap_content"
            Android:text="@string/terms_and_privacy"/>
    
  2. Dans le fichier de chaînes, j'ai ajouté le texte de la ressource avec les balises 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>
    
  3. Dans onCreateView, définissez LinkMovementMethod sur TextView

    TextView privacyTextView = (TextView) root.findViewById(R.id.sign_up_privacy);
    privacyTextView.setMovementMethod(LinkMovementMethod.getInstance());
    

Maintenant, les liens TextView sont cliquables.

Deuxièmement, nous devons gérer ces clics:

  1. Dans mon fichier Manifest, j'ai ajouté un filtre d'intention pour les "termes" et "confidentialité" Et le mode de lancement d'instance unique.

    <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>
    
  2. Dans MyActivity, remplacez onNewIntent pour saisir les intentions de confidentialité et les termes .

    @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);
            }
        }
    
3
Ahmad Baraka

Cela fonctionne pour moi :

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

Dans 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>

dans l'activité:

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

Une solution simple consiste à utiliser plusieurs étiquettes. Un pour chaque lien et un pour le texte.

[TermsOfServiceLabel][andLabel][PrivacyPolicy]

Ou est-il nécessaire que vous n'utilisiez qu'une seule étiquette?

0
Deutro

Avec Textoo , cela peut être réalisé comme suit:

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:

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

Cette approche présente les avantages suivants:

  • Conserver le texte externalisé en tant que ressource de chaîne. Facilitez la localisation de votre application.
  • Peut gérer l'événement click directement à l'aide de LinksHandler et il n'est pas nécessaire de définir un filtre d'intention supplémentaire
  • Code plus simple et plus lisible
0
PH88