Home > Software engineering >  Unable to horizontally scroll a ListView in Flutter
Unable to horizontally scroll a ListView in Flutter

Time:08-05

I am trying to scroll the logos of brands in a horizontal direction. The image urls of these logos are held in a list of maps. However, when I return the custom widget BrandLogoCard, not all logos are visible and I'm unable to scroll to the end of the list.

My code:

home_welcome_screen.dart

import 'package:flutter/material.dart';
import 'package:musicart/widgets/animated_bottom_bar.dart';
import 'package:musicart/widgets/brand_logo_card.dart';
import 'package:musicart/widgets/search_widget.dart';

import '../global_variables/global_variables.dart';
import 'package:carousel_slider/carousel_slider.dart';

class HomeWelcomeScreen extends StatefulWidget {
  const HomeWelcomeScreen({Key? key}) : super(key: key);

  @override
  State<HomeWelcomeScreen> createState() => _HomeWelcomeScreenState();
}

class _HomeWelcomeScreenState extends State<HomeWelcomeScreen> {
  final TextEditingController _searchBoxController = TextEditingController();
  final String _hintText = "Search instruments...";
  int _currentIndex = 0;
  int _currentCarouselIndex = 0;

  @override
  Widget build(BuildContext context) {
    double? screenWidth = MediaQuery.of(context).size.width;
    double? screenHeight = MediaQuery.of(context).size.height;
    List<Widget> indicators(imagesLength, currentIndex) {
      return List<Widget>.generate(imagesLength, (index) {
        return Container(
          margin: EdgeInsets.symmetric(
            vertical: screenHeight * 0.26,
            horizontal: 2,
          ),
          width: currentIndex == index ? 15 : 10,
          height: 3,
          decoration: BoxDecoration(
            color: currentIndex == index ? Colors.black87 : Colors.grey,
            borderRadius: const BorderRadius.all(
              Radius.circular(2),
            ),
          ),
        );
      });
    }

    return Scaffold(
      body: Stack(
        children: [
          SizedBox(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.start,
              children: [
                Padding(
                  padding: EdgeInsets.only(top: screenHeight * 0.02),
                ),
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                  children: [
                    Padding(
                      padding: EdgeInsets.only(
                          left: screenWidth * 0.025, right: screenWidth * 0.02),
                      child: InkWell(
                        onTap: () {},
                        child: const Icon(
                          Icons.menu_rounded,
                          color: Colors.black87,
                          size: 40,
                        ),
                      ),
                    ),
                    Image(
                      image: const AssetImage("../assets/images/logo.png"),
                      height: 40,
                      width: screenWidth * 0.25,
                    ),
                    Padding(
                      padding: EdgeInsets.only(right: screenWidth * 0.02),
                      child: SearchWidget(
                        width: screenWidth * 0.33,
                        onChanged: (p0) {},
                        searchController: _searchBoxController,
                        onTap: () {},
                        hintText: _hintText,
                      ),
                    ),
                    Padding(
                      padding: EdgeInsets.only(right: screenWidth * 0.02),
                      child: InkWell(
                        onTap: () {},
                        child: const Icon(
                          Icons.favorite_outline_rounded,
                          color: Colors.black87,
                          size: 40,
                        ),
                      ),
                    ),
                    Padding(
                      padding: EdgeInsets.only(right: screenWidth * 0.02),
                      child: InkWell(
                        onTap: () {},
                        child: const Icon(
                          Icons.shopping_cart_outlined,
                          color: Colors.black87,
                          size: 40,
                        ),
                      ),
                    ),
                  ],
                ),
                Padding(padding: EdgeInsets.only(top: screenHeight * 0.01)),
                Stack(
                  children: [
                    CarouselSlider(
                      items: carouselImageList.map<Widget>((i) {
                        return Builder(
                          builder: (BuildContext context) {
                            return Container(
                              width: screenWidth * 0.95,
                              decoration: BoxDecoration(
                                image: DecorationImage(image: NetworkImage(i)),
                              ),
                            );
                          },
                        );
                      }).toList(),
                      options: CarouselOptions(
                          height: screenHeight * 0.25,
                          aspectRatio: 16 / 9,
                          autoPlay: true,
                          autoPlayInterval: const Duration(seconds: 5),
                          initialPage: 0,
                          viewportFraction: 1,
                          onPageChanged: (index, timed) {
                            setState(() {
                              _currentCarouselIndex = index;
                            });
                          }),
                    ),
                    Positioned(
                      //bottom: screenHeight * 0.01,
                      child: Row(
                        mainAxisAlignment: MainAxisAlignment.center,
                        children: indicators(
                            carouselImageList.length, _currentCarouselIndex),
                      ),
                    ),
                  ],
                ),
                //Padding(padding: EdgeInsets.only(top: screenHeight * 0.01)),
              ],
            ),
          ),
          Positioned(
            top: screenHeight * 0.35,
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Padding(
                  padding: EdgeInsets.only(left: screenWidth * 0.025),
                  child: HomeWelcomeScreenLabel(
                    screenWidth: screenWidth,
                    labelText: "Top Brands",
                  ),
                ),
                Padding(
                  padding: EdgeInsets.only(
                      top: screenHeight * 0.01, left: screenWidth * 0.025),
                  child: SizedBox(
                    height: screenHeight * 0.09,
                    //width: screenWidth * 0.33 * brandLogos.length,
                    child: ListView.builder(
                        itemCount: brandLogos.length,
                        scrollDirection: Axis.horizontal,
                        shrinkWrap: true,
                        physics: const AlwaysScrollableScrollPhysics(),
                        itemBuilder: (BuildContext context, int index) {
                          return BrandLogoCard(
                            width: screenWidth * 0.25,
                            //height: screenHeight * 0.0,
                            brandImageUrl: brandLogos[index]["img-url"],
                            paddingRight: screenWidth * 0.01,
                          );
                        }),
                  ),
                ),
              ],
            ),
          ),
          Positioned(
            bottom: screenHeight * 0.01,
            child: Padding(
              padding: EdgeInsets.only(left: screenWidth * 0.02),
              child: SizedBox(
                width: screenWidth * 0.96,
                child: CustomAnimatedBottomBar(
                    containerHeight: 56,
                    backgroundColor: Colors.black87,
                    selectedIndex: _currentIndex,
                    showElevation: true,
                    itemCornerRadius: 50,
                    curve: Curves.easeIn,
                    items: navBarItems,
                    onItemSelected: (index) {
                      setState(() {
                        _currentIndex = index;
                      });
                    }),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

class HomeWelcomeScreenLabel extends StatelessWidget {
  const HomeWelcomeScreenLabel({
    Key? key,
    required this.screenWidth,
    required this.labelText,
  }) : super(key: key);

  final double? screenWidth;
  final String labelText;

  @override
  Widget build(BuildContext context) {
    return Container(
      width: screenWidth! * 0.15,
      decoration: const BoxDecoration(
        color: Colors.black,
        borderRadius: BorderRadius.all(
          Radius.circular(10),
        ),
      ),
      child: Padding(
        padding: const EdgeInsets.all(8.0),
        child: Text(
          labelText,
          style: globalTextStyle.copyWith(
            color: Colors.white,
            fontSize: 12,
            fontWeight: FontWeight.bold,
            //backgroundColor: Colors.black,
          ),
        ),
      ),
    );
  }
}

brand_logo_card.dart

import 'package:flutter/material.dart';

class BrandLogoCard extends StatelessWidget {
  final double width;
  final double? height;
  final String brandImageUrl;
  final double paddingRight;
  const BrandLogoCard({
    Key? key,
    required this.width,
    this.height,
    required this.brandImageUrl,
    required this.paddingRight,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Material(
      child: Padding(
        padding: EdgeInsets.only(right: paddingRight),
        child: Container(
          width: width,
          height: height,
          decoration: BoxDecoration(
            image: DecorationImage(
              image: NetworkImage(brandImageUrl),
              fit: BoxFit.contain,
            ),
            border: Border.all(),
          ),
        ),
      ),
    );
  }
}

App screenshot:

enter image description here

How can I implement a horizontal scroll for my brand logos list?

CodePudding user response:

To fix the ListView scroll you can add a width to the SizedBox like

Padding(
                  padding: EdgeInsets.only(
                      top: screenHeight * 0.01, left: screenWidth * 0.025),
                  child: SizedBox(
                    height: screenHeight * 0.09,
                    width: screenWidth - (screenWidth * 0.02), //<--here
                    child: ListView.builder(
                        itemCount: brandLogos.length,
                        scrollDirection: Axis.horizontal,
                        shrinkWrap: true,
                        physics: const AlwaysScrollableScrollPhysics(),
                        itemBuilder: (BuildContext context, int index) {
                          return BrandLogoCard(
                            width: screenWidth * 0.25,
                            //height: screenHeight * 0.0,
                            brandImageUrl: brandLogos[index]["img-url"],
                            paddingRight: screenWidth * 0.01,
                          );
                        }),
                  ),
                ),

Also just a suggestion. You can create the same UI using this layout

Scaffold(
 body: Column(
  children: [
   Carousel(),//carousel here
   Row(
    mainAxisAlignment : MainAxisAlignment.center,
   children:[
      //carouselIndicatorsHere
    ]
   ),
   ListView.builder(
     scrollDirection: Axis.horizontal,
     itemBuilder: (BuildContext context, int index) {
         return BrandLogoCard(
           width: screenWidth * 0.25,
           //height: screenHeight * 0.0,
             brandImageUrl: brandLogos[index]["img-url"],
             paddingRight: screenWidth * 0.01,
              );
          }),
   )
  ]
 )
)
  • Related