Алфавитный указатель - PullRequest
0 голосов
/ 22 ноября 2018

Как получить событие движения пальца во флаттере, например, «индекс алфавита реселлера в андроиде», проверьте пример изображения.

Я создал просмотр списка индексов позиционированного алфавита, но не могу найти текущий индекс в DragUpdate.

            var alphabet = ["#","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"];

            new Positioned(
                top: .0,
                left: 1,
                bottom: 10,
                width: 55,
                child: Material(
                  borderRadius: BorderRadius.circular(15.0),
                  elevation: 10.0,
                  child: ListView.builder(
                      itemCount: alphabet.length,
                      itemBuilder: (BuildContext context, int index) {


                        return new GestureDetector(
                            onVerticalDragUpdate:
                                (DragUpdateDetails detail) {
                              setState(() {
                                _barOffset += detail.delta.dy;
                              });

                              print("$detail");
                              print("Update ${alphabet[index]}");
                            },

                             onVerticalDragStart: (DragStartDetails detail) {
                              print("onVerticalDragStart");
                              print("Start ${alphabet[index]}");
                            },
                            onVerticalDragEnd: (DragEndDetails detail) {
                              print("onVerticalDragEnd");
                              print("End ${alphabet[index]}");
                            },
                            onTap: () => print(alphabet[index]),
                            child: new Container(
                              margin: EdgeInsets.only(
                                  left: 20.0, right: 10.0, top: 6.5),
                              height: 15.0,
                              child: new Text('${alphabet[index]}'),
                            ));
                      }),
                ),

enter image description here

Ответы [ 2 ]

0 голосов
/ 09 июля 2019

Для этого выполните следующие шаги.

Шаг 1: Детектор жестов для ползунка от А до Я

  1. onVerticalDragUpdate: _onVerticalDragUpdate

  2. onVerticalDragStart: _onVerticalDragStart

Шаг 2: Добавить речевой пузырь для прокручиваемого алфавита.

Шаг 3: вычислить индекс с вертикально прокрученной позицией

if ((_offsetContainer + details.delta.dy) >= 0 &&
        (_offsetContainer + details.delta.dy) <=
            (_sizeheightcontainer - _heightscroller)) {
    _offsetContainer += details.delta.dy;
    posSelected =
        ((_offsetContainer / _heightscroller) % _alphabet.length).round();
    _text = _alphabet[posSelected];
    if (_text != _oldtext) {
        for (var i = 0; i < exampleList.length; i++) {
            if (_text
                    .toString()
                    .compareTo(exampleList[i].toString().toUpperCase()[0]) == 0) {
                _controller.jumpTo(i * _itemsizeheight);
                break;
            }
        }
        _oldtext = _text;
    }
}

Для полной реализации, проверьте это:

https://github.com/sanjaysingh1990/AtoZSliderCustomized.git

0 голосов
/ 09 марта 2019

Чтобы иметь что-то вроде этого:

Exemple

Начальная часть

Чтобы решить эту проблему, вам нужно создать собственный виджет, которыйвернет LayoutBuilder, который содержит Stack, который содержит ListView на первом слое и Container на втором слое (как скроллер) справа (чтобы поместить ваш скроллер справа, добавьте alignment: Alignment.topRight к вашему Stack).

Перемещение скроллера

Чтобы переместить скроллер, добавьте GestureDetector и поймайте onVerticalDragUpdate, добавьте пользовательское свойство _offsetContainer к тому, которое вы добавите details.delta.dy (из события), чтобы прокрутить ваш скроллер вниз и вверх.

Переместить ListView из скроллера

Первая часть

После этого вам нужно добавитьScrollController к вашему ListView для управления его вертикальным перемещением (как свойство controller).

Хорошо, теперь вам нужно знать кратные данные, чтобы продолжить:

  • Ваш алфавитный массивдлина
  • размер высоты вашего ListView
  • размер высоты скроллера
  • есть элемент colлекция отсортирована (логика)
  • Размер высоты одного элемента вашего ListView (который мы назовем _itemsizeheight)

Цель, которую нужно достичь сейчас, состоит в том, чтобы заставить вашListView на первый элемент в списке, начиная с выбранной буквы алфавита.

Для этого вам понадобятся некоторые математические и некоторые трюки.

Чтобы рассчитать ваш ListView рост, вам нужно взятьвысота тела и убрать высоту другого виджета.Но для упрощения здесь мы скажем, что ваш ListView принимает весь рост.Тогда это соответствует contrainsts.biggest.height (благодаря LayoutBuilder).

Чтобы рассчитать высоту скроллера, вы можете сделать это эффективно и разделить высоту тела на количество букв в вашем алфавитном массиве._heightscroller = contrainsts.biggest.height / _alphabet.length;

Вторая часть

Сначала мы заставим скроллер показывать индекс букв с помощью виджета Text.Затем добавьте виджет Text в свой контроллер и добавьте свойство _text в свой пользовательский виджет, чтобы вы могли изменить его с помощью функции setState.

В вашем onVerticalDragUpdate у вас есть _offset значение, соответствующее вашей позиции скроллера.Затем вам нужно сделать «простой» калькулятор, чтобы найти соответствующий ему индекс вашего массива алфавитов.

_text = _alphabet[((_offsetContainer / _heightscroller) % _alphabet.length).round()];

Третья часть

Теперь вы знаете букву, тогда будет легкосделай ход своим ListView.Сначала получите в своем списке индекс первого элемента, который соответствует выбранной букве.

Пример:

var index = 0;
for (var i = 0; i < widget.items.length; i++) {
   if (widget.items[i].toString().trim().length > 0 &&
       widget.items[i].toString().trim().toUpperCase()[0] ==
       _text.toString().toUpperCase()[0]) {
      index = i;
      break;
   }
}

Теперь, когда у вас есть индекс, просто используйте ваш ScrollController для перемещенияListView.

_scrollController.animateTo(index * _itemsizeheight,                         
   duration: new Duration(milliseconds: 500),
   curve: Curves.ease);

Сделать перемещение скроллера из ListView

Хорошо, теперь это работает, но нам нужно сделать перемещение скроллера тоже, не так ли?Я имею в виду, что я не хочу, чтобы он оставался на букве V, когда ListView отобразит мне A буквенных знаков.

Как это сделать?

В вашей функции инициализации простопосле этого вы устанавливаете ScrollController и добавляете _scrollController.addListener(onscrolllistview);, чтобы знать, когда пользователь будет выполнять прокрутку непосредственно в ListView.

. В вашей функции onscrolllistview вам нужны некоторые вычисления, чтобы отобразить первый элемент ипоследний отображаемый элемент.

var indexFirst = ((_scrollController.offset / _itemsizeheight) % widget.items.length).floor();
var indexLast = ((((_heightscroller * _alphabet.length) / _itemsizeheight).floor() + indexFirst) - 1) % widget.items.length;

Отлично, теперь вы можете легко узнать букву ведьмы, которую нужно отобразить на скроллере, а затем узнать, где она должна быть (изменить ее смещение).

var i = _alphabet.indexOf(fletter);
        if (i != -1) {
          setState(() {
            _text = _alphabet[i];
            _offsetContainer = i * _heightscroller;
          });

Значение fletter будет зависеть от направления прокрутки.

Если вы идете вниз, это будет:

var fletter = widget.items[indexLast].toString().toUpperCase()[0];

Если вы собираетесьвверх это будет:

var fletter = widget.items[indexFirst].toString().toUpperCase()[0];

Исправьте анимацию скроллера

Хорошо, теперь, если вы поставите debugPrint, вы увидите, что функция onscrolllistviewзвонил все время, даже когда мы используем скроллер.Это проблема.Тогда как это исправить?

Вам нужно знать, когда вы закончили двигаться, когда все ваши анимации закончены.

Затем просто добавьте свойство _animationcounter в ваш класс.Вы будете увеличивать его, когда перемещаете скроллер, и уменьшать его, когда одна анимация закончена.Как это:

for (var i = 0; i < widget.items.length; i++) {
   if (widget.items[i].toString().trim().length > 0 &&
       widget.items[i].toString().trim().toUpperCase()[0] ==
       _text.toString().toUpperCase()[0]) {
     _animationcounter++;
     _scrollController.animateTo(i * _itemsizeheight,
             duration: new Duration(milliseconds: 500),
             curve: Curves.ease) .then((x) => {_animationcounter--});
             break;
        }
   }

Теперь просто окружите свой код скроллера движущимся в onscrolllistview на

if (_animationcounter == 0) {/*...your code...*/}

PS

Вам нужно позаботиться о себе _offsetContainer, чтобы не выйти за пределы.Вы можете сделать это следующим образом:

if ((_offsetContainer + details.delta.dy) >= 0 &&
                  (_offsetContainer + details.delta.dy) <=
                      (context.size.height - _heightscroller)) {
                _offsetContainer += details.delta.dy;
    }

Это решение, вероятно, может быть оптимизировано (не отправляйте несколько анимаций, добавьте var, чтобы сделать меньше вызовов).Вы можете найти полную реализацию здесь: AtoZscrollflutter

...