如何在文本输入时防止android SearchView Query切换

时间:2017-12-08 10:57:48

标签: android xamarin mvvmcross searchview

我使用SearchView组件获取了我的视图。问题是输入字段中的每个新符号切换Query操作,因此有一些http请求是触发等,因此它开始工作缓慢。

我希望它只在我点击虚拟键盘上的搜索按钮(波纹管按钮)后才能运行。

enter image description here

SearchView中是否有任何属性?

布局代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                xmlns:local="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">


    <SearchView
        android:id="@+id/search"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:clickable="true"
        local:MvxBind="Query SearchString" />

</LinearLayout>

或者我应该像自定义绑定那样检测键盘按键点击?

UPD:

有些代码可以清楚地说明搜索的工作原理:

查看模型

public class RemoteMusicSearchViewModel : MvxViewModel
    {
        private IMvxNavigationService _mvxNavigationService;
        private IRemoteMusicDataService _remoteMusicDataService;
        private int _currentPage;

        public RemoteMusicSearchViewModel(IMvxNavigationService mvxNavigationService,
            IRemoteMusicDataService remoteMusicDataService)
        {
            _mvxNavigationService = mvxNavigationService;
            _remoteMusicDataService = remoteMusicDataService;
        }

        public override void Start()
        {
            base.Start();

            _currentPage = 0;
        }

        private string _searchString;

        public string SearchString
        {
            get { return _searchString; }

            set
            {
                _searchString = value;
                RaisePropertyChanged(() => SearchString);
                PerformBasicSearch().ConfigureAwait(false);
            }
        }

        private ObservableCollection<DownloadableEntity> _foundItems;

        public ObservableCollection<DownloadableEntity> FoundItems
        {
            get { return _foundItems; }

            set
            {
                if (_currentPage > 0)
                {
                    _foundItems = new ObservableCollection<DownloadableEntity>(_foundItems.Concat(value));
                }
                else
                {
                    _foundItems = value;
                }

                RaisePropertyChanged(() => FoundItems);
            }
        }

        private async Task PerformBasicSearch(int page = 0)
        {
            string request = SearchString;
            string result = await _remoteMusicDataService.SearchByProperty(request, MusicSearchType.ByTracks, page).ConfigureAwait(false);
            var searchResult = MusicSearchResult.FromJson(result);

            await PrepareDataForOutput(searchResult).ConfigureAwait(false);
        }
    }

完整的布局代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                xmlns:local="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">


    <SearchView
        android:id="@+id/search"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:clickable="true"
        local:MvxBind="Query SearchString"
        />

    <MvvmCross.Binding.Droid.Views.MvxListView
        android:id="@+id/searchlist"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        local:MvxBind="ItemsSource FoundItems"
        local:MvxItemTemplate="@layout/listitem"/>


</LinearLayout>

2 个答案:

答案 0 :(得分:1)

我猜你正在为这个问题寻找手动解决方案。

对于每个关键事件,您可以在特定阈值500毫秒后触发延迟操作。

也许使用Handler.postDelayed()

然后有三个场景

  • 另一个事件发生之前,所以你打电话给Handler.removeCallbacks()并发起另一个延迟行动
  • 当请求已被触发但是还没有结果时,会发生另一个事件,因此您取消请求并触发延迟操作。
  • 当没有延迟的操作未决或请求待处理时发生事件,因此您只需触发延迟操作。

但是,如果您愿意使用任何Reactive变体,那么通过基本上去除键盘敲击事件,有更复杂的解决方案。

答案 1 :(得分:0)

我找到了解决方案 - 我刚为此创建了新的绑定:

public class SearchViewKeyPressEventsBinding : MvxAndroidTargetBinding
    {
        private readonly SearchView _searchView;
        private IMvxAsyncCommand _command;

        public SearchViewKeyPressEventsBinding(SearchView searchView) : base(searchView)
        {
            _searchView = searchView;
            _searchView.QueryTextSubmit += _searchView_KeyPress;
        }

        private void _searchView_KeyPress(object sender, SearchView.QueryTextSubmitEventArgs e)
        {
            try
            {
                if (_command != null)
                {
                    _command.ExecuteAsync();
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public override Type TargetType
        {
            get { return typeof(IMvxAsyncCommand); }
        }


        protected override void SetValueImpl(object target, object value)
        {
            try
            {
                _command = (IMvxAsyncCommand)value;
            }
            catch (Exception e)
            {
                Log.Error("SOME BINDER FAIL\n\t" + e.Message + "\n", "SOME BINDER FAIL\n\t" + e.Message + "\n");
                throw;
            }
        }

        protected override void Dispose(bool isDisposing)
        {
            if (isDisposing)
            {
                _searchView.QueryTextSubmit -= _searchView_KeyPress;
            }
            base.Dispose(isDisposing);
        }
    }
}

然后注册它并且它起作用了:

   registry.RegisterFactory(new MvxCustomBindingFactory<SearchView>("OnSearchSubmit", (sv) => new SearchViewKeyPressEventsBinding(sv)))

布局:

<SearchView
        android:id="@+id/search10"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:clickable="true"
        local:MvxBind="Query SearchString; OnSearchSubmit OnSubmitPressCommand" />

并且不要忘记设置viewmodel的属性:

 public IMvxAsyncCommand OnSubmitPressCommand
        {
            get
            {
                return new MvxAsyncCommand(OnSearchSubmit);
            }
        }

  private async Task OnSearchSubmit()
        {
            //HideKeyboardOnSearchStart.Invoke(this, null);
            await PerformBasicSearch().ConfigureAwait(false);
        }