Flutter Dart layouts, Stack, Positioned how to stretch matrix of Material Buttons over whole screen

Issue

How can I have matrix of material buttons stretch across whole screen, if I just use height they will stretch to little or out of the screen based on screen size?

I can do that easily just in matrix with height: double.infinity, and CrossAxisAlignment.stretch,.

Though when I add Stack and Positioned widgets to the mix, then screen goes white if I use height: double.infinity,. and I get error: BoxConstraints forces an infinite height.
The relevant error-causing widget was:
MaterialButton file:///Users/janiveble/AndroidStudioProjects/midi_app/lib/main.dart:113:14

Though when I search for this error, I can’t figure out how is it related to my issue.

Also how can I position text on white keys to the botom of key instead of center?

Also I would like to get width of white keys, as I would like to use it to control position and width of black keys based on it.

  Expanded buildWhiteKey({Color color, int soundNumber}) {
    return Expanded(
      child: MaterialButton(
        //height: double.infinity,
        height: 100,
        color: color,
        textColor: Colors.red,
        padding: EdgeInsets.all(1.0),
        onPressed: () {
          //playSound(soundNumber);
          FlutterMidi.playMidiNote(midi: soundNumber);
          setState(() {
            userAnswer = soundNumber;
          });
        },
        child: Text('$soundNumber'),
      ),
    );
  }

  Expanded buildBlackKey({Color color, int soundNumber}) {
    return Expanded(
      child: MaterialButton(
        //height: double.infinity,
        height: 100,
        color: color,
        textColor: Colors.red,
        padding: EdgeInsets.all(1.0),
        onPressed: () {
          //playSound(soundNumber);
          FlutterMidi.playMidiNote(midi: soundNumber);
          setState(() {
            userAnswer = soundNumber;
          });
        },
        child: Text(
          '$soundNumber',
        ),
      ),
    );
  }

@override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        backgroundColor: Colors.white30,
        body: SafeArea(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: [
              Row(
                children: <Widget>[
                  quizKey(color: Colors.green),
                  checkAnswer(color: Colors.red),
                ],
              ),
              Stack(children: <Widget>[
                Row(mainAxisSize: MainAxisSize.min, children: <Widget>[
                  buildWhiteKey(color: Colors.white, soundNumber: 96),
                  buildWhiteKey(color: Colors.white, soundNumber: 98),
                  buildWhiteKey(color: Colors.white, soundNumber: 100),
                  buildWhiteKey(color: Colors.white, soundNumber: 101),
                  buildWhiteKey(color: Colors.white, soundNumber: 103),
                  buildWhiteKey(color: Colors.white, soundNumber: 105),
                  buildWhiteKey(color: Colors.white, soundNumber: 107),
                ]),
                Positioned(
                    left: 0.0,
                    right: 0.0,
                    bottom: 50.0,
                    top: 0.0,
                    child: Row(
                        mainAxisAlignment: MainAxisAlignment.spaceBetween,
                        mainAxisSize: MainAxisSize.min,
                        children: <Widget>[
                          Container(width: keyWidth),
                          buildBlackKey(color: Colors.black, soundNumber: 97),
                          Container(width: keyWidth1),
                          buildBlackKey(color: Colors.black, soundNumber: 99),
                          Container(width: keyWidth2),
                          buildBlackKey(color: Colors.black, soundNumber: 102),
                          Container(width: keyWidth1),
                          buildBlackKey(color: Colors.black, soundNumber: 104),
                          Container(width: keyWidth1),
                          buildBlackKey(color: Colors.black, soundNumber: 106),
                          Container(width: keyWidth),
                        ])),
              ]),
              Stack(children: <Widget>[
                Row(mainAxisSize: MainAxisSize.min, children: <Widget>[
                  buildWhiteKey(color: Colors.white, soundNumber: 84),
                  buildWhiteKey(color: Colors.white, soundNumber: 86),
                  buildWhiteKey(color: Colors.white, soundNumber: 88),
                  buildWhiteKey(color: Colors.white, soundNumber: 89),
                  buildWhiteKey(color: Colors.white, soundNumber: 91),
                  buildWhiteKey(color: Colors.white, soundNumber: 93),
                  buildWhiteKey(color: Colors.white, soundNumber: 95),
                ]),
                Positioned(
                    left: 0.0,
                    right: 0.0,
                    bottom: 50.0,
                    top: 0.0,
                    child: Row(
                        mainAxisAlignment: MainAxisAlignment.spaceBetween,
                        mainAxisSize: MainAxisSize.min,
                        children: <Widget>[
                          Container(width: keyWidth),
                          buildBlackKey(color: Colors.black, soundNumber: 85),
                          Container(width: keyWidth1),
                          buildBlackKey(color: Colors.black, soundNumber: 87),
                          Container(width: keyWidth2),
                          buildBlackKey(color: Colors.black, soundNumber: 90),
                          Container(width: keyWidth1),
                          buildBlackKey(color: Colors.black, soundNumber: 92),
                          Container(width: keyWidth1),
                          buildBlackKey(color: Colors.black, soundNumber: 94),
                          Container(width: keyWidth),
                        ])),
              ]),
              Stack(children: <Widget>[
                Row(mainAxisSize: MainAxisSize.min, children: <Widget>[
                  buildWhiteKey(color: Colors.white, soundNumber: 72),
                  buildWhiteKey(color: Colors.white, soundNumber: 74),
                  buildWhiteKey(color: Colors.white, soundNumber: 76),
                  buildWhiteKey(color: Colors.white, soundNumber: 77),
                  buildWhiteKey(color: Colors.white, soundNumber: 79),
                  buildWhiteKey(color: Colors.white, soundNumber: 81),
                  buildWhiteKey(color: Colors.white, soundNumber: 83),
                ]),
                Positioned(
                    left: 0.0,
                    right: 0.0,
                    bottom: 50.0,
                    top: 0.0,
                    child: Row(
                        mainAxisAlignment: MainAxisAlignment.spaceBetween,
                        mainAxisSize: MainAxisSize.min,
                        children: <Widget>[
                          Container(width: keyWidth),
                          buildBlackKey(color: Colors.black, soundNumber: 73),
                          Container(width: keyWidth1),
                          buildBlackKey(color: Colors.black, soundNumber: 75),
                          Container(width: keyWidth2),
                          buildBlackKey(color: Colors.black, soundNumber: 78),
                          Container(width: keyWidth1),
                          buildBlackKey(color: Colors.black, soundNumber: 80),
                          Container(width: keyWidth1),
                          buildBlackKey(color: Colors.black, soundNumber: 82),
                          Container(width: keyWidth),
                        ])),
              ]),
              Stack(children: <Widget>[
                Row(mainAxisSize: MainAxisSize.min, children: <Widget>[
                  buildWhiteKey(color: Colors.white, soundNumber: 60),
                  buildWhiteKey(color: Colors.white, soundNumber: 62),
                  buildWhiteKey(color: Colors.white, soundNumber: 64),
                  buildWhiteKey(color: Colors.white, soundNumber: 65),
                  buildWhiteKey(color: Colors.white, soundNumber: 67),
                  buildWhiteKey(color: Colors.white, soundNumber: 69),
                  buildWhiteKey(color: Colors.white, soundNumber: 71),
                ]),
                Positioned(
                    left: 0.0,
                    right: 0.0,
                    bottom: 50.0,
                    top: 0.0,
                    child: Row(
                        mainAxisAlignment: MainAxisAlignment.spaceBetween,
                        mainAxisSize: MainAxisSize.min,
                        children: <Widget>[
                          Container(width: keyWidth),
                          buildBlackKey(color: Colors.black, soundNumber: 61),
                          Container(width: keyWidth1),
                          buildBlackKey(color: Colors.black, soundNumber: 63),
                          Container(width: keyWidth2),
                          buildBlackKey(color: Colors.black, soundNumber: 66),
                          Container(width: keyWidth1),
                          buildBlackKey(color: Colors.black, soundNumber: 68),
                          Container(width: keyWidth1),
                          buildBlackKey(color: Colors.black, soundNumber: 70),
                          Container(width: keyWidth),
                        ])),
              ]),
              Stack(children: <Widget>[
                Row(mainAxisSize: MainAxisSize.min, children: <Widget>[
                  buildWhiteKey(color: Colors.white, soundNumber: 48),
                  buildWhiteKey(color: Colors.white, soundNumber: 50),
                  buildWhiteKey(color: Colors.white, soundNumber: 52),
                  buildWhiteKey(color: Colors.white, soundNumber: 53),
                  buildWhiteKey(color: Colors.white, soundNumber: 55),
                  buildWhiteKey(color: Colors.white, soundNumber: 57),
                  buildWhiteKey(color: Colors.white, soundNumber: 59),
                ]),
                Positioned(
                    left: 0.0,
                    right: 0.0,
                    bottom: 50.0,
                    top: 0.0,
                    child: Row(
                        mainAxisAlignment: MainAxisAlignment.spaceBetween,
                        mainAxisSize: MainAxisSize.min,
                        children: <Widget>[
                          Container(width: keyWidth),
                          buildBlackKey(color: Colors.black, soundNumber: 49),
                          Container(width: keyWidth1),
                          buildBlackKey(color: Colors.black, soundNumber: 51),
                          Container(width: keyWidth2),
                          buildBlackKey(color: Colors.black, soundNumber: 54),
                          Container(width: keyWidth1),
                          buildBlackKey(color: Colors.black, soundNumber: 56),
                          Container(width: keyWidth1),
                          buildBlackKey(color: Colors.black, soundNumber: 58),
                          Container(width: keyWidth),
                        ])),
              ]),
              Stack(children: <Widget>[
                Row(mainAxisSize: MainAxisSize.min, children: <Widget>[
                  buildWhiteKey(color: Colors.white, soundNumber: 36),
                  buildWhiteKey(color: Colors.white, soundNumber: 38),
                  buildWhiteKey(color: Colors.white, soundNumber: 40),
                  buildWhiteKey(color: Colors.white, soundNumber: 41),
                  buildWhiteKey(color: Colors.white, soundNumber: 43),
                  buildWhiteKey(color: Colors.white, soundNumber: 45),
                  buildWhiteKey(color: Colors.white, soundNumber: 47),
                ]),
                Positioned(
                    left: 0.0,
                    right: 0.0,
                    bottom: 50.0,
                    top: 0.0,
                    child: Row(
                        mainAxisAlignment: MainAxisAlignment.spaceBetween,
                        mainAxisSize: MainAxisSize.min,
                        children: <Widget>[
                          Container(width: keyWidth),
                          buildBlackKey(color: Colors.black, soundNumber: 37),
                          Container(width: keyWidth1),
                          buildBlackKey(color: Colors.black, soundNumber: 39),
                          Container(width: keyWidth2),
                          buildBlackKey(color: Colors.black, soundNumber: 42),
                          Container(width: keyWidth1),
                          buildBlackKey(color: Colors.black, soundNumber: 44),
                          Container(width: keyWidth1),
                          buildBlackKey(color: Colors.black, soundNumber: 46),
                          Container(width: keyWidth),
                        ])),
              ]),
              Stack(children: <Widget>[
                Row(mainAxisSize: MainAxisSize.min, children: <Widget>[
                  buildWhiteKey(color: Colors.white, soundNumber: 24),
                  buildWhiteKey(color: Colors.white, soundNumber: 26),
                  buildWhiteKey(color: Colors.white, soundNumber: 28),
                  buildWhiteKey(color: Colors.white, soundNumber: 29),
                  buildWhiteKey(color: Colors.white, soundNumber: 31),
                  buildWhiteKey(color: Colors.white, soundNumber: 33),
                  buildWhiteKey(color: Colors.white, soundNumber: 35),
                ]),
                Positioned(
                    left: 0.0,
                    right: 0.0,
                    bottom: 50.0,
                    top: 0.0,
                    child: Row(
                        mainAxisAlignment: MainAxisAlignment.spaceBetween,
                        mainAxisSize: MainAxisSize.min,
                        children: <Widget>[
                          Container(width: keyWidth),
                          buildBlackKey(color: Colors.black, soundNumber: 25),
                          Container(width: keyWidth1),
                          buildBlackKey(color: Colors.black, soundNumber: 27),
                          Container(width: keyWidth2),
                          buildBlackKey(color: Colors.black, soundNumber: 30),
                          Container(width: keyWidth1),
                          buildBlackKey(color: Colors.black, soundNumber: 32),
                          Container(width: keyWidth1),
                          buildBlackKey(color: Colors.black, soundNumber: 34),
                          Container(width: keyWidth),
                        ])),
              ]),
            ],
          ),
        ),
      ),
    );
  }

Solution

Ive solved the issues

for proper button arrangements I’ve had to wrap Stack and Positioned widgets in one Expanded widget in proper place

 @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Column(
        mainAxisSize: MainAxisSize.max,
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          Row(
            children: <Widget>[
              quizKey(color: Colors.green),
              checkAnswer(color: Colors.red),
            ],
          ),
          Expanded(
            child: Stack(children: <Widget>[
              Row(children: <Widget>[
                buildWhiteKey(color: Colors.white, soundNumber: 96),
                buildWhiteKey(color: Colors.white, soundNumber: 98),
                buildWhiteKey(color: Colors.white, soundNumber: 100),
                buildWhiteKey(color: Colors.white, soundNumber: 101),
                buildWhiteKey(color: Colors.white, soundNumber: 103),
                buildWhiteKey(color: Colors.white, soundNumber: 105),
                buildWhiteKey(color: Colors.white, soundNumber: 107),
              ]),
              Positioned(
                  left: 0.0,
                  right: 0.0,
                  bottom: kbottomHeight,
                  top: 0.0,
                  child: Row(children: <Widget>[
                    Container(width: kkeyWidth),
                    buildBlackKey(color: Colors.black, soundNumber: 97),
                    Container(width: kkeyWidth * 0.5),
                    buildBlackKey(color: Colors.black, soundNumber: 99),
                    Container(width: kkeyWidth * 2),
                    buildBlackKey(color: Colors.black, soundNumber: 102),
                    Container(width: kkeyWidth * 0.5),
                    buildBlackKey(color: Colors.black, soundNumber: 104),
                    Container(width: kkeyWidth * 0.5),
                    buildBlackKey(color: Colors.black, soundNumber: 106),
                    Container(width: kkeyWidth),
                  ])),
            ]),
          ),
         
          ],
        ),
      );
  }

For proper aligment of text in Button widget I’ve used InkWell button widget and then it works fine.

  Expanded buildWhiteKey({Color color, int soundNumber}) {
    return Expanded(
      child: Padding(
        padding: const EdgeInsets.all(1.0),
        child: InkWell(
          onTap: () {
            //playSound(soundNumber);
          },
          child: Container(
            //height: double.infinity,
            color: color,
            padding: EdgeInsets.all(1.0),
            child: Align(
              alignment: Alignment.bottomCenter,
              child: Text(
                '$soundNumber',
                textAlign: TextAlign.left,
              ),
            ),
          ),
        ),
      ),
    );
  }

For how to get width of white keys, I’m not really sure how that works yet, but have work around, where I found how to control it with one constant and divide it or multiply based on position of black key.

Thank Ammar for your time and effort, even though your code didn’t really work out for me (guess you couldn’t really test it out as you didn’t have machine at hand), though your advices helped me as well in my work.

Answered By – Jan

Answer Checked By – Jay B. (FlutterFixes Admin)

Leave a Reply

Your email address will not be published. Required fields are marked *