J'ai un simple TextView
avec le numéro de téléphone local 852112222 ou (8 5) 211 2222.
J'ai besoin que ce soit cliquable, alors naturellement j'ai utilisé Android:autoLink="all"
.
Mais pour une raison quelconque, je ne comprends pas que le même numéro de téléphone ne soit pas "lié" sur tous les appareils.
Sur l’appareil Genymotion, cela ne fonctionnait pas. Sur mon appareil OnePlus2 personnel, cela a fonctionné… .. Testé sur de nombreux appareils, sans succès.
Quel pourrait être le problème?
Préférences de compte d'utilisateur? Version Android? ORM? Autre chose?
Voici mon enquête.
J'ai créé un nouveau projet et ajouté Android:autoLink="all"
à une vue de texte dans activity_main.xml
. Grâce aux développeurs d'Android Studio, j'ai pu voir l'aperçu et j'ai trouvé quelque chose d'intéressant:
12345
non lié123456
non lié1234567
lié12345678
lié123456789
non lié1234567890
ne ressemble pas12345678901
lié123456789012
non liéLe résultat est le même sur mon téléphone. Alors j'ai regardé dans le code source, cherché le mot clé autolink, puis j'ai trouvé ceci:
private void setText(CharSequence text, BufferType type,
boolean notifyBefore, int oldlen) {
...
// unconcerned code above
if (mAutoLinkMask != 0) {
Spannable s2;
if (type == BufferType.EDITABLE || text instanceof Spannable) {
s2 = (Spannable) text;
} else {
s2 = mSpannableFactory.newSpannable(text);
}
if (Linkify.addLinks(s2, mAutoLinkMask)) {
text = s2;
type = (type == BufferType.EDITABLE) ? BufferType.EDITABLE : BufferType.SPANNABLE;
/*
* We must go ahead and set the text before changing the
* movement method, because setMovementMethod() may call
* setText() again to try to upgrade the buffer type.
*/
mText = text;
// Do not change the movement method for text that support text selection as it
// would prevent an arbitrary cursor displacement.
if (mLinksClickable && !textCanBeSelected()) {
setMovementMethod(LinkMovementMethod.getInstance());
}
}
}
...
// unconcerned code above
}
Donc, le mot clé est Linkify
maintenant. Pour addLinks
:
public static final boolean addLinks(@NonNull Spannable text, @LinkifyMask int mask) {
...
if ((mask & PHONE_NUMBERS) != 0) {
gatherTelLinks(links, text);
}
...
}
private static final void gatherTelLinks(ArrayList<LinkSpec> links, Spannable s) {
PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
Iterable<PhoneNumberMatch> matches = phoneUtil.findNumbers(s.toString(),
Locale.getDefault().getCountry(), Leniency.POSSIBLE, Long.MAX_VALUE);
for (PhoneNumberMatch match : matches) {
LinkSpec spec = new LinkSpec();
spec.url = "tel:" + PhoneNumberUtils.normalizeNumber(match.rawString());
spec.start = match.start();
spec.end = match.end();
links.add(spec);
}
}
Ensuite, quelque chose de grave est arrivé, le SDK n'a pas PhoneNumberUtil
, plus précisément ces 3 classes ci-dessous:
import com.Android.i18n.phonenumbers.PhoneNumberMatch;
import com.Android.i18n.phonenumbers.PhoneNumberUtil;
import com.Android.i18n.phonenumbers.PhoneNumberUtil.Leniency;
Pour le moment, la première raison est apparue: Locale.getDefault().getCountry()
.
Je suis donc allé à la configuration, trouvé la langue, sélectionné le chinois. Le résultat est ci-dessous:
12345
lié123456
lié1234567
lié12345678
lié123456789
lié1234567890
lié12345678901
lié123456789012
liéDeuxièmement, pour le paquetage de com.Android.i18n.phonenumbers
, j'ai trouvé ceci:
https://Android.googlesource.com/platform/external/libphonenumber/+/ics-factoryrom-2-release/Java/src/com/Android/i18n/phonenumbers
Si vous êtes intéressé, vérifiez le lien ci-dessus. Remarquez dans l'URL: ics-factoryrom-2-release
. Je doute donc fortement que cela dépende de plate-forme.
Pour la solution, CleverAndroid a raison, prendre le contrôle intégral de LinkMovementMethod
est une bonne option.
Il suffit de faire ce qui suit
TextView userInput= (TextView) view.findViewById(R.id.textView);
if(userInput != null){
Linkify.addLinks(userInput, Patterns.PHONE,"tel:",Linkify.sPhoneNumberMatchFilter,Linkify.sPhoneNumberTransformFilter);
userInput.setMovementMethod(LinkMovementMethod.getInstance());
}
et aussi retirer le
Android:autoLink
depuis votre fichier xml
Pouvez-vous s'il vous plaît essayer ci-dessous le code. Définir l'attribut par programme.
Activité
package custom.com.Android_lab;
import Android.app.Activity;
import Android.os.Bundle;
import Android.text.util.Linkify;
import Android.widget.TextView;
/**
* You can use Activity or AppCompatActivity
*/
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// local phone number 852112222 or (8 5) 211 2222.
// Tested OK!
TextView textView1 = (TextView) findViewById(R.id.textv1);
textView1.setAutoLinkMask(Linkify.PHONE_NUMBERS);
textView1.setText("852112222");
// Tested OK!
TextView textView2 = (TextView) findViewById(R.id.textv2);
textView2.setAutoLinkMask(Linkify.PHONE_NUMBERS);
textView2.setText("(85) 211-2222");
// Tested Failed!
// Reason : Need to apply setAutoLinkMask prior to apply setText
TextView textView3 = (TextView) findViewById(R.id.textv3);
textView3.setText("852112222");
textView2.setAutoLinkMask(Linkify.PHONE_NUMBERS);
}
}
Vue
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:id="@+id/activity_main"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:orientation="vertical">
<TextView
Android:id="@+id/textv1"
Android:layout_width="match_parent"
Android:layout_height="wrap_content" />
<TextView
Android:id="@+id/textv2"
Android:layout_width="match_parent"
Android:layout_height="wrap_content" />
<TextView
Android:id="@+id/textv3"
Android:layout_width="match_parent"
Android:layout_height="55dp" />
</LinearLayout>
Appareils de test
Je vous suggère juste pour ajouter le code pays et tout votre problème sera résolu,
Android:autoLink="phone"
Android:text="+91-8000000000"
Si nous ajoutons le code pays avant le numéro, aucune autre solution temporaire n’est alors nécessaire.
J'ai constaté de nombreuses incohérences lors de l'utilisation de la liaison automatique. Si vous travaillez du tout pour une version prod. Choisissez toujours SpannableStringBuilder avec LinkMovementMethod. Vous avez un bon contrôle sur la manière dont le texte doit être affiché.
L'extrait ci-dessous peut aider.
String phone = "your phone number";
String message = "Phone number is: ";
Spannable span = new SpannableString(String.format("%s\n%s",message, phone));
ForegroundColorSpan color = new ForegroundColorSpan(Res.color(R.color.blue));
ClickableSpan click = new ClickableSpan() {
@Override
public void onClick(View widget) {
Navigator.dialer("your phone number");
}
public void updateDrawState(TextPaint ds) {// override updateDrawState
ds.setUnderlineText(false); // set to false to remove underline
}
};
span.setSpan(color, message.length(), message.length() + phone.length() + 1, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
span.setSpan(click, message.length(), message.length() + phone.length() + 1, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
changesMessageLabel.setText(span);
changesMessageLabel.setMovementMethod(LinkMovementMethod.getInstance());
Harsh Agrawal answer a fonctionné pour moi dans les cas où le numéro de téléphone est de 11 chiffres ou plus avec 3 blocs. par exemple. 123 456 78910
TextView textView = findViewById(R.id.text_view);
textView.setText("123 456 78910");
Linkify.addLinks(textView, Patterns.PHONE, "tel:", Linkify.sPhoneNumberMatchFilter,
Linkify.sPhoneNumberTransformFilter);
J'ai dû appeler Linkify.addLinks
après avoir configuré le texte pour que cela fonctionne.
Notez que Linkify.addLinks
appelle déjà setMovementMethod
dans la vue texte.
Pour les liaisons téléphoniques spécifiques, vous devez utiliser
Android:autoLink="phone"
Pour plus, consultez: textview autolink