Флаттер | Проблема с индикатором Refre sh при использовании вкладок внутри customscrollview, имеющих - PullRequest
0 голосов
/ 01 марта 2020

Я новичок, чтобы трепетать и пытаюсь получить представление карусели над моим списком, но при добавлении индикатора refre sh у меня странное поведение, когда я пытаюсь опустить вниз, чтобы обновить sh, экран обновляется сам без появления значка refre sh и когда я слишком сильно тяну, только тогда появляется значок refre sh, но затем также выдается эта ошибка 'package:flutter/src/widgets/scrollable.dart': Failed assertion: line 493 pos 12: '_drag == null': is not true. Я использовал представление Custom Scroll и пробовал также Nested scrollView, но проблема сохраняется. Я предполагаю, что что-то не так с настройкой высоты, но не в состоянии это выяснить. Вот gif для справки https://imgur.com/XCDxeng

Вот код, который я пытаюсь запустить

>>>>>>>>main.dart starts from here<<<<<<

void main() => runApp(MyApp());


class MyApp extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
   return MultiProvider(
     providers: [
       ChangeNotifierProvider.value(
         value: DefaultContentProvider(),
       ),
     ],
        child: MaterialApp(
       title: 'My Flutter App',
      //  home: HomePage(),
       routes: {
         '/': (context) => HomePage(),
       },
     ),
   );
 }
}

>>>>>>>>HomePage starts from here <<<<<<<<

class HomePage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _HomePageState();
  }
}

class _HomePageState extends State<HomePage>
    with SingleTickerProviderStateMixin {
  int _currentIndex = 0;
  TabController _tabController;

  @override
  void initState() {
    super.initState();
    _tabController = TabController(
      // initialIndex: 2,
      vsync: this,
      length: 3,
    );
  }

  @override
  void dispose() {
    _tabController.dispose();
    super.dispose();
  }

  void onBottomTabTapped(int index) {
    setState(() {
      _currentIndex = index;
      _tabController.index = 0;
    });
  }

  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: 3,
      child: Scaffold(
        appBar: AppBar(
          title: Text('My Flutter App'),
        ),
        drawer: AppDrawer(),
        body: Column(
          children: <Widget>[
            Container(
              decoration: BoxDecoration(color: Colors.cyanAccent),
              child: TabBar(
                labelColor: Colors.black,
                controller: _tabController,
                tabs: buildTabBar(_currentIndex),
                onTap: (i) {
                  print(i);
                },
              ),
            ),
            Expanded(
              child: TabBarView(
                controller: _tabController,
                children: buildTabBody(_currentIndex),
              ),
            ),
          ],
        ),
        bottomNavigationBar: BottomNavigationBar(
          onTap: onBottomTabTapped,
          currentIndex: _currentIndex,
          items: [
            BottomNavigationBarItem(
                icon: Icon(Icons.home), title: Text('Home')),
            BottomNavigationBarItem(
              icon: Icon(Icons.mail),
              title: Text('Messages'),
            ),
            BottomNavigationBarItem(
              icon: Icon(Icons.person),
              title: Text('Profile'),
            )
          ],
        ),
      ),

    );
  }
}

>>>>>>>buildTabBar and TabBody starts from here<<<<<

buildTabBar(index) {
  switch (index) {
    case 0:
      return <Tab>[
        Tab(text: 'Test'),
        Tab(icon: Icon(Icons.directions_car)),
        Tab(icon: Icon(Icons.directions_transit)),
      ];

buildTabBody(index) {
  switch (index) {
    case 0:
      return [
        FirstTab(),
        _children[1],
        _children[2],
      ];


>>>>>>FirstTab code starts from here<<<<<

class FirstTab extends StatefulWidget {
  @override
  _FirstTabState createState() => _FirstTabState();
}

class _FirstTabState extends State<FirstTab> {
  ScrollController _scrollController = ScrollController();

  @override
  void initState() {
    _scrollController.addListener(() {
      if (_scrollController.position.pixels ==
          _scrollController.position.maxScrollExtent) {
        getMoreData();
      }
    });
    super.initState();
  }

  @override
  void dispose() {
    _scrollController.dispose();
    super.dispose();
  }

  Future<void> getMoreData() {
    return Provider.of<DefaultContentProvider>(context, listen: false)
        .fetchAndSetItems();
  }

  Future<void> refreshData() {
    Provider.of<DefaultContentProvider>(context, listen: false).clearAllData();
    return Provider.of<DefaultContentProvider>(context, listen: false)
        .fetchAndSetItems();
  }

  @override
  Widget build(BuildContext context) {
    return RefreshIndicator(
      onRefresh: refreshData,
          child: CustomScrollView(
        // physics: const AlwaysScrollableScrollPhysics(),
        controller: _scrollController,
        slivers: <Widget>[
          SliverList(
            delegate: SliverChildListDelegate([
              CaraouselItems(),
            ]),
          ),
          SliverList(
              delegate: SliverChildListDelegate([
            ContentList(),
          ]))
        ],
      ),
    );
  }
}


>>>>>>> CarouselItems code<<<<<<


class CaraouselItems extends StatefulWidget {
  @override
  _CaraouselItemsState createState() => _CaraouselItemsState();
}

class _CaraouselItemsState extends State<CaraouselItems> {
  int _currentIndex = 0;
  List imgList = [
    'https://images.pexels.com/photos/3667816/pexels-photo-3667816.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260',
    'https://images.pexels.com/photos/3807512/pexels-photo-3807512.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260',
    'https://images.pexels.com/photos/3690052/pexels-photo-3690052.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260',
    'https://images.pexels.com/photos/3617496/pexels-photo-3617496.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260',
    'https://images.pexels.com/photos/3639542/pexels-photo-3639542.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260',
  ];
  List<T> map<T>(List list, Function handler) {
    List<T> result = [];
    for (var i = 0; i < list.length; i++) {
      result.add(handler(i, list[i]));
    }
    return result;
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        CarouselSlider(
          height: 200.0,
          initialPage: 0,
          enlargeCenterPage: true,
          // autoPlay: true,
          enableInfiniteScroll: true,
          autoPlayInterval: Duration(seconds: 4),
          autoPlayAnimationDuration: Duration(milliseconds: 2000),
          pauseAutoPlayOnTouch: Duration(seconds: 6),
          onPageChanged: (index) {
            setState(() {
              _currentIndex = index;
            });
          },
          items: imgList
              .map((imgUrl) => Builder(builder: (BuildContext context) {
                    return Container(
                      width: double.infinity,
                      margin:
                          EdgeInsets.symmetric(horizontal: 5, vertical: 10),
                      decoration: BoxDecoration(
                        color: Colors.grey,
                      ),
                      child: Image.network(imgUrl, fit: BoxFit.cover),
                    );
                  }))
              .toList(),
        ),
        SizedBox(height: 5),
        Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: map<Widget>(imgList, (index, url) {
            return Container(
              width: 10,
              height: 10,
              margin: EdgeInsets.symmetric(vertical: 10, horizontal: 2),
              decoration: BoxDecoration(
                  shape: BoxShape.circle,
                  color: _currentIndex == index ? Colors.blue : Colors.grey),
            );
          }),
        ),
      ],
    );
  }
}

>>>>> ContentList class <<<<

class ContentList extends StatefulWidget {
  @override
  _ContentListState createState() => _ContentListState();
}

class _ContentListState extends State<ContentList> {
  ScrollController _scrollController = ScrollController();



  @override
  void dispose() {
    _scrollController.dispose();
    super.dispose();
  }

@override
  Widget build(BuildContext context) {
    return FutureBuilder(
      future: Provider.of<DefaultContentProvider>(context, listen: false)
          .fetchAndSetItems(),
      builder: (context, AsyncSnapshot snapshot) {
        if (snapshot.connectionState == ConnectionState.waiting) {
          return Center(child: CircularProgressIndicator());
        } else {
          if (snapshot.error != null) {
            print(snapshot.error);
            return Center(
              child: Text('An error occured'),
            );
          } else {
            return Consumer<DefaultContentProvider>(
              builder: (context, contentData, child) => ListView.builder(
                shrinkWrap: true,
                controller: _scrollController,
itemCount: contentData.lazyItem.length + 1,
                itemBuilder: (context, index) {
                  if (index < contentData.lazyItem.length) {
                    return CardItem(
                      id: contentData.lazyItem[index].id,
                      title: contentData.lazyItem[index].title,
                      imageUrl: contentData.lazyItem[index].imageUrl,
                      contentLength: contentData.items.length,
                    );
                  } else if (index < contentData.items.length) {
                    // return _buildProgressIndicator();
                    return Padding(
                      padding: EdgeInsets.symmetric(vertical: 32),
                      child: Center(
                        child: Text('Loading more content'),
                      ),
                    );
                  } else {
                    return Padding(
                      padding: EdgeInsets.symmetric(vertical: 32),
                      child: Center(
                        child: Text('No more content to display'),
                      ),
                    );
                  }
                },
              ),
            );
          }
        }
      },
    );
  }



 }




>>>>>> ProviderClass<<<<<<

class DefaultContentProvider extends ChangeNotifier {
  List _items = [];
  List<CardItem> lazyItem = [];
  int lazyItemIndex = 0;

  List<CardItem> get items {
    return [..._items];
  }

  List<CardItem> fetchTenItems() {
    if (lazyItemIndex >= items.length - 1) return [];
    var i;
    for (i = 0; i < 10; i++) {
      lazyItem.add(items[lazyItemIndex + i]);
    }
    lazyItemIndex += i;
    return lazyItem;
  }

  void clearAllData() {
    _items = [];
    lazyItem = [];
    lazyItemIndex = 0;
  }

  Future<void> fetchAndSetItems() async {
    var url = 'https://jsonplaceholder.typicode.com/posts';
    final response = await http.get(url);
    final extractedData = await json.decode(response.body) as List<dynamic>;
    if (extractedData == null) {
      return;
    }

    final List<CardItem> responseData = [];
    extractedData.forEach((objectResponse) {
      responseData.add(
        CardItem(
          id: objectResponse['id'],
          title: objectResponse['title'],
          imageUrl:
              'https://images.pexels.com/photos/3690052/pexels-photo-3690052.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260',
        ),
      );
    });
    _items = responseData;
    fetchTenItems();
    notifyListeners();
  }
}

Пожалуйста, проверьте скобки и другие ошибки, которые могут были закраданы при копировании.

Вот изображение для справки https://imgur.com/XCDxeng

Заранее спасибо.

...