Изменить цвет текущего верхнего видимого элемента в ListView - Flutter

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

Самое близкое, что у меня есть, это плагин ScrollablePositionedList: https://pub.dev/packages/scrollable_positioned_list

Первый элемент в списке теперь меняет цвет ИЛИ какой бы элемент ни находился на верхнем экране при горячей перезагрузке. Но они не делают это в реальном времени, пока я прокручиваю.

Буду очень признателен за любую помощь. Пожалуйста, найдите соответствующий код ниже. Заранее спасибо!

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:scrollviewexperiment/models/place_data.dart';
import 'package:scrollviewexperiment/widgets/place_tile.dart';
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';

class PlacesList extends StatefulWidget {
  @override
  _PlacesListState createState() => _PlacesListState();
}

class _PlacesListState extends State<PlacesList> {
  final ItemPositionsListener itemPositionsListener =
      ItemPositionsListener.create();

  ItemScrollController _itemScrollController = ItemScrollController();
  int currentIndex = 0;



  @override
  void initState() {
    super.initState();
    currentVisibleIndex();
  }

  @override
  Widget build(BuildContext context) {
    return Consumer<PlaceData>(
      builder: (context, placeData, child) {
        return ScrollablePositionedList.builder(
          itemCount: placeData.placeCount,
          itemPositionsListener: itemPositionsListener,
          itemBuilder: (context, index) {
            final place = placeData.places[index];
            return Card(
              color: index == currentIndex ? Colors.blue : Colors.white,
              elevation: 2.0,
              shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(10.0)),
              child: PlaceTile(
                placeName: place.name,
                distance: place.distance,
              ),
            );
          },
        );
      },
    );
  }

  currentVisibleIndex() {
    itemPositionsListener.itemPositions.addListener(() {
      int min;
      if (itemPositionsListener.itemPositions.value.isNotEmpty) {
        min = itemPositionsListener.itemPositions.value
            .where((ItemPosition position) => position.itemTrailingEdge > 0)
            .reduce((ItemPosition min, ItemPosition position) =>
                position.itemTrailingEdge < min.itemTrailingEdge
                    ? position
                    : min)
            .index;
        print('Min Index $min');
        currentIndex = min;
      }
    });
  }
}

person Alexander Taylro    schedule 23.05.2020    source источник


Ответы (1)


Я понял!

Я вернул ValueListenableBuilder внутри ScrollablePositionedList.builder itemBuilder

Это не самое чистое решение в мире, поэтому, если кто-то может улучшить его, я хотел бы знать.

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:scrollviewexperiment/models/place_data.dart';
import 'package:scrollviewexperiment/widgets/place_tile.dart';
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';

class PlacesList extends StatefulWidget {
  @override
  _PlacesListState createState() => _PlacesListState();
}

class _PlacesListState extends State<PlacesList> {
  final ItemPositionsListener itemPositionsListener =
      ItemPositionsListener.create();

  @override
  Widget build(BuildContext context) {
    return Consumer<PlaceData>(
      builder: (context, placeData, child) {
        return ScrollablePositionedList.builder(
          itemCount: placeData.placeCount,
          itemPositionsListener: itemPositionsListener,
          itemBuilder: (context, index) {
            final place = placeData.places[index];
            return ValueListenableBuilder<Iterable<ItemPosition>>(
              valueListenable: itemPositionsListener.itemPositions,
              builder: (context, positions, child) {
                int min;
                if (positions.isNotEmpty) {
                  min = positions
                      .where((ItemPosition position) =>
                          position.itemTrailingEdge > 0)
                      .reduce((ItemPosition min, ItemPosition position) =>
                          position.itemTrailingEdge < min.itemTrailingEdge
                              ? position
                              : min)
                      .index;
                }
                return Card(
                  color: index == min ? Colors.blue : Colors.white,
                  elevation: 2.0,
                  shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(10.0)),
                  child: PlaceTile(
                    placeName: place.name,
                    distance: place.distance,
                  ),
                );
              },
            );
          },
        );
      },
    );
  }
}
person Alexander Taylro    schedule 23.05.2020