diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 95e6f038..85b661cb 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -78,4 +78,5 @@ dependencies { implementation("io.github.iamr0s:Dhizuku-API:2.4") implementation("me.zhanghai.android.appiconloader:appiconloader:1.5.0") implementation("org.lsposed.hiddenapibypass:hiddenapibypass:4.3") + implementation("com.belerweb:pinyin4j:2.5.1") } \ No newline at end of file diff --git a/app/src/main/kotlin/com/aistra/hail/ui/apps/AppsAdapter.kt b/app/src/main/kotlin/com/aistra/hail/ui/apps/AppsAdapter.kt index abfb1389..a938ae52 100644 --- a/app/src/main/kotlin/com/aistra/hail/ui/apps/AppsAdapter.kt +++ b/app/src/main/kotlin/com/aistra/hail/ui/apps/AppsAdapter.kt @@ -18,6 +18,7 @@ import com.aistra.hail.app.HailData import com.aistra.hail.utils.AppIconCache import com.aistra.hail.utils.HPackages import com.aistra.hail.utils.NameComparator +import com.aistra.hail.utils.PinyinSearch import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job @@ -58,8 +59,10 @@ object AppsAdapter : && ((HailData.filterFrozenApps && AppManager.isAppFrozen(it.packageName)) || (HailData.filterUnfrozenApps && !AppManager.isAppFrozen(it.packageName))) - && (query.isNullOrEmpty() || it.packageName.contains(query, true) - || it.loadLabel(pm).toString().contains(query, true)) + && (query.isNullOrEmpty() + || it.packageName.contains(query, true) + || it.loadLabel(pm).toString().contains(query, true) + || PinyinSearch.searchPinyinAll(it.loadLabel(pm).toString(), query)) }.run { when (HailData.sortBy) { HailData.SORT_INSTALL -> sortedBy { diff --git a/app/src/main/kotlin/com/aistra/hail/ui/home/PagerFragment.kt b/app/src/main/kotlin/com/aistra/hail/ui/home/PagerFragment.kt index 707263e6..c0a1d939 100644 --- a/app/src/main/kotlin/com/aistra/hail/ui/home/PagerFragment.kt +++ b/app/src/main/kotlin/com/aistra/hail/ui/home/PagerFragment.kt @@ -31,6 +31,7 @@ import com.aistra.hail.utils.HPackages import com.aistra.hail.utils.HShortcuts import com.aistra.hail.utils.HUI import com.aistra.hail.utils.NameComparator +import com.aistra.hail.utils.PinyinSearch import com.aistra.hail.work.HWork import com.google.android.material.color.MaterialColors import com.google.android.material.dialog.MaterialAlertDialogBuilder @@ -115,7 +116,9 @@ class PagerFragment : MainFragment(), PagerAdapter.OnItemClickListener, private fun updateCurrentList() = HailData.checkedList.filter { if (query.isEmpty()) it.tagId == tag.second - else it.packageName.contains(query, true) || it.name.contains(query, true) + else (it.packageName.contains(query, true) + || it.name.contains(query, true) + || PinyinSearch.searchPinyinAll(it.name.toString(), query)) }.sortedWith(NameComparator).let { binding.empty.isVisible = it.isEmpty() pagerAdapter.submitList(it) diff --git a/app/src/main/kotlin/com/aistra/hail/utils/PinyinSearch.kt b/app/src/main/kotlin/com/aistra/hail/utils/PinyinSearch.kt new file mode 100644 index 00000000..ccfc6c65 --- /dev/null +++ b/app/src/main/kotlin/com/aistra/hail/utils/PinyinSearch.kt @@ -0,0 +1,144 @@ +package com.aistra.hail.utils + +import net.sourceforge.pinyin4j.PinyinHelper +import java.util.Locale + + +/**中文拼音搜索类*/ +object PinyinSearch { + /** + * 分别使用首字母和全拼进行匹配,满足条件之一就返回true, + * 如果当前语言不是中文就直接返回false + * @param textToSearch 需要匹配的字符串 + * @param textInput 用户输入 + * */ + fun searchPinyinAll(textToSearch: String?, textInput: String): Boolean { + if (textToSearch==null){ + return false + } + val language = Locale.getDefault().language + return if (language.equals(Locale.CHINESE.language)) { + searchCap(textToSearch, textInput) || searchAllSpell(textToSearch, textInput) + } else { + false + } + } + + /** + * 根据首字母进行搜索 + * 比如搜索”计算器“ 只需要输入 ”jsq“ + * */ + fun searchCap(appName: String, pinyinCap: String): Boolean { + if (pinyinCap.length < 80) { + for (index in getNameStringList(appName)) { + if (index.contains(pinyinCap, true)) { + return true + } + } + return false + } else { + return false + } + } + + /** + * 根据全部拼音进行搜索 + * 比如搜索 计算器 只需要输入 "jisuanqi" + * */ + fun searchAllSpell(appName: String, pinyinAll: String): Boolean { + if (pinyinAll.length < 30) { + for (index in getNameStringPinyinAll(appName)) { + if (index.contains(pinyinAll, true)) { + return true + } + } + return false + } else { + return false + } + } + + fun getNameStringPinyinAll(target: String): ArrayList { + val res = ArrayList() + getNameCapListPinyinAll(Array(target.length) { "" }, 0, target, res) + return res + } + + fun getNameStringList(target: String): ArrayList { + val res = ArrayList() + getNameCapList(CharArray(target.length), 0, target, res) + return res + } + + fun getNameCapList( + capList: CharArray, currentIndex: Int, target: String, result: ArrayList + ) { + if (currentIndex == target.length - 1) { + val arrayOrNull = PinyinHelper.toHanyuPinyinStringArray(target[currentIndex]) + if (arrayOrNull == null) { + capList[currentIndex] = target[currentIndex] + result.add(String(capList)) + } else { + val arrayOrNullCharArray = arrayOrNull.map { e -> e[0] }.distinct().toCharArray() + for (item in arrayOrNullCharArray) { + capList[currentIndex] = item + result.add(String(capList)) + } + } + + } else { + val arrayOrNull = PinyinHelper.toHanyuPinyinStringArray(target[currentIndex]) + if (arrayOrNull == null) { + val arr = capList.copyOf() + arr[currentIndex] = target[currentIndex] + val newIndex = currentIndex + 1 + getNameCapList(arr, newIndex, target, result) + } else { + val arrayOrNullCharArray = arrayOrNull.map { e -> e[0] }.distinct().toCharArray() + for (item in arrayOrNullCharArray) { + val arr = capList.copyOf() + arr[currentIndex] = item + val newIndex = currentIndex + 1 + getNameCapList(arr, newIndex, target, result) + } + } + + } + } + + fun getNameCapListPinyinAll( + fullList: Array, currentIndex: Int, target: String, result: ArrayList + ) { + if (currentIndex == target.length - 1) { + val arrayOrNull = PinyinHelper.toHanyuPinyinStringArray(target[currentIndex]) + if (arrayOrNull == null) { + fullList[currentIndex] = target[currentIndex].toString() + result.add(fullList.joinToString("")) + } else { + val arrayDis = arrayOrNull.map { e -> e.substring(0, e.length - 1) }.distinct() + for (item in arrayDis) { + fullList[currentIndex] = item + result.add(fullList.joinToString("")) + } + } + + } else { + val arrayOrNull = PinyinHelper.toHanyuPinyinStringArray(target[currentIndex]) + if (arrayOrNull == null) { + val arr = fullList.copyOf() + arr[currentIndex] = target[currentIndex].toString() + val newIndex = currentIndex + 1 + getNameCapListPinyinAll(arr, newIndex, target, result) + } else { + val arrayDis = arrayOrNull.map { e -> e.substring(0, e.length - 1) }.distinct() + for (item in arrayDis) { + val arr = fullList.copyOf() + arr[currentIndex] = item + val newIndex = currentIndex + 1 + getNameCapListPinyinAll(arr, newIndex, target, result) + } + } + + } + } +} \ No newline at end of file