skip to Main Content

My aim is to postion a text centrally on top of a picture by using a Stack widget. I want that the text stays in the middle independet of how the window is resized.
Based on my research should the solution be a the following structure:

  • Stack Widget
  • Impage Widget
  • Layout Builder
  • Text Widget

However when trying this my Text sticks to the top left corner. So i create a simpler version of the code and am still unable to reach the desired outcome. My current thinking is that maybe my Layoutbuilder does not correctly receive the size input of the window.

My example code is as follows

main.dart

import 'package:flutter/material.dart';
import 'package:imdb/screens/home_screen.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
       home: HomeScreen());
  }
}

home_screen.dart

import 'package:flutter/material.dart';

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        backgroundColor: Color(0xfff3f3f3),
        body: Stack(
          children: [
            Container(
              height: 200,
              width: 200,
              color: Colors.red,
            ),
 
            LayoutBuilder(builder: (context, constraints) {
              return Positioned(
                left: constraints.maxWidth * 0.5,
                top: constraints.maxHeight*0.5,
                child: Container(
                  height: 10,
                  width: 10,
                  color: Colors.yellowAccent
                ),
              );
            }),
          ],
        ));
  }
}

As output I would expect that the yellow container is placed centrally on the Red box. However the output looks as follows:

Screenshot of output

3

Answers


  1. If you just want to center something, you can use the Center widget – no need to use LayoutBuilder.

    So your code would look something like this:

    Stack:
    [
      Image,
      Center:
        Text,
    ]
    

    This way, your stack will match the size of your image, and the Text widget will be centered in the image.


    Edit: Apparently the question wants to do more than just center. In that case, use Align widget instead. For the alignment property, you can pass in Alignment(0, 0) for center, or values between [-1.0, +1.0] for both x and y offsets. For example, "far-left" would be Alignment (-1.0, 0).

    Login or Signup to reply.
  2. I would suggest directly setting alignment on Stack if you need to use a stack (you could just add the overlapping element as a child):

    Scaffold(
              body: Container(
                color: Colors.blue,
                child: Stack(alignment: Alignment.center, children: [
                  Container(
                    color: Colors.red,
                  ),
                  Container(
                    height: 10,
                    width: 10,
                    color: Colors.yellow,
                  ),
                ],
               ),
              ),
            );
    

    Stacks that are not explicitly sized (via SizedBox, for example) will be the size of their largest child, unless they have constraints placed upon them ("Size goes up, constraints go down").

    To answer your question though, Stacks must have positioned elements as direct children.

    Edit: To address your comment, you can use an alignment offset from 0,0:

    Scaffold(
              body: SizedBox(
                height: 200,
                width: 200,
                child: Stack(children: [
                  Container(     
                    color: Colors.red,
                  ),
                  Align(
                    alignment: Alignment(0,0.5),
                    child: Container(
                      height: 20,
                      width: 20,
                      color: Colors.yellow,
                    ),
                  ),
                ]),
              ),
            );
    

    If you don’t need to use a stack, you could set the yellow box as a child of your parent container, and use alignment on the parent container:

    Scaffold(
              body: Container(
                color: Colors.red,
                height: 200,
                width: 200,
                alignment: const Alignment(0.5, 0.5),
                child: Container(
                    height: 20,
                    width: 20,
                    color: Colors.yellow,
                  ),
              ),
            );
    

    Align uses a fractional offset. If you want to use an absolute offset, you can wrap the child in padding or use Transform.translate. The only thing to keep in mind with Transforms is that difficult bugs can arise when it comes to pointer events (hit boxes are transformed somewhat unexpectedly)

    Scaffold(
              body: Container(
                color: Colors.red,
                height: 200,
                width: 200,
                alignment: Alignment.center,
                child:  Transform.translate(
                      offset: const Offset(50, 10),
                      child: Container(
                        height: 20,
                        width: 20,
                        color: Colors.yellow,
                      ),
                    ),
                 ),
              
            );
    
    Login or Signup to reply.
    • As long as the position of the y-axis is the same, the x-axis can be adjusted freely

    • this is example

    import 'package:flutter/material.dart';
    
    class MyWidget extends StatefulWidget {
      const MyWidget({super.key});
    
      @override
      State<MyWidget> createState() => _MyWidgetState();
    }
    
    class _MyWidgetState extends State<MyWidget> {
      var _switch = ValueNotifier<bool>(false);
      @override
      void initState() {
        super.initState();
      }
    
      @override
      void dispose() {
        _switch.dispose();
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        var screenWidth = MediaQuery.of(context).size.width;
        var screenHeight = MediaQuery.of(context).size.height;
        var bgBoxHeight = screenHeight * .5;
        var bgBoxWidth = screenWidth * .5;
        var secendBoxHeight = bgBoxHeight * .2;
        var secendBoxWidth = bgBoxWidth * .2;
        // Just need to adjust the left and right offset
           var xAxisStartPosition = ((bgBoxWidth / 2) - secendBoxWidth / 2) * .3;
        var yAxisStartPosition = (bgBoxHeight / 2) - secendBoxHeight / 2;
        var rightPading = bgBoxWidth * .1;
        var bottomPading = bgBoxHeight * .1;
        return Scaffold(
            backgroundColor: Color(0xfff3f3f3),
            body: Stack(
              fit: StackFit.loose,
              children: [
                Container(
                  height: bgBoxHeight,
                  width: bgBoxWidth,
                  color: Colors.red,
                ),
                Positioned(
                  left: xAxisStartPosition,
                  bottom: yAxisStartPosition,
                  child: LayoutBuilder(builder: (context, constraints) {
                    return Container(
                        height: secendBoxHeight,
                        width: secendBoxWidth,
                        color: Colors.yellowAccent);
                  }),
                ),
                Positioned(
                    left: xAxisStartPosition,
                    right: rightPading,
                    // bottom: bottomPading,
                    bottom: yAxisStartPosition,
                    child: ConstrainedBox(
                      constraints: BoxConstraints(
                          maxWidth: bgBoxWidth, maxHeight: bgBoxHeight),
                      child: Text("""Easy to use, stylish placeholders
    Just add your desired image size (width & height) after our URL, and you'll get a random image."""),
                    ))
              ],
            ));
      }
    }
    
    
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search