亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何允許在 Android 中使用字符重音進行搜索?

如何允許在 Android 中使用字符重音進行搜索?

翻翻過去那場雪 2023-12-30 15:56:26
我在我的應用程序中實現了一個搜索機制,這樣當我搜索姓名或電子郵件時,它會顯示具有匹配字符的字符串。但是,我的列表中有一些帶重音的字符串,當我使用與該特定重音相關的常規字符進行搜索時,假設我有字符串“àngela”并且我搜索“angela”,它不會顯示該字符串,除非我使用確切的字符串“進行搜索”安吉拉”。我試圖讓它工作,無論重音與否,假設我輸入“à”,它應該顯示包含“à”和“a”的所有字符串,反之亦然。知道該怎么做嗎?我在網上查找了一堆文章,例如:How toignoreaccent in SQLite query (Android) ",也嘗試了規范化器,但它部分有效,如果我搜索“a”,它確實也會顯示帶有常規字母的重音字母,但是如果我用帶重音的字母搜索,它不會顯示任何內容。這是我的過濾器代碼:@Override    public Filter getFilter() {        return new Filter() {            @Override            protected FilterResults performFiltering(CharSequence charSequence) {                String charString = charSequence.toString();                if (charString.isEmpty()) {                    mSearchGuestListResponseListFiltered = mSearchGuestListResponseList;                } else {                    List<RegisterGuestList.Guest> filteredList = new ArrayList<>();                    for (RegisterGuestList.Guest row : mSearchGuestListResponseList) {                        // name match condition. this might differ depending on your requirement                        // here we are looking for name or phone number match                        String firstName = row.getGuestFirstName().toLowerCase();                        String lastName = row.getGuestLastName().toLowerCase();                        String name = firstName + " " +lastName;                        String email = row.getGuestEmail().toLowerCase();                        if ( name.trim().contains(charString.toLowerCase().trim()) ||                                email.trim().contains(charString.toLowerCase().trim())){                            filteredList.add(row);                            searchText = charString.toLowerCase();                        }                    }        };    }如果有人感興趣,這里是整個適配器類:https://pastebin.com/VxsWWMiS 這是相應的活動視圖:如有必要,很樂意分享任何細節。另外,我在搜索時隨機得到了indexoutofboundexception onBind()方法(使用recyclerview作為列表):java.lang.IndexOutOfBoundsException: Index: 7, Size: 0        at java.util.ArrayList.get(ArrayList.java:437)知道該怎么做嗎?
查看完整描述

1 回答

?
慕少森

TA貢獻2019條經驗 獲得超9個贊

一般來說,我建議使用Collator強度設置為 的Collator.PRIMARY來比較包含重音符號和不同大小寫的字符串(例如,Nvsn和évs e)。不幸的是,Collator沒有contains()功能。


所以我們將自己制作。


private static boolean contains(String source, String target) {

    if (target.length() > source.length()) {

        return false;

    }


    Collator collator = Collator.getInstance();

    collator.setStrength(Collator.PRIMARY);


    int end = source.length() - target.length() + 1;


    for (int i = 0; i < end; i++) {

        String sourceSubstring = source.substring(i, i + target.length());


        if (collator.compare(sourceSubstring, target) == 0) {

            return true;

        }

    }


    return false;

}

這會迭代源字符串,并檢查與搜索目標長度相同的每個子字符串是否等于搜索目標(就 Collator 而言)。


例如,假設我們的源字符串是,"This is a Tèst"并且我們正在搜索單詞"test"。此方法將迭代每個四個字母的子字符串:


This

his 

is i

s is

 is 

is a

s a 

 a T

a Tè

 Tès

Tèst

一旦找到匹配項就會返回 true。由于強度設置為Collator.PRIMARY,整理器認為"Tèst"和"test"相等,因此我們的方法返回true。


此方法很可能需要進行更多優化,但這應該是一個合理的起點。


編輯RuleBasedCollator:一種可能的優化是利用排序規則鍵以及and的已知實現細節RuleBasedCollationKey(假設您的項目中有 Google 的 Guava):


private static boolean containsBytes(String source, String target) {

    Collator collator = Collator.getInstance();

    collator.setStrength(Collator.PRIMARY);


    byte[] sourceBytes = dropLastFour(collator.getCollationKey(source).toByteArray());

    byte[] targetBytes = dropLastFour(collator.getCollationKey(target).toByteArray());


    return Bytes.indexOf(sourceBytes, targetBytes) >= 0;

}


private static byte[] dropLastFour(byte[] in) {

    return Arrays.copyOf(in, in.length - 4);

}

這是相當脆弱的(可能不適用于所有語言環境),但在我的測試中,它的速度快了 2 倍到 10 倍。


編輯:要支持突出顯示,您應該轉換contains()為indexOf(),然后使用該信息:


private static int indexOf(String source, String target) {

    if (target.length() > source.length()) {

        return -1;

    }


    Collator collator = Collator.getInstance();

    collator.setStrength(Collator.PRIMARY);


    int end = source.length() - target.length() + 1;


    for (int i = 0; i < end; i++) {

        String sourceSubstring = source.substring(i, i + target.length());


        if (collator.compare(sourceSubstring, target) == 0) {

            return i;

        }

    }


    return -1;

}

然后你可以像這樣應用它:


String guestWholeName = guest.getGuestFirstName() + " " + guest.getGuestLastName();

int wholeNameIndex = indexOf(guestWholeName, searchText);


if (wholeNameIndex > -1) {

    Timber.d("guest name first : guest.getGuestFirstName() %s", guest.getGuestFirstName());

    Timber.d("guest name last : guest.getGuestLastName() %s", guest.getGuestLastName());


    int endPos = wholeNameIndex + searchText.length();


    Spannable spannable = new SpannableString(guestWholeName);

    Typeface firstNameFont = Typeface.createFromAsset(context.getAssets(), "fonts/Graphik-Semibold.otf");

    spannable.setSpan(new CustomTypefaceSpan("", firstNameFont), wholeNameIndex, endPos, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

    Objects.requireNonNull(guestName).setText(spannable);

} else {

    Objects.requireNonNull(guestName).setText(guestWholeName);

}


查看完整回答
反對 回復 2023-12-30
  • 1 回答
  • 0 關注
  • 145 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號