String text = "Cámélan discovered ônte red aleŕt \n Como se extingue la deuda";
Si je donne l’entrée Ca, elle devrait être mise en évidence à partir de la chaîne donnée Cá mais elle ne le sera pas.
Ci-dessous est ce que j'ai essayé.
Pattern mPattern;
String filterTerm; //this is the input which I give from input filter. Say for eg: Ca
String regex = createFilterRegex(filterTerm);
mPattern = Pattern.compile(regex);
private String createFilterRegex(String filterTerm) {
filterTerm = Normalizer.normalize(filterTerm, Normalizer.Form.NFD);
filterTerm = filterTerm.replaceAll("[\\p{InCombiningDiacriticalMarks}]", "");
return filterTerm;
}
public Pattern getPattern() {
return mPattern;
}
Dans une autre classe,
private SpannableStringBuilder createHighlightedString(String nodeText, int highlightColor) { //nodeText is the entire list displaying.
SpannableStringBuilder returnValue = new SpannableStringBuilder(nodeText);
String lowercaseNodeText = nodeText;
Matcher matcher = mFilter.getPattern().matcher((createFilterRegex(lowercaseNodeText)));
while (matcher.find()) {
returnValue.setSpan(new ForegroundColorSpan(highlightColor), matcher.start(0),
matcher.end(0), Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
}
return returnValue;
}
viewHolder.mTextView.setText (createHighlightedString ((node.getText ()), mHighlightColor));
Mais ce que je reçois comme sortie,
Si je tape un alphabet seul ou seul, il est en surbrillance mais si je passe plus de deux alphabets, par exemple, par exemple: Ca, ce n'est pas en surbrillance ni en affichage. Je ne pouvais pas comprendre quelle erreur je faisais.
Mais si vous regardez WhatsApp. cela a été réalisé.
J'ai tapé Co, c'est reconnaître et mettre en évidence les caractères accentués dans la phrase.
Comme tu dis,
String text = "Cámélan a découvert la couleur rouge comme d'habitude";
Donc, chaque fois que vous donnez votre première entrée, recevez ce premier caractère et comparez.
Ex.: Si vous donnez Ca, alors
if (StringUtils.isNotEmpty(substring)) { //this is the search text
substring=substring.substring(0,1); //now you get C alone.
}
Donc, tout ce que vous tapez est affiché en filtrant le premier caractère. À présent
SpannableString builder = higlightString((yourContent.getText()), mHighlightColor);
viewHolder.mTextView.setText(builder);
private SpannableString higlightString(String entireContent, int highlightColor) {
SpannableString returnValue = new SpannableString(entireContent);
String lowercaseNodeText = entireContent;
try {
Matcher matcher = mFilter.getPattern().matcher(((diacritical(lowercaseNodeText.toLowerCase()))));
while (matcher.find()) {
returnValue.setSpan(new ForegroundColorSpan(highlightColor), matcher.start(0),
matcher.end(0), Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
}
}
catch (Exception e){
e.printStackTrace();
}
return returnValue;
}
private String diacritical(String original) {
String removed=null;
String decomposed = Normalizer.normalize(original, Normalizer.Form.NFD);
removed = decomposed.replaceAll("\\p{InCombiningDiacriticalMarks}+", "");
return removed;
}
Cas de test:
Lorsque vous donnez une entrée Ca, le texte entier est affiché en affichant tout le contenu C, toutes les données sont filtrées et filtré en normalisant le contenu;.
Vous avez déjà:
private String convertToBasicLatin(String text) {
return Normalizer.normalize(text, Normalizer.Form.NFD)
.replaceAll("\\p{M}", "").replaceAll("\\R", "\n");
}
Pour avoir un correspondance de caractère latine de base non accentuée one point de code Unicode d'une lettre accentuée, , Il convient de normaliser la forme en compose:
private String convertToComposedCodePoints(String text) {
return Normalizer.normalize(text, Normalizer.Form.NFC).replaceAll("\\R", "\n");
}
En général, on peut supposer que le point de code Unicode a aussi 1 caractère.
Maintenant, les positions d'index de l'adversaire de start
et end
sont correctes . J'ai normalisé explicitement les fins de ligne (regex \R
) comme \r\n
ou \u0085
en un seul \n
. varie: La lettre minuscule allemande ß
correspond à la lettre majuscule SS
.
String sought = ...;
String content = ...;
sought = convertToBasicLatin(sought);
String latinContent = convertToBasicLatin(content);
String composedContent = convertToComposedUnicode(content);
Matcher m = Pattern.compile(sought, Pattern.CASE_INSENSITIVE
| Pattern.UNICODE_CASE | Pattern.UNICODE_CHARACTER_CLASS
| Pattern.UNIX_LINES)
.matcher(latinContent);
while (m.find()) {
... // One can apply `m.start()` and `m.end()` to composedContent of the view too.
}
Je ne suis pas un programmeur Java, donc juste une solution de base de regex brute ici.
Si vous pouvez Normaliser la chaîne avec sa décomposition form
suppose que c'est ça
String sSourceTargetDecom = Normalizer.normalize(sourcetarget, Normalizer.Form.NFD);
,
cela devrait tourner quelque chose comme 0000C1 Á LATIN CAPITAL LETTER A WITH ACUTE
en deux caractères A
et 000301 ́ COMBINING ACUTE ACCENT
.
Vous pouvez obtenir la plupart des caractères de combinaison de blocs en utilisant
[\p{Block=Combining_Diacritical_Marks}\p{Block=Combining_Diacritical_Marks_Extended}\p{Block=Combining_Diacritical_Marks_For_Symbols}\p{Block=Combining_Diacritical_Marks_Supplement}\p{Block=Combining_Half_Marks}]
qui a une plage d'hex de
[\x{300}-\x{36f}\x{1ab0}-\x{1aff}\x{1dc0}-\x{1dff}\x{20d0}-\x{20ff}\x{fe20}-\x{fe2f}]
Il s’avère que la plupart des marques combinées relatives au latin de base peuvent être
sont décomposés dans la plage [\x{300}-\x{36f}]
.
Vous pouvez décomposer les deux la cible source et la chaîne de recherche en entrée.
Créez ensuite une expression rationnelle à partir de la chaîne de recherche d'entrée . Injectez [\x{300}-\x{36f}]?
après chaque lettre latine de base.
String regex = sSearch.replaceAll("([a-zA-Z])[\\x{300}-\\x{36f}]?", "\\1[\\x{300}-\\x{36f}]?");
(je ne sais pas ce que Java utilise pour la notation des points de code dans leurs expressions rationnelles, doit éventuellement être \u{DD}
Ensuite, utilisez l'expression régulière sur la chaîne sSourceTargetDecom , elle correspond au latin de base en tant qu'indépendant et/ou avec un code de combinaison facultatif.