更改MultiAutoCompleteTextView适配器中间短语

时间:2018-01-12 01:28:40

标签: c# android xamarin autocompletetextview

当用户在我的MultiAutoCompleteTextView中输入内容时,我会在每个空格后重新检查可用短语列表。我的一些建议值包含空格,我希望用户能够键入空格并使建议值继续仅列出以输入单词开头的字符串,只要我的ITokenizer&#39 ; s FindTokenStart函数返回表示空格前单词开头的位置。这实际上适用于在键入空格时我不会将Adapter更改为其他值的情况。但如果在输入空格时发生变化,则会出现问题。

例如,我有短语" Lunch Token"在我的建议值列表中,当我开始输入它时,一切看起来都很好:

enter image description here

在#34; Lunch"这个词的结尾处继续看起来很好。然后我添加了一个空格,我有一些逻辑检测到,因为已经输入了完整的单词午餐,一些选项不再有效。因此,它将MultiAutoCompleteTextView的Adapter属性切换到其中包含较少单词的其他适配器。但是在弹出列表时执行此操作似乎会导致列表中包含所有可能的值:

enter image description here

我在FindTokenStart函数中添加了代码以验证是否正在返回正确的值,而且它是。所以它必须与弹出列表时更改适配器有关。如何解决此问题并强制列表继续仅显示匹配的条款?我尝试仅在新列表而不是之前列表的子集时更新适配器,但这会导致其他问题(我现在无法记住它们)。

更改Adapter属性的最高级代码:

private void Command_AfterTextChanged(object sender, Android.Text.AfterTextChangedEventArgs e)
{
   try
   {
      if (!(command.Text.EndsWith(" ") || command.Text.Length == 0))
         return;

      var words = new SuggestionCache.WordList();
      if (command.Text.Length > 0)
         words.AddFromParserStates(parser.ParsePartial(command.Text, currentStory));
      else
         words.AddFromSyntaxes(Syntax.currentSyntaxes);
      command.Adapter = suggestions.GetArrayAdapter(words);
   }
   catch (Exception ex)
   {
      ShowMessage(ex.Message);
   }
}

FindTokenStart实现:

public int FindTokenStart(ICharSequence text, int cursor)
{
   System.Diagnostics.Debug.Write("FindTokenStart: ");
   if ((currentWordList == null) || (currentWordList.tokenBounds.Count == 0))
   {
      System.Diagnostics.Debug.WriteLine("A 0");
      return 0;
   }
   int idx = currentWordList.tokenBounds.BinarySearch(new Syntax.SyntaxMatch() { startPos = cursor }, SyntaxMatchComparer.EndComparer);
   if (idx >= 0)
   {
      System.Diagnostics.Debug.WriteLine("B {0}", currentWordList.tokenBounds[idx].startPos);
      return currentWordList.tokenBounds[idx].startPos;
   }
   if (~idx < currentWordList.tokenBounds.Count)
   {
      System.Diagnostics.Debug.WriteLine("C {0}", currentWordList.tokenBounds[~idx].startPos);
      return currentWordList.tokenBounds[~idx].startPos;
   }
   var lastBound = currentWordList.tokenBounds.LastOrDefault((b) => b.matched == 2);
   if (lastBound.NextPos <= cursor)
   {
      System.Diagnostics.Debug.WriteLine("D {0}", lastBound.NextPos);
      return lastBound.NextPos;
   }
   else
   {
      System.Diagnostics.Debug.WriteLine("E {0}", lastBound.startPos);
      return lastBound.startPos;
   }
}

按空格键时调试输出:

[0:] FindTokenStart: 
[0:] D 5
[0:] FindTokenStart: 
[0:] D 5
[0:] FindTokenStart: 
[0:] D 5
[0:] FindTokenStart: 
[0:] B 5
01-11 19:08:10.743 E/Surface ( 3326): getSlotFromBufferLocked: unknown buffer: 0x9a5e7d60
01-11 19:08:10.759 E/EGL_emulation( 3326): tid 3369: eglSurfaceAttrib(1210): error 0x3009 (EGL_BAD_MATCH)
01-11 19:08:10.759 W/OpenGLRenderer( 3326): Failed to set EGL_SWAP_BEHAVIOR on surface 0x98422b20, error=EGL_BAD_MATCH

我使用Visual Studio 2017和Xamarin开发此Android应用程序,并在Android模拟器上测试它是否重要。

1 个答案:

答案 0 :(得分:0)

没有必要更改MultiAutoCompleteTextView中间短语的适配器。期望是所有选项都被赋予适配器,并且适配器过滤器列出了更多字符,并确定哪些选项在当前令牌/短语中仍然相关。我经常更换适配器的原因是在确定适当的时间以确定应该应用什么新的适配器时的懒惰。如果空格不总是令牌的终止符,则它不应仅基于空格分隔符。

我的解决方案是使代码更加智能,以确保仅在两个令牌之间的分离时更新适配器。这相对容易实现,因为我现有的解析器知道最后一个令牌的结束位置以及下一个令牌应该从哪里开始。当它们相同时,意味着令牌仍然不完整。一旦输入完整的令牌值并由空格终止,则最后一个令牌的末尾将小于下一个令牌的开头。因此,在更新适配器之前添加此条件,我的问题已得到解决:

if (words.tokenBounds.Count == 0 || words.tokenBounds.Last().NextPos > words.tokenBounds.Last().EndPos)
    command.Adapter = suggestions.GetArrayAdapter(words);