skip to Main Content

So I was trying to build a user id page for my flutter app where you tap on a container and the containers height is increased and a different set of data is shown. On expanded I also wanted to add a scrollable tabview and that’s second part of the problem.

the expected ui looks like thishttps://i.stack.imgur.com/62sro.gif.

I have tried Expanded and expansion tile, Can’t quite achieve the output
Is there any other method to achieve this?

2

Answers


  1. Welcome @Anand Pillai,

    First add this line to your pubspec.yaml expandable: ^5.0.1

    try this code

    import 'package:expandable/expandable.dart';
    import 'package:flutter/material.dart';
    
    void main() {
      runApp(const MyApp());
    }
    
    class MyApp extends StatelessWidget {
      const MyApp({super.key});
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: const MyHomePage(),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      const MyHomePage({super.key});
    
      @override
      State<MyHomePage> createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      late PageController _pageController;
      final ExpandableController _controller = ExpandableController();
    
      int activePage = 1;
      int _counter = 0;
      List<String> images = [
        "https://images.pexels.com/photos/14686142/pexels-photo-14686142.jpeg",
        "https://wallpaperaccess.com/full/2637581.jpg",
        "https://uhdwallpapers.org/uploads/converted/20/01/14/the-mandalorian-5k-1920x1080_477555-mm-90.jpg"
      ];
    
      List<Widget> indicators(imagesLength, currentIndex) {
        return List<Widget>.generate(imagesLength, (index) {
          return Container(
            margin: const EdgeInsets.all(3),
            width: 10,
            height: 10,
            decoration: BoxDecoration(
                color: currentIndex == index ? Colors.white : Colors.blueGrey,
                shape: BoxShape.circle),
          );
        });
      }
    
      AnimatedContainer slider(images, pagePosition, active) {
        // double margin = active ? 10 : 20;
    
        return AnimatedContainer(
          duration: const Duration(milliseconds: 500),
          curve: Curves.easeInOutCubic,
          // margin: EdgeInsets.all(margin),
          decoration: BoxDecoration(
              image: DecorationImage(
            image: NetworkImage(images[pagePosition]),
            fit: BoxFit.cover,
          )),
        );
      }
    
      @override
      void initState() {
        super.initState();
        _pageController = PageController();
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
            body: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            SizedBox(
              width: MediaQuery.of(context).size.width,
              height: MediaQuery.of(context).size.height,
              child: Stack(
                alignment: Alignment.center,
                children: [imageSlider(), expandedWidget(context)],
              ),
            ),
          ],
        ));
      }
    
      Positioned expandedWidget(BuildContext context) {
        return Positioned.fill(
            bottom: _controller.expanded ? 0 : 60,
            left: 0,
            right: 0,
            child: Column(
              mainAxisAlignment: MainAxisAlignment.end,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: [
                _controller.expanded
                    ? const SizedBox.shrink()
                    : Row(
                        mainAxisAlignment: MainAxisAlignment.center,
                        children: indicators(images.length, activePage)),
                ExpandableNotifier(
                    child: AnimatedContainer(
                  height: _controller.expanded ? 400 : 110.0,
                  width: double.infinity,
                  alignment: Alignment.bottomCenter,
                  padding: const EdgeInsets.all(15.0),
                  margin: _controller.expanded
                      ? EdgeInsets.zero
                      : const EdgeInsets.all(8.0),
                  decoration: BoxDecoration(
                    color: const Color.fromARGB(255, 255, 79, 77).withOpacity(0.8),
                    borderRadius: _controller.expanded
                        ? const BorderRadius.only(
                            topRight: Radius.circular(15),
                            topLeft: Radius.circular(15),
                          )
                        : BorderRadius.circular(15.0),
                  ),
                  duration: const Duration(milliseconds: 500),
                  child: Column(
                    children: <Widget>[
                      ScrollOnExpand(
                        scrollOnExpand: true,
                        scrollOnCollapse: false,
                        child: ExpandablePanel(
                          controller: _controller
                            ..addListener(() {
                              setState(() {});
                            }),
                          theme: const ExpandableThemeData(
                            headerAlignment: ExpandablePanelHeaderAlignment.center,
                            tapBodyToCollapse: true,
                            iconColor: Colors.white,
                          ),
                          header: Padding(
                              padding: const EdgeInsets.all(10),
                              child: Text(
                                "ExpandablePanel",
                                style: Theme.of(context)
                                    .textTheme
                                    .bodyText1!
                                    .copyWith(color: Colors.white),
                              )),
                          collapsed: const Text(
                            "loremIpsum",
                            style: TextStyle(color: Colors.white),
                            softWrap: true,
                            maxLines: 2,
                            overflow: TextOverflow.ellipsis,
                          ),
                          expanded: Column(
                            crossAxisAlignment: CrossAxisAlignment.start,
                            children: <Widget>[
                              for (var _ in Iterable.generate(5))
                                const Padding(
                                    padding: EdgeInsets.only(bottom: 10),
                                    child: Text(
                                      "loremIpsum",
                                      style: TextStyle(color: Colors.white),
                                      softWrap: true,
                                      overflow: TextOverflow.fade,
                                    )),
                            ],
                          ),
                          builder: (_, collapsed, expanded) {
                            return Padding(
                              padding: const EdgeInsets.only(
                                  left: 10, right: 10, bottom: 10),
                              child: Expandable(
                                collapsed: collapsed,
                                expanded: expanded,
                                theme: const ExpandableThemeData(crossFadePoint: 0),
                              ),
                            );
                          },
                        ),
                      ),
                    ],
                  ),
                )),
              ],
            ));
      }
    
      PageView imageSlider() {
        return PageView.builder(
            itemCount: images.length,
            physics: _controller.expanded
                ? const NeverScrollableScrollPhysics()
                : ScrollPhysics(),
            padEnds: false,
            controller: _pageController,
            onPageChanged: (page) {
              setState(() {
                activePage = page;
              });
            },
            itemBuilder: (context, pagePosition) {
              bool active = pagePosition == activePage;
              return slider(images, pagePosition, active);
            });
      }
    }
    
    Login or Signup to reply.
  2. class _MyHomePageState extends State<MyHomePage> {
      double _margin = 30, _height = 100, _width = 300;
      
      final Text _widget1 = const Text('This is my Foo');
      final Text _widget2 = const Text('This is Bar');
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text(widget.title),
          ),
          body: Center(
              child: GestureDetector(
            // When the child is tapped, set state is called.
            onTap: () {
              setState(() {
                _margin = _margin == 30 ? 0 : 30;
                _height = _height == 100 ? 300 : 100;
                _width = _width == 300 ? MediaQuery.of(context).size.width : 300;
              });
            },
            // The custom button
            child: Align(
              alignment: Alignment.bottomCenter,
              child: AnimatedContainer(
                width: _width,
                height: _height,
                curve: Curves.easeInExpo,
                margin: EdgeInsets.fromLTRB(_margin, 0, _margin, _margin),
                duration: Duration(milliseconds: 250),
                padding: const EdgeInsets.all(0),
                decoration: BoxDecoration(
                  color: Colors.lightBlue,
                  borderRadius: BorderRadius.circular(8.0),
                ),
                child: _margin == 30 ? _widget1 : _widget2,
              ),
            ),
          )),
        );
      }
    }
    

    Simple logic is to animate the container when tapped and change the widget in it. On tap it calls setsate that sets the height, width, margin and child of the container.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search