Home > Mobile >  flutter how to display a list by scrolling
flutter how to display a list by scrolling

Time:08-08

i want the popular menu to scroll down as i scroll on the whole page , not as it is right now scrolling only on that little part

its a Listview.builder inside a Listview

Demo : https://i.stack.imgur.com/TZ8xH.gif

here is the full code

its commented where the Listview and Listview.builder are

ctrl f search this "//////" to quickly find them

import 'dart:async';
import 'package:custom_refresh_indicator/custom_refresh_indicator.dart';

import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:foodninja/consts.dart';
import 'package:lottie/lottie.dart';
 
Color whiteBcg = const Color.fromARGB(255, 255, 255, 255);
Color limeColor = const Color.fromARGB(204, 77, 200, 118);
Color blackColor = Colors.black;
Color orangeInside = const Color.fromARGB(255, 210, 122, 0);
Color orangeOutside = const Color.fromARGB(45, 210, 123, 0);
Color cardBcg = const Color.fromRGBO(238, 238, 238, 1);
Color subText = const Color.fromARGB(255, 164, 164, 164);

class MyIconButton extends StatelessWidget {
  const MyIconButton({
    Key? key,
    required this.icon,
    required this.onClickAction,
  }) : super(key: key);

  final IconData icon;
  final Function onClickAction;

  @override
  Widget build(BuildContext context) {
    return Container(
        height: 50,
        width: 50,
        decoration: BoxDecoration(
            color: orangeOutside,
            // border: Border.all(
            //   color: Colors.red,
            // ),
            borderRadius: BorderRadius.circular(15)),
        child: TextButton(
          style: ButtonStyle(
            backgroundColor: MaterialStateProperty.all<Color>(
                const Color.fromARGB(2, 255, 149, 0)),
          ),
          onPressed: () => onClickAction(),
          child: Icon(
            icon,
            color: orangeInside,
          ),
        ));
  }
}

class HomeScreen extends StatelessWidget {
  const HomeScreen({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    double h = MediaQuery.of(context).size.height;
    double w = MediaQuery.of(context).size.width;
    return Scaffold(
      body: CustomRefreshIndicator(
        onRefresh: () {
          return Future(
            () {},
          );
        },
        builder: (
          BuildContext context,
          Widget child,
          IndicatorController controller,
        ) {
          return AnimatedBuilder(
            animation: controller,
            builder: (BuildContext context, _) {
              return Stack(
                children: <Widget>[
                  if (controller.isDragging ||
                      controller.isArmed ||
                      controller.isLoading)
                    Positioned(
                      left: w * 0.37,
                      top: controller.value * 50,
                      child: SizedBox(
                        height: 100,
                        width: 100,
                        child: Transform.translate(
                            offset: Offset(0, controller.value * 20),
                            child: Transform.scale(
                                scale: controller.value *1.5,
                                child:
                                    Lottie.asset("assets/burgerBounce.json"))),
                      ),
                    ),
                  // if (controller.isArmed)
                  //   Positioned(
                  //     left: 0,
                  //     top: 25 * controller.value,
                  //     child: SizedBox(
                  //       height: 100,
                  //       width: 100,
                  //       child: Lottie.asset("assets/icecream.json"),
                  //     ),
                  //   ),
                  Transform.translate(
                    offset: const Offset(0, 0),
                    child: child,
                  )
                ],
              );
            },
          );
        },
        child: ListView(physics: const BouncingScrollPhysics(), children: [ ///////the list view
          SafeArea(
            child: Stack(children: [
              SizedBox(
                width: 500,
                child: Image.asset(
                  'assets/PhoneVerificationPattern.png',
                  fit: BoxFit.fill,
                ),
              ),
              Padding(
                padding: const EdgeInsets.all(20.0),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    const SizedBox(
                      height: 30,
                    ),
                    Row(
                        mainAxisAlignment: MainAxisAlignment.spaceBetween,
                        children: [
                          const Text(
                            "Find your \nfavorite food",
                            style: TextStyle(
                                fontSize: 35, fontWeight: FontWeight.bold),
                          ),
                          MyIconButton(
                            icon: Icons.notifications_none,
                            onClickAction: () {},
                          ),
                        ]),
                    const SizedBox(
                      height: 20,
                    ),
                    Container(
                      alignment: Alignment.center,
                      height: 70,
                      width: w,
                      decoration: BoxDecoration(
                          color: orangeOutside,
                          // border: Border.all(
                          //   color: Colors.red,
                          // ),
                          borderRadius: BorderRadius.circular(15)),
                      child: TextFormField(
                          style: TextStyle(color: orangeInside),
                          decoration: InputDecoration(
                              hintText: "what do you want to order ?",
                              hintStyle: TextStyle(color: orangeInside),
                              prefixIconColor: orangeInside,
                              fillColor: orangeInside,
                              focusColor: orangeInside,
                              border: InputBorder.none,
                              focusedBorder: InputBorder.none,
                              prefixIcon: Icon(
                                Icons.search,
                                color: orangeInside,
                              ),
                              contentPadding:
                                  EdgeInsets.fromLTRB(0, 14, 0, 0))),
                    ),
                    const SizedBox(
                      height: 20,
                    ),
                    PromoAdvert(h: h, w: w),
                    const SizedBox(
                      height: 15,
                    ),
                    Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: [
                        const Text(
                          "Nearest resturants",
                          style: TextStyle(
                              fontSize: 18, fontWeight: FontWeight.bold),
                        ),
                        RichText(
                          text: TextSpan(
                            children: [
                              TextSpan(
                                  text: "View more",
                                  style: TextStyle(
                                    fontSize: 15,
                                    color: orangeInside,
                                  ),
                                  recognizer: TapGestureRecognizer()
                                    ..onTap = () {}),
                            ],
                          ),
                        ),
                      ],
                    ),
                    const SizedBox(
                      height: 15,
                    ),
                    NearestResturants(w: w, h: h),
                    const SizedBox(
                      height: 15,
                    ),
                    Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: [
                        const Text(
                          "Popular menu",
                          style: TextStyle(
                              fontSize: 18, fontWeight: FontWeight.bold),
                        ),
                        RichText(
                          text: TextSpan(
                            children: [
                              TextSpan(
                                  text: "View more",
                                  style: TextStyle(
                                    fontSize: 15,
                                    color: orangeInside,
                                  ),
                                  recognizer: TapGestureRecognizer()
                                    ..onTap = () {}),
                            ],
                          ),
                        ),
                      ],
                    ),
                    const SizedBox(
                      height: 20,
                    ),
                    SizedBox(
                      height: 70,
                      width: 400,
                      child: ListView.builder( ////////////////List view builder where the problem is
                        shrinkWrap: true,
                        scrollDirection: Axis.vertical,
                        itemCount: 4,
                        itemBuilder: (context, index) => Container(
                            height: 70,
                            width: 400,
                            decoration: BoxDecoration(
                                color: cardBcg,
                                // border: Border.all(
                                //   color: Colors.red,
                                // ),
                                borderRadius: BorderRadius.circular(15)),
                            child: Row(
                              children: [
                                Padding(
                                  padding:
                                      const EdgeInsets.fromLTRB(9, 5, 0, 5),
                                  child: Container(
                                    width: 50,
                                    decoration: BoxDecoration(
                                      image: DecorationImage(
                                        image: AssetImage(
                                          nearestResturantsContentList[index]
                                              .image,
                                        ),
                                      ),
                                      borderRadius: BorderRadius.circular(15),
                                    ),
                                  ),
                                ),
                                const SizedBox(
                                  width: 20,
                                ),
                                Column(
                                  crossAxisAlignment: CrossAxisAlignment.start,
                                  mainAxisAlignment: MainAxisAlignment.center,
                                  children: [
                                    Text(
                                      "Fruit Salade ",
                                      textAlign: TextAlign.start,
                                    ),
                                    Text(
                                      "Vegan resto",
                                      textAlign: TextAlign.start,
                                      style: TextStyle(color: subText),
                                    ),
                                  ],
                                ),
                                const SizedBox(
                                  width: 150,
                                ),
                                Text(
                                  "7\$",
                                  textAlign: TextAlign.start,
                                  style: TextStyle(
                                      color: const Color.fromARGB(
                                          255, 254, 171, 29),
                                      fontSize: 23),
                                )
                              ],
                            )),
                      ),
                    ),
                  ],
                ),
              )
            ]),
          ),
        ]),
      ),
    );
  }
}

class NearestResturantsContent {
  late String image;
  late String text;
  late String subText;

  NearestResturantsContent(
    this.image,
    this.text,
    this.subText,
  );
}

List<NearestResturantsContent> nearestResturantsContentList = [
  NearestResturantsContent(
    "assets/veganRestoLogo.png",
    "veganResto",
    "3KM",
  ),
  NearestResturantsContent(
    "assets/AjintiLogo.png",
    "Ajinti",
    "6KM",
  ),
  NearestResturantsContent(
    "assets/ChefGoLogo.png",
    "ChefGo",
    "10KM",
  ),
  NearestResturantsContent(
    "assets/BakeryLogo.png",
    "Bakery",
    "3KM",
  ),
  NearestResturantsContent(
    "assets/healthyFoodLogo.png",
    "healthyFood",
    "5KM",
  ),
  NearestResturantsContent(
    "assets/windowstoLogo.png",
    "windowsto",
    "3KM",
  ),
];

class NearestResturants extends StatelessWidget {
  const NearestResturants({
    Key? key,
    required this.w,
    required this.h,
  }) : super(key: key);

  final double w;
  final double h;

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      width: w,
      height: h * 0.22,
      child: ListView.builder(
        scrollDirection: Axis.horizontal,
        itemCount: nearestResturantsContentList.length,
        itemBuilder: (context, index) {
          return Container(
            margin: const EdgeInsets.fromLTRB(0, 0, 10, 0),
            width: w * 0.4,
            height: h * 0.22,
            decoration: BoxDecoration(
                color: cardBcg,
                // border: Border.all(
                //   color: Colors.red,
                // ),
                borderRadius: BorderRadius.circular(15)),
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: [
                SizedBox(
                  child: SizedBox(
                    height: 90,
                    width: 90,
                    child: Image.asset(
                      nearestResturantsContentList[index].image,
                      fit: BoxFit.fill,
                    ),
                  ),
                ),
                Text(
                  nearestResturantsContentList[index].text,
                  style: const TextStyle(
                      fontSize: 20,
                      fontWeight: FontWeight.bold,
                      overflow: TextOverflow.ellipsis),
                ),
                const SizedBox(
                  height: 5,
                ),
                Text(
                  nearestResturantsContentList[index].subText,
                  style: TextStyle(
                      color: subText,
                      fontSize: 13,
                      fontWeight: FontWeight.bold,
                      overflow: TextOverflow.ellipsis),
                ),
              ],
            ),
          );
        },
      ),
    );
  }
}

class PromoAdvertContent {
  late String image;
  late String text;
  late String subText;
  late Color color;
  PromoAdvertContent(this.image, this.text, this.subText, this.color);
}

List<PromoAdvertContent> promoAdvertContentList = [
  PromoAdvertContent("assets/promoAdvert.png", "Special deal for \nOctober",
      "Buy now", limeColor),
  PromoAdvertContent("assets/promoAdvert.png", "Special deal for \nOctober",
      "check out", orangeInside),
  PromoAdvertContent(
      "assets/promoAdvert.png", "No way this \nOctober", "check out", subText)
];

class PromoAdvert extends StatelessWidget {
  const PromoAdvert({
    Key? key,
    required this.h,
    required this.w,
  }) : super(key: key);

  final double h;
  final double w;

  @override
  Widget build(BuildContext context) {
    bool isScrollingToRight = true;
    int currentPage = 0;
    PageController scrollController = PageController(initialPage: 0);

 
    void _scrollToBottom() {
      if (currentPage < promoAdvertContentList.length && isScrollingToRight) {
        currentPage  ;
      } else if (!isScrollingToRight && currentPage == 0) {
        currentPage  ;
        isScrollingToRight = true;
      } else {
        isScrollingToRight = false;
        currentPage--;
      }
      if (scrollController.hasClients) {
        scrollController.animateToPage(
          currentPage,
          duration: const Duration(milliseconds: 1000),
          curve: Curves.easeOut,
        );
      }
    }

    WidgetsBinding.instance.addPostFrameCallback(
        (_) => Timer.periodic(const Duration(seconds: 15), (_) {
              _scrollToBottom();
            }));

    return SizedBox(
      width: w,
      height: h * 0.217,
      child: CustomRefreshIndicator(
        onRefresh: () {
          return Future(
            () {},
          );
        },
        builder: (
          BuildContext context,
          Widget child,
          IndicatorController controller,
        ) {
          return AnimatedBuilder(
            animation: controller,
            builder: (BuildContext context, _) {
              return Stack(
                children: <Widget>[
                  if (controller.isDragging ||
                      controller.isArmed ||
                      controller.isLoading)
                    Positioned(
                      left: 0,
                      top: h * 0.05,
                      child: SizedBox(
                        height: 100,
                        width: 100,
                        child: Transform.translate(
                            offset: Offset(-controller.value * 20, 0),
                            child: Transform.rotate(
                                angle: 11,
                                child: Lottie.asset("assets/icecream.json"))),
                      ),
                    ),
                  // if (controller.isArmed)
                  //   Positioned(
                  //     left: 0,
                  //     top: 25 * controller.value,
                  //     child: SizedBox(
                  //       height: 100,
                  //       width: 100,
                  //       child: Lottie.asset("assets/icecream.json"),
                  //     ),
                  //   ),
                  Transform.translate(
                    offset: const Offset(0, 0),
                    child: child,
                  )
                ],
              );
            },
          );
        },
        child: PageView.builder(
          controller: scrollController,
          physics: const BouncingScrollPhysics(),
          scrollDirection: Axis.horizontal,
          itemCount: promoAdvertContentList.length,
          itemBuilder: (context, index) {
            if (promoAdvertContentList.length == index) {
              print('a"sqdqsqs');
              CircularProgressIndicator();
            }
            return Container(
              width: h * 0.47,
              height: 160,
              decoration: BoxDecoration(
                  color: promoAdvertContentList[index].color,
                  // border: Border.all(
                  //   color: Colors.red,
                  // ),
                  borderRadius: BorderRadius.circular(15)),
              child: Stack(children: [
                SizedBox(
                  height: 160,
                  width: h * 0.47,
                  child: Image.asset(
                    promoAdvertContentList[index].image,
                    fit: BoxFit.fill,
                  ),
                ),
                Positioned(
                    top: 30,
                    right: 5,
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Text(
                          promoAdvertContentList[index].text,
                          style: TextStyle(
                              color: whiteBcg,
                              fontSize: 20,
                              fontWeight: FontWeight.bold),
                        ),
                        const SizedBox(
                          height: 10,
                        ),
                        NextButton(
                          h: h,
                          w: w,
                          text: promoAdvertContentList[index].subText,
                        )
                      ],
                    ))
              ]),
            );
          },
        ),
      ),
    );
  }
}

class NextButton extends StatelessWidget {
  const NextButton({
    Key? key,
    required this.h,
    required this.w,
    required this.text,
  }) : super(key: key);
  final double h;
  final double w;
  final String text;

  @override
  Widget build(BuildContext context) {
    return Center(
      child: SizedBox(
        height: 45,
        width: 100,
        child: Card(
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(5),
          ),
          elevation: 5,
          child: TextButton(
              style: ButtonStyle(
                  shape: MaterialStateProperty.all<RoundedRectangleBorder>(
                      RoundedRectangleBorder(
                    borderRadius: BorderRadius.circular(5),
                  )),
                  backgroundColor: MaterialStateProperty.all<Color>(whiteBcg)),
              onPressed: () {},
              child: Text(
                text,
                style: TextStyle(color: limeColor, fontSize: 15),
                overflow: TextOverflow.ellipsis,
                softWrap: false,
              )),
        ),
      ),
    );
  }
}

CodePudding user response:

To the list view that is scrolling separately add physics

physics: NeverScrollableScrollPhysics(),

And remove sized box which is wrapping the listview

  • Related