Search code examples
flutterflutter-layout

Place button on top of joining lines of two containers


I am new to the flutter world. For learning purposes, I am trying to create a dummy app and while doing so I came across a design and I am wondering how can I achieve this by making my design responsive across devices?

enter image description here


Solution

  • You can use Column with Flexible to set ratios between two Container(Blue and White in your example).

    Put the button between containers and use Transform.translate to offset it for half it's height in a negative direction. This will put it on top of the blue Conainer.

    Working example

    import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) => MaterialApp(home: MyPage());
    }
    
    class MyPage extends StatefulWidget {
      @override
      _MyPageState createState() => _MyPageState();
    }
    
    class _MyPageState extends State<MyPage> with WidgetsBindingObserver {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: SafeArea(
            child: _buildColumn(),
          ),
        );
      }
    
      Widget _buildColumn() => Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: [
              // First blue container
              _buildTopContainer(),
              // Button with offset
              _buildMidContainerWithButton(),
              // Bottom white container
              _buildBottomContainer(),
            ],
          );
    
      Widget _buildTopContainer() => Flexible(
            flex: 10,
            child: Container(
              color: Colors.blue[900],
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Text(
                    'Top container',
                    style: TextStyle(
                      fontSize: 17.0,
                      fontWeight: FontWeight.w600,
                      color: Colors.white,
                    ),
                  ),
                ],
              ),
            ),
          );
    
      Widget _buildMidContainerWithButton() {
        final buttonHeight = 50.0;
        return Stack(
          children: [
            // Use same background color like the second container
            Container(height: buttonHeight, color: Colors.white),
            // Translate the button 
            Transform.translate(
              offset: Offset(0.0, -buttonHeight / 2.0),
              child: Center(
                child: GestureDetector(
                  onTap: () { /* do stuff */ },
                  child: Container(
                    height: buttonHeight,
                    decoration: BoxDecoration(
                      color: Colors.orange[400],
                      borderRadius: BorderRadius.circular(buttonHeight / 2.0),
                      boxShadow: [
                        BoxShadow(
                          blurRadius: 16.0,
                          offset: Offset(0.0, 6.0),
                          color: Colors.black.withOpacity(0.16),
                        ),
                      ],
                    ),
                    padding: const EdgeInsets.fromLTRB(24.0, 3.0, 24.0, 0.0),
                    child: Row(
                      mainAxisSize: MainAxisSize.min,
                      children: [
                        Icon(
                          Icons.photo_camera_outlined,
                          size: 20.0,
                          color: Colors.white,
                        ),
                        Padding(
                          padding: const EdgeInsets.only(left: 8.0),
                          child: Text(
                            'Use camera',
                            style: TextStyle(
                              fontSize: 17.0,
                              fontWeight: FontWeight.w600,
                              color: Colors.white,
                            ),
                          ),
                        ),
                      ],
                    ),
                  ),
                ),
              ),
            ),
          ],
        );
      }
    
      Widget _buildBottomContainer() => Flexible(
            flex: 5,
            child: Container(
              color: Colors.white,
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                Text(
                  'Bottom container',
                  style: TextStyle(
                    fontSize: 17.0,
                    fontWeight: FontWeight.w600,
                    color: Colors.black54,
                  ),
                ),
              ]),
            ),
          );
    }
    

    Result

    enter image description here