滚动索引方法无法持续触发

时间:2018-11-13 18:59:57

标签: xamarin xamarin.android

在Xamarin.Forms和Xamarin.Android项目中,我为ListView创建了自定义渲染和适配器。 适配器实现BaseAdapter和ISectionIndexer。该控件的自定义呈现使用FastScroll功能,在Android中,当您点击此滚动时,会出现带有索引字母的气泡。这很好用,但是我的想法是要有一种方法来释放滚动后的选定的索引,并且滚动“气泡”消失。 我认为使用以下类(在GetSectionForPosition方法中)可以实现这一点:

public class ListViewconIndexAdapter : BaseAdapter<string>, ISectionIndexer
    {
        string[] items;
        Activity context;

        string[] sections;
        Java.Lang.Object[] sectionsObjects;
        Dictionary<string, int> alphaIndex;

        public ListViewconIndexAdapter(Activity context, string[] items) : base()
        {
            this.context = context;
            this.items = items;

            alphaIndex = new Dictionary<string, int>();
            for (int i = 0; i < items.Length; i++)
            {
                var key = items[i][0].ToString();
                if (!alphaIndex.ContainsKey(key))
                    alphaIndex.Add(key, i);
            }
            sections = new string[alphaIndex.Keys.Count];
            alphaIndex.Keys.CopyTo(sections, 0);
            sectionsObjects = new Java.Lang.Object[sections.Length];
            for (int i = 0; i < sections.Length; i++)
            {
                sectionsObjects[i] = new Java.Lang.String(sections[i]);
            }

        }


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

        public override long GetItemId(int position)
        {
            return position;
        }

        public override string this[int position]
        {
            get { return items[position]; }
        }

        public override View GetView(int position, View convertView, ViewGroup parent)
        {
            View view = convertView;
            if (view == null)
                view = context.LayoutInflater.Inflate(Android.Resource.Layout.SimpleListItem1, null);
            view.FindViewById<TextView>(Android.Resource.Id.Text1).Text = items[position];
            return view;
        }

        //Fill in cound here, currently 0
        public override int Count
        {
            get { return items.Length; }
        }

        // -- ISectionIndexer --
        public int GetPositionForSection(int section)
        {
            return alphaIndex[sections[section]];
        }

        public int GetSectionForPosition(int position)
        {      // this method isn't called in this example, but code is provided for completeness
            int prevSection = 0;

            for (int i = 0; i < sections.Length; i++)
            {
                if (GetPositionForSection(i) > position)
                {
                    break;
                }

                prevSection = i;
            }

            Console.WriteLine(prevSection);
            Console.WriteLine(sections[prevSection]);

            //Toast.MakeText(context, sections[prevSection], ToastLength.Short).Show();
            Xamarin.Forms.MessagingCenter.Send<object,string>(this, "CambioSeccion", sections[prevSection]);
            return prevSection;
        }

    }

我放置了那些Console.writeline来检查索引字母,并且消息发送是一种将其发送回PCL / NET Standard代码(以显示DisplayAlert或类似内容)的方式。 但是问题是方法触发不一致,例如,有时您快速向下滚动到“ C”,但在将其释放后,Console无法打印任何内容,但是在您离开的位置再次触摸它之后它,它启动。但是有时它会像我想要的那样工作,在释放选定索引处的滚动条后会打印出来。

1 个答案:

答案 0 :(得分:0)

ListView有两个不同的滚动侦听器,AbsListView.IOnScrollListenerAbsListView.IOnScrollChangeListener(API 23中添加了此滚动侦听器)和一个触摸侦听器(AbsListView.IOnTouchListener

我认为,根据您的用例,您正在寻找OnScrollStateChanged,当它进入空闲状态并且您没有触摸列表视图时,请执行某项操作(反之亦然)。

示例(当然,请根据您的需要进行调整):

    public class MyScrollListener : Java.Lang.Object, AbsListView.IOnTouchListener, AbsListView.IOnScrollListener, AbsListView.IOnScrollChangeListener //(API23)
    {
        bool touching;
        bool scrolling;

        public void OnScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount)
        {
        }

        public void OnScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY)
        {
        }

        public void OnScrollStateChanged(AbsListView view, [GeneratedEnum] ScrollState scrollState)
        {
            switch(scrollState)
            {
                case ScrollState.Idle:
                    if (!touching)
                    {
                        scrolling = false;
                        GetSelection();
                    }
                    break;
                default:
                    scrolling = true;
                    break;
            }
        }

        public bool OnTouch(View v, MotionEvent e)
        {
            switch (e.Action)
            {
                case MotionEventActions.Up:
                    touching = false;
                    if (!scrolling)
                        GetSelection();
                    break;
                default:
                    touching = true;
                    break;
            }
            return true;
        }

        void GetSelection()
        {
            // touch and srolling is done, do something
        }
    }

用法:

var scrollListener = new MyScrollListener();
listView.SetOnTouchListener(scrollListener);
listView.SetOnScrollListener(scrollListener);
listView.SetOnScrollChangeListener(scrollListener); // API23