flutterdartlistviewrotationflutter-row

Flutter remove white space in ListView


I want to make a cover for the cover of movies, which includes two rows, the first row rotates from right to left and the second row rotates from left to right. I also gave them an angle

But there is a series of white spaces around them and the list views do not expand How to remove that white space?

enter image description here

Here is my code:


class _CinemaTopBannerState extends State<CinemaTopBanner> {
  late ScrollController _scrollControllerLeftToRight;
  late ScrollController _scrollControllerRightToLeft;

  @override
  void initState() {
    super.initState();
    _scrollControllerLeftToRight = ScrollController();
    _scrollControllerRightToLeft = ScrollController();

    // Start auto-scrolling for the first row (left to right)
    Timer.periodic(Duration(milliseconds: 30), (timer) {
      if (_scrollControllerLeftToRight.hasClients) {
        double newOffset = _scrollControllerLeftToRight.offset + 1;

        if (newOffset < _scrollControllerLeftToRight.position.maxScrollExtent) {
          _scrollControllerLeftToRight.animateTo(
            newOffset,
            duration: Duration(milliseconds: 30),
            curve: Curves.linear,
          );
        } else {
          // Reset the position if the end is reached
          _scrollControllerLeftToRight.jumpTo(0.0);
        }
      }
    });

    // Start auto-scrolling for the second row (right to left)
    Timer.periodic(Duration(milliseconds: 30), (timer) {
      if (_scrollControllerRightToLeft.hasClients) {
        double newOffset = _scrollControllerRightToLeft.offset - 1;

        if (newOffset > 0) {
          _scrollControllerRightToLeft.animateTo(
            newOffset,
            duration: Duration(milliseconds: 30),
            curve: Curves.linear,
          );
        } else {
          // Reset the position if the start is reached
          _scrollControllerRightToLeft.jumpTo(_scrollControllerRightToLeft.position.maxScrollExtent);
        }
      }
    });
  }

  @override
  void dispose() {
    _scrollControllerLeftToRight.dispose();
    _scrollControllerRightToLeft.dispose();
    super.dispose();
  }

  List<String> movieCovers = [
    "https://m.media-amazon.com/images/I/71eHZFw+GlL._AC_UF894,1000_QL80_.jpg",
   ...
  ];

  @override
  Widget build(BuildContext context) {
    return Stack(
      alignment: Alignment.center,
      children: [
        SingleChildScrollView(
          padding: EdgeInsets.zero,
          physics: const NeverScrollableScrollPhysics(),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.start,
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              SizedBox(
                height: 300,
                child: RotationTransition(
                  turns: const AlwaysStoppedAnimation(-29 / 360),
                  child: ListView.builder(
                    padding: EdgeInsets.zero,
                    scrollDirection: Axis.horizontal,
                    controller: _scrollControllerRightToLeft,
                    shrinkWrap: true,
                    itemCount: movieCovers.length,
                    reverse: true,
                    itemBuilder: (context, index) => _buildMovieCover(movieCovers[index]),
                  ),
                ),
              ),
              SizedBox(
                height: 50.w,
              ),
              SizedBox(
                height: 300,
                child: RotationTransition(
                  turns: const AlwaysStoppedAnimation(-29 / 360),
                  child: ListView.builder(
                    padding: EdgeInsets.zero,
                    scrollDirection: Axis.horizontal,
                    shrinkWrap: true,
                    controller: _scrollControllerLeftToRight,
                    reverse: true,
                    itemCount: movieCovers.length,
                    itemBuilder: (context, index) => _buildMovieCover(movieCovers[index]),
                  ),
                ),
              ),
            ],
          ),
        ),
        Container(
          width: 390.w,
          height: 810.w,
          decoration: BoxDecoration(
            gradient: LinearGradient(
              begin: Alignment(0.00, -1.00),
              end: Alignment(0, 1),
              colors: [Colors.white, Colors.white.withOpacity(0), Colors.white],
            ),
          ),
        ),
        SizedBox(
          width: 265.w,
          child: Column(
            mainAxisAlignment: MainAxisAlignment.end,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [
              Text(
                Env.cinemaTitle,
                style: AppTextTheme.tvWidgetsTitleBanner,
              ),
              SizedBox(
                height: 8.w,
              ),
              Text(Env.cinemaTitleDescription, style: AppTextTheme.avaTvCinemaCartsDescription),
            ],
          ),
        )
      ],
    );
  }

  Widget _buildMovieCover(String coverPath) {
    return Padding(
      padding: const EdgeInsets.symmetric(horizontal: 8.0),
      child: ClipRRect(
        borderRadius: BorderRadius.circular(12),
        child: CachedNetworkImage(
          imageUrl: coverPath,
          width: 213.w,
          height: 316.w,
          fit: BoxFit.fill,
        ),
      ),
    );
  }
}

enter image description here


Solution

  • Try This!

    Output:

    enter image description here

    Code:

    class CinemaTopBanner extends StatefulWidget {
      const CinemaTopBanner({super.key});
    
      @override
      State<CinemaTopBanner> createState() => _CinemaTopBannerState();
    }
    
    class _CinemaTopBannerState extends State<CinemaTopBanner> {
       final ScrollController _scrollControllerLeftToRight = ScrollController();
       final ScrollController _scrollControllerRightToLeft = ScrollController();
    
      @override
      void initState() {
        super.initState();
    
        // Start auto-scrolling for the first row (left to right)
        Timer.periodic(const Duration(milliseconds: 30), (timer) {
          if (_scrollControllerLeftToRight.hasClients) {
            double newOffset = _scrollControllerLeftToRight.offset + 1;
    
            if (newOffset < _scrollControllerLeftToRight.position.maxScrollExtent) {
              _scrollControllerLeftToRight.animateTo(
                newOffset,
                duration: const Duration(milliseconds: 30),
                curve: Curves.linear,
              );
            } else {
              // Reset the position if the end is reached
              _scrollControllerLeftToRight.jumpTo(0.0);
            }
          }
        });
    
        // Start auto-scrolling for the second row (right to left)
        Timer.periodic(const Duration(milliseconds: 30), (timer) {
          if (_scrollControllerRightToLeft.hasClients) {
            double newOffset = _scrollControllerRightToLeft.offset - 1;
    
            if (newOffset > 0) {
              _scrollControllerRightToLeft.animateTo(
                newOffset,
                duration: const Duration(milliseconds: 30),
                curve: Curves.linear,
              );
            } else {
              _scrollControllerRightToLeft
                  .jumpTo(_scrollControllerRightToLeft.position.maxScrollExtent);
            }
          }
        });
      }
    
      @override
      void dispose() {
        _scrollControllerLeftToRight.dispose();
        _scrollControllerRightToLeft.dispose();
        super.dispose();
      }
    
      List<String> movieCovers = [
        "https://m.media-amazon.com/images/I/71eHZFw+GlL._AC_UF894,1000_QL80_.jpg",
        'https://i.pravatar.cc/150?img=1',
        'https://i.pravatar.cc/150?img=2',
        'https://i.pravatar.cc/150?img=3',
        'https://i.pravatar.cc/150?img=4',
        'https://i.pravatar.cc/150?img=5',
        'https://i.pravatar.cc/150?img=6',
        'https://i.pravatar.cc/150?img=7',
        'https://i.pravatar.cc/150?img=8',
        'https://i.pravatar.cc/150?img=9',
      ];
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Stack(
            alignment: Alignment.center,
            fit: StackFit.expand,
            children: [
              Column(
                mainAxisAlignment: MainAxisAlignment.start,
                crossAxisAlignment: CrossAxisAlignment.start,
                mainAxisSize: MainAxisSize.max,
                children: [
                  Expanded(
                    child: Center(
                      child: OverflowBox(
                        minWidth: 300,
                        maxHeight: 300,
                        maxWidth: MediaQuery.of(context).size.width * 2,
                        child: RotationTransition(
                          alignment: Alignment.bottomRight,
                          turns: const AlwaysStoppedAnimation(-29 / 360),
                          child: ListView.builder(
                            padding: EdgeInsets.zero,
                            scrollDirection: Axis.horizontal,
                            controller: _scrollControllerRightToLeft,
                            shrinkWrap: true,
                            itemCount: movieCovers.length,
                            reverse: true,
                            itemBuilder: (context, index) =>
                                _buildMovieCover(movieCovers[index]),
                          ),
                        ),
                      ),
                    ),
                  ),
                  SizedBox(
                    height: 230.w,
                  ),
                  Expanded(
                    child: Center(
                      child: OverflowBox(
                        minWidth: 300,
                        maxHeight: 300,
                        maxWidth: MediaQuery.of(context).size.width * 2,
                        child: RotationTransition(
                          turns: const AlwaysStoppedAnimation(-29 / 360),
                          child: ListView.builder(
                            padding: EdgeInsets.zero,
                            scrollDirection: Axis.horizontal,
                            shrinkWrap: true,
                            controller: _scrollControllerLeftToRight,
                            reverse: true,
                            itemCount: movieCovers.length,
                            itemBuilder: (context, index) =>
                                _buildMovieCover(movieCovers[index]),
                          ),
                        ),
                      ),
                    ),
                  ),
                ],
              ),
              Container(
                width: 390.w,
                height: 810.w,
                decoration: BoxDecoration(
                  gradient: LinearGradient(
                    begin: const Alignment(0.00, -1.00),
                    end: const Alignment(0, 1),
                    colors: [
                      Colors.white,
                      Colors.white.withOpacity(0),
                      Colors.white
                    ],
                  ),
                ),
              ),
              SizedBox(
                width: 265.w,
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.end,
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: [
                    const Text(
                      'Env.cinemaTitle',
                      // style: AppTextTheme.tvWidgetsTitleBanner,
                    ),
                    SizedBox(
                      height: 8.w,
                    ),
                    const Text(
                      'Env.cinemaTitleDescription',
                      //  style: AppTextTheme.avaTvCinemaCartsDescription,
                    ),
                  ],
                ),
              )
            ],
          ),
        );
      }
    
      Widget _buildMovieCover(String coverPath) {
        return Padding(
          padding: const EdgeInsets.symmetric(horizontal: 8.0),
          child: ClipRRect(
            borderRadius: BorderRadius.circular(12),
            child: CachedNetworkImage(
              imageUrl: coverPath,
              width: 213.w,
              height: 316.w,
              fit: BoxFit.fill,
            ),
          ),
        );
      }