列表视图中的CheckedTextView在过滤搜索后更改位置

时间:2018-01-09 09:07:30

标签: android listview xamarin.android multi-select

我想在 android Xamarin 中实现多选列表。我使用了checkedTextview的自定义适配器。

适配器类:

 public class FilterableMultiselectAdapter : ArrayAdapter, IFilterable, View.IOnClickListener
    {
        LayoutInflater inflater;
        Filter filter;
        Activity context;
        public List<FilterableListViewModel> AllItems;
        public List<FilterableListViewModel> MatchItems;

        public List<string> SelectedItems= new List<string>();
        private CheckedTextView _checkedText;

        public FilterableMultiselectAdapter(Activity context, int txtViewResourceId, List<FilterableListViewModel> items) : base(context, txtViewResourceId, items)
        {
            inflater = context.LayoutInflater;
            filter = new SuggestionsFilter(this);
            AllItems = items;
            MatchItems = items;
        }

        public override int Count
        {
            get
            {
                return MatchItems.Count;
            }
        }

        public override Java.Lang.Object GetItem(int position)
        {
            return null;
        }

        public FilterableListViewModel GetMatchedItem(int position)
        {
            return MatchItems[position];
        }

        public List<string> SelectedItemsList()
        {
            return SelectedItems;
        }


        public override View GetView(int position, View convertView, ViewGroup parent)
        {
            View view = convertView;
            if (view == null)
                view = inflater.Inflate(Resource.Drawable.filterMultiselectList_view, null);

            _checkedText = view.FindViewById<CheckedTextView>(Resource.Id.chkTV);

            _checkedText.Text = MatchItems[position].displayName;
            _checkedText.SetOnClickListener(this);

            return view;
        }


        public void OnClick(View V)
        { 
            if (((CheckedTextView)V).Checked)
            {
                // set check mark drawable and set checked property to false
               // value = "un-Checked";
                ((CheckedTextView)V).SetCheckMarkDrawable(0);
                ((CheckedTextView)V).Checked = (false);

            }
            else
            {
                // set cheek mark drawable and set checked property to true
                // value = "Checked";
                ((CheckedTextView)V).SetCheckMarkDrawable(Resource.Drawable.ic_check);
                ((CheckedTextView)V).Checked = (true);
                addItemIntoCheckedList(((CheckedTextView)V).Text);
            }
        }

        private void addItemIntoCheckedList(string id)
        {


            SelectedItems.Add(id);

        }

        public override Filter Filter
        {
            get
            {
                return filter;
            }
        }

        public void ResetSearch()
        {
            MatchItems = AllItems;
            NotifyDataSetChanged();
        }

        class SuggestionsFilter : Filter
        {
            readonly FilterableMultiselectAdapter _adapter;

            public SuggestionsFilter(FilterableMultiselectAdapter adapter) : base()
            {
                _adapter = adapter;
            }

            protected override Filter.FilterResults PerformFiltering(Java.Lang.ICharSequence constraint)
            {
                FilterResults results = new FilterResults();
                if (!String.IsNullOrEmpty(constraint.ToString()))
                {
                    var searchFor = constraint.ToString();
                    Console.WriteLine("searchFor:" + searchFor);
                    var matchList = new List<FilterableListViewModel>();
                    //var matches = _adapter.AllItems.Where(i => i.title.ToLower().Contains(searchFor.ToLower()) || string.IsNullOrEmpty(i.subText) ? 1 == 1 : i.subText.ToLower().Contains(searchFor.ToLower()));

                    var matches = _adapter.AllItems.Where(i => i.item.ToLower().Contains(searchFor.ToLower()));// || (i.subItem != null && i.subItem.ToLower().Contains(searchFor.ToLower())));//   !string.IsNullOrEmpty(i.subText) ? i.subText.ToLower().Contains(searchFor.ToLower()) : null);


                    foreach (var match in matches)
                    {
                        matchList.Add(match);
                    }

                    _adapter.MatchItems = matchList;
                    Console.WriteLine("resultCount:" + matchList.Count);

                    List<FilterableListViewModel> matchObjects = new List<FilterableListViewModel>();
                    for (int i = 0; i < matchList.Count; i++)
                    {
                        matchObjects.Add(matchList[i]);
                    }

                    results.Count = matchList.Count;
                }
                else
                {
                    _adapter.ResetSearch();
                }
                return results;
            }

            protected override void PublishResults(Java.Lang.ICharSequence constraint, Filter.FilterResults results)
            {
                _adapter.NotifyDataSetChanged();
            }
        }
    }

这里的问题是假设我的列表中有4个项目,我选择了第1个和第2个项目,然后我去搜索一些给我剩余列表的内容,然后复选框的选择无法正常工作。

我试图找出问题,但我无法解决这个问题。我在Stackoverflow上发现了一个类似的问题,但它的解决方案指向和android库。我不能使用android库,因为我正在使用Xamarin android。

如果有人已经解决了这个问题,请帮助我。

2 个答案:

答案 0 :(得分:1)

我不是Xamarin开发人员,但我可以说你的代码没有优化。例如,您不需要使用成员变量private CheckedTextView _checkedText;,而是使用方法范围/局部变量。您可能希望查看ViewHolder模式以优化内存使用和性能。要解决您的问题,请检查代码段中的// TODO条评论,首先出现逻辑错误:

public void OnClick(View V)
{ 
    if (((CheckedTextView)V).Checked)
    {
        // set check mark drawable and set checked property to false
       // value = "un-Checked";
        ((CheckedTextView)V).SetCheckMarkDrawable(0);
        ((CheckedTextView)V).Checked = (false);
        // TODO I believe you should remove your item from SelectedItems
        SelectedItems.Remove(((CheckedTextView)V).Text);
    }
    else
    {
        // set cheek mark drawable and set checked property to true
        // value = "Checked";
        ((CheckedTextView)V).SetCheckMarkDrawable(Resource.Drawable.ic_check);
        ((CheckedTextView)V).Checked = (true);
        addItemIntoCheckedList(((CheckedTextView)V).Text);
    }
}

然后在方法GetView上,您应该检查SelectedItems列表中是否存在您的ID /文字

public override View GetView(int position, View convertView, ViewGroup parent)
{
    View view = convertView;
    if (view == null)
        view = inflater.Inflate(Resource.Drawable.filterMultiselectList_view, null);

    _checkedText = view.FindViewById<CheckedTextView>(Resource.Id.chkTV);

    _checkedText.Text = MatchItems[position].displayName;
    _checkedText.SetOnClickListener(this);
    // TODO check if the item is checked based on the id you have saved
    // something like this:
    if (SelectedItems.Contains(_checkedText.Text)) {
        _checkedText.Checked = true;
        _checkedText.SetCheckMarkDrawable(Resource.Drawable.ic_check);
    }
    else {
        _checkedText.Checked = false;
        _checkedText.SetCheckMarkDrawable(0);   
    }
    return view;
}

答案 1 :(得分:0)

您在单独的列表SelectedItems中管理所选项目,因此当MatchItems更改SelectedItems的内容变为过时而不是单独管理时,在模型中定义boolean { {1}} MatchItems并更新isSelected/isChecked

相关问题