如何为非标准文本输入实现自定义自动填充字典?

时间:2018-04-01 16:53:29

标签: android multilingual

我正在将a larger GTK/Python program的部分内容重写为Android。在其中一个编辑文本中,我的用户将输入一个植物分类名称,其中包括 Pachypharynx Erythroxylaceae 等字样。

这些词是“植物词典”的一部分,而说不同语言的人会以不同的方式发音,并且在输入时会产生不同的输入错误。有些人具有准同音异义词,如/ Hieronima / Hyeronima / Hieronyma / group,其中前两个被归类为大戟科,后者被归类为Phyllanthaceae。有些是有效的名称,但有更好的选择(例如:Coccus被认为是Cocos的同义词)

那么编程问题在哪儿?好吧,我想帮助用户!

  • 我需要TextView
  • 在此TextView中,我需要帮助用户输入名称
  • 我不能用植物名称弄脏用户的字典
  • 允许输入错误,但更喜欢文字匹配,
  • 提供上下文信息(姓氏),
  • 帮助用户更喜欢接受的绰号。

我考虑过并放弃了以下内容:

  • 定义您自己的输入法,(矫枉过正)
  • 更改用户词典,(不可接受)

我想

  • 使用AutoCompleteTextView(但如何?)

我认为这个问题值得一提(我不知道为什么你们这些人/女士在没有解释的情况下投票)并且我认为我找到和建立的答案会帮助其他人。

1 个答案:

答案 0 :(得分:1)

这个答案建立在其他人的基础之上,但最重要的是Carl Anderson's。它基于AutoCompleteTextView选项,我将在解决方案的每个元素上逐一查看。

首先,在创建视图时,让我们抓住ACTV并将其与自定义适配器关联:

public View onCreateView([...]) {
 .
 .
    TaxonomyDatabase db = new TaxonomyDatabase(getContext());
    List<Epithet> allEpithets = db.getAllGenera();
    EpithetAdapter hints = new EpithetAdapter(getContext(),
            android.R.layout.select_dialog_item, allEpithets);
    AutoCompleteTextView widget = rootView.findViewById(R.id.etCollectSpecies);
    widget.setThreshold(2); // start hinting from second character
    widget.setAdapter(hints);

TaxonomyDatabase.getAllGenera从数据库中获取所有属,包括它们所接受的等价物,以及它们所属的家族。

List<Epithet> getAllGenera() {
    ArrayList<Epithet> r = new ArrayList<>();
    SQLiteDatabase db = getReadableDatabase();
    Cursor cr = db.rawQuery(
            "select o.epithet, a.epithet, o.phonetic, a.family_name " +
                    "from taxon o "+"" +
                    "left join taxon a on o.accepted_id = a.id " +
                    "where o.rank = 5 " +
                    "order by o.epithet",
            new String[]{});
     .
     .

现在,EpithetAdapter构造函数接受此列表,首先将其添加到其内部候选列表中,然后再次在列表中再次复制每个Epithet:第一个实例用于文字匹配,第二个实例用于允许语音匹配。其中的逻辑隐藏在Epithet复制构造函数中,它将isExact字段设置为false

EpithetAdapter(Context context, int textViewResourceId, List<Epithet> epithets) {
    super(context, textViewResourceId, epithets);
    // copy all the epithets twice
    mEpithets = new ArrayList<>(epithets.size() * 2);
    // first to be used as exact matches (String×4 constructor)
    mEpithets.addAll(epithets);
    // then again to be used as phonetic matches (copy constructor)
    for(Epithet e : epithets) {
        mEpithets.add(new Epithet(e));
    }
}

Epithet类有一个toString方法,用于处理Epithet在ACTV下拉列表中的显示方式:

public String toString() {
    if (accepted != null) {
        return epithet + " → " + accepted;
    } else {
        return epithet + " (" + family + ")";
    }
}

EpithetAdapter中的过滤器执行剩下的任务:当用户点击建议时,会调用ConvertResultToString

    public String convertResultToString(Object resultValue) {
        return ((Epithet)resultValue).epithet;
    }

过滤自身,即performFiltering方法,只是迄今为止所有人所说的逻辑结果:

    protected FilterResults performFiltering(CharSequence constraint) {
        FilterResults results = new FilterResults();
        if (constraint != null) {
            String exact = constraint.toString();
            String phonetic = TaxonomyDatabase.phonetic(exact);
            exact = exact.substring(0, 1).toUpperCase() + exact.substring(1).toLowerCase();
            ArrayList<Epithet> suggestions = new ArrayList<>();
            for (Epithet epithet : mEpithets) {
                if (epithet.isExact) {
                    if (epithet.epithet.startsWith(exact)) {
                        suggestions.add(epithet);
                    }
                } else {
                    if (epithet.phonetic.startsWith(phonetic) &&
                            !epithet.epithet.startsWith(exact)) {
                        suggestions.add(epithet);
                    }
                }
            }
            results.values = suggestions;
            results.count = suggestions.size();
        }
        return results;
    }
  • 最后一个小细节,禁用文本建议(布局中为android:inputType="textNoSuggestions"),以免污染用户词典。

当用户输入coccus时,软件建议:

enter image description here

当用户输入»galanth«时,文字匹配首先出现:

enter image description here

当用户输入»calanth«时,再次出现字面匹配:

enter image description here

您在下拉列表中看到的是Epithet.toString。单击提示仅复制Epithet.epithet