Search code examples
flutterdartflutter-web

how to use multi scroll in one screen -Flutter


I want to create an web ui in flutter like trello in that I want one horizontal primary scroll and one vertical secondary scroll but I am not able to scroll vertically in column I attach what I want to create and my code and if you still not understand please let me know

enter image description here

Here is my code :-


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

  // Use this for set width of card and row in list
  final double cardWidth = 180.0;
  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        Expanded(child: _getSideMenu()),
        Container(
          height: Get.height,
          width: 1,
          color: scrollBarColor,
        ),
        Expanded(
          child: _getMainScreen(),
          flex: 6,
        ),
      ],
    );
  }

  Widget _getMainScreen() {
    return SingleChildScrollView(
      scrollDirection: Axis.horizontal,
      child: ListView.builder(
          itemCount: 4,
          shrinkWrap: true,
          physics: NeverScrollableScrollPhysics(),
          scrollDirection: Axis.horizontal,
          padding: EdgeInsets.zero,
          itemBuilder: (context, i) {
            return Row(
              children: [
                Column(
                  mainAxisAlignment: MainAxisAlignment.start,
                  children: [
                    SizedBox(
                      width: cardWidth,
                      child: Row(
                        children: [
                          (10.0).addWSpace(),
                          "29".h3(
                              size: 25,
                              weight: FontWeight.w700,
                              color: GrayColor),
                          (5.0).addWSpace(),
                          Expanded(
                              child: "Sun".h3(
                                  color: GrayColor,
                                  weight: FontWeight.w400,
                                  size: 15)),
                          (10.0).addWSpace(),
                        ],
                      ),
                    ),
                    Container(
                      color: scrollBarColor,
                      height: 1,
                      width: cardWidth,
                    ),
                    SizedBox(
                      width: cardWidth,
                      child: Row(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          SingleChildScrollView(
                            primary: false,
                            child: Column(
                              mainAxisAlignment: MainAxisAlignment.start,
                              children: [
                                PlaningWeekCard(
                                  device: Device.Web,
                                  onTap: () {},
                                  width: cardWidth,
                                ),
                                PlaningWeekCard(
                                  device: Device.Web,
                                  onTap: () {},
                                  width: cardWidth,
                                ),
                                PlaningWeekCard(
                                  device: Device.Web,
                                  onTap: () {},
                                  width: cardWidth,
                                ),
                                PlaningWeekCard(
                                  device: Device.Web,
                                  onTap: () {},
                                  width: cardWidth,
                                ),
                                PlaningWeekCard(
                                  device: Device.Web,
                                  onTap: () {},
                                  width: cardWidth,
                                ),
                                PlaningWeekCard(
                                  device: Device.Web,
                                  onTap: () {},
                                  width: cardWidth,
                                ),
                              ],
                            ),
                          ),
                          Container(
                            height: Get.height,
                            width: 1,
                            color: scrollBarColor,
                          ),
                        ],
                      ),
                    ),
                  ],
                ),
              ],
            );
          }),
    );
  }

  Widget _getSideMenu() {
    return Container(
      height: Get.height,
      // width: 220,
      child: SingleChildScrollView(
        padding: EdgeInsets.zero,
        child: Column(
          mainAxisAlignment: MainAxisAlignment.start,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            "Employers".h3(weight: FontWeight.w700, size: 22),
            (10.0).addHSpace(),
            PerytonSearchField(
              hintText: 'Name',
            ),
            (10.0).addHSpace(),
            ExpansionTile(
              title: Row(
                children: [
                  PerytonCheckBox(val: false),
                  (5.0).addWSpace(),
                  Expanded(child: "Codonnier Offieces".expansionTileTittleWeb())
                ],
              ),
              children: [
                _getRow("Norway office"),
                _getRow("Surat office"),
                _getRow("Bardoli office"),
                _getRow("Usa office"),
              ],
            ),
            (10.0).addHSpace(),
            ExpansionTile(
              title: Row(
                children: [
                  PerytonCheckBox(val: false),
                  (5.0).addWSpace(),
                  Expanded(child: "Codonnier Branches".expansionTileTittleWeb())
                ],
              ),
              children: [
                _getRow("Amsterdam office"),
                _getRow("Surat office"),
                _getRow("Suart-6 office"),
                _getRow("california office"),
              ],
            ),
            (10.0).addHSpace(),
            ExpansionTile(
              title: Row(
                children: [
                  PerytonCheckBox(val: false),
                  (5.0).addWSpace(),
                  Expanded(
                      child: "Codonnier sub branches".expansionTileTittleWeb())
                ],
              ),
              children: [
                _getRow("van gogh branch"),
                _getRow("Mota varacha branch"),
                _getRow("vesu branch"),
                _getRow("san francisco office"),
              ],
            ),
            (10.0).addHSpace(),
            "Workers".h3(weight: FontWeight.w700, size: 22),
            (10.0).addHSpace(),
            PerytonSearchField(
              hintText: 'Name',
            ),
            (10.0).addHSpace(),
            _getRow("Harsh codonnier"),
            (10.0).addHSpace(),
            _getRow("Dipak codonnier"),
            (10.0).addHSpace(),
            _getRow("Subham codonnier"),
            (10.0).addHSpace(),
            _getRow("ravi codonnier"),
            (10.0).addHSpace(),
          ],
        ).pSymmetricOnly(horizontal: 10),
      ),
    );
  }

  Widget _getRow(String name) {
    return Row(
      children: [
        PerytonCheckBox(val: false),
        (5.0).addWSpace(),
        Expanded(child: name.expansionTileWeb())
      ],
    );
  }
}


Here is my card widget:-

class PlaningDayCard extends StatelessWidget {
  PlaningDayCard(
      {Key? key,
      required this.device,
      required this.onTap,
      required this.width})
      : super(key: key);
  final Device device;
  final double width;
  final Function onTap;
  @override
  Widget build(BuildContext context) {
    return ResponsiveWidget(
        mobile: _getMobileCard(),
        tablet: _getWebCard(),
        desktop: _getWebCard(),
        device: device);
  }

  Widget _getWebCard() {
    return SizedBox(
      width: width - 2,
      child: Card(
          color: Colors.white,
          shape: RoundedRectangleBorder(
            side: BorderSide(color: Colors.white, width: 0.0),
            borderRadius: BorderRadius.circular(15),
          ),
          child: Material(
            borderRadius: BorderRadius.circular(15),
            clipBehavior: Clip.antiAlias,
            color: Colors.transparent,
            child: InkWell(
              onTap: () {
                onTap.call();
              },
              child: Column(
                mainAxisAlignment: MainAxisAlignment.start,
                children: [
                  Row(
                    children: [
                      Expanded(
                        child: "Scrubbing sinks, tubs, showers"
                            .h2(weight: FontWeight.w700, size: 15),
                      ),
                    ],
                  ),
                  (6.0).addHSpace(),
                  Row(
                    children: [
                      ImageAssetIconWithColor(
                        color: GrayColor,
                        size: 15,
                        image: ImageIcons.icTriangle,
                      ),
                      (8.0).addWSpace(),
                      Expanded(
                        child: "Main Office".h2(
                            weight: FontWeight.w500,
                            color: GrayColor,
                            size: 14),
                      ),
                    ],
                  ),
                  (8.0).addWSpace(),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.end,
                    children: [
                      "09:00—13:00".h2(
                          weight: FontWeight.w700, color: GrayColor, size: 13),
                    ],
                  )
                ],
              ).pSymmetricOnly(vertical: 5, horizontal: 6),
            ),
          )),
    );
  }

  Widget _getMobileCard() {
    return SizedBox(
      width: width - 2,
      child: Card(
          color: Colors.white,
          shape: RoundedRectangleBorder(
            side: BorderSide(color: Colors.white, width: 0.0),
            borderRadius: BorderRadius.circular(15.sp),
          ),
          child: Material(
            borderRadius: BorderRadius.circular(15.sp),
            clipBehavior: Clip.antiAlias,
            color: Colors.transparent,
            child: InkWell(
              onTap: () {
                onTap.call();
              },
              child: Column(
                children: [],
              ),
            ),
          )),
    );
  }
}

Solution

  • enter image description here

    Complete Tested Code

    import 'dart:math';
    import 'package:flutter/gestures.dart';
    import 'package:flutter/material.dart';
    
    class TrelloExample extends StatefulWidget {
      const TrelloExample({Key? key}) : super(key: key);
    
      @override
      State<TrelloExample> createState() => _TrelloExampleState();
    }
    
    class _TrelloExampleState extends State<TrelloExample> {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          backgroundColor: Colors.white,
          body: Padding(
            padding: const EdgeInsets.only(top: 64.0),
            child: ScrollConfiguration(
               behavior: ScrollConfiguration.of(context).copyWith(
                dragDevices: {
                  PointerDeviceKind.touch,
                  PointerDeviceKind.mouse,
                },
              ),
              child: SingleChildScrollView(
                physics: const ClampingScrollPhysics(),
                scrollDirection: Axis.horizontal,
                child: Row(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: List.generate(
                    16,
                    (index) => SingleChildScrollView(
                      physics: const ClampingScrollPhysics(),
                      child: Padding(
                        padding: EdgeInsets.only(
                            right: 16.0, left: index == 0 ? 16.0 : 0.0),
                        child: Column(
                          children: List.generate(
                            index % 2 == 1
                                ? 16
                                : index % 3 == 1
                                    ? 8
                                    : index % 1 == 1
                                        ? 4
                                        : 6,
                            (index) => Padding(
                              padding: const EdgeInsets.only(bottom: 16.0),
                              child: Material(
                                elevation: 4.0,
                                child: Container(
                                  padding: const EdgeInsets.all(38.0),
                                  color: Color(
                                          (Random().nextDouble() * 0xFFFFFF).toInt())
                                      .withOpacity(1.0),
                                  child: Text(
                                    "Trello Ticket Item $index",
                                    style: const TextStyle(
                                      fontSize: 16.0,
                                      color: Colors.black,
                                      fontWeight: FontWeight.bold,
                                    ),
                                  ),
                                ),
                              ),
                            ),
                          ),
                        ),
                      ),
                    ),
                  ),
                ),
              ),
            ),
          ),
        );
      }
    }