Search code examples
flutterdartalignment

Flutter: SizedBox around button corrupts text alignment


I am building a keypad, however, fighting 2 strange behaviors since yesterday:

(1) my construction of the button with a SizedBox to create a square button causes a text alignment to the right. Actually it appears more like an offset, because if add a button with a longer text than 1, 2, 3 ("some text" in the snippet below), the text is not displayed. If I cut the text to the 1st character, this character will be shown.

(2) the keypad is hosted within a column. The column's crossAxisAlignment is center. While all column items I put above or below the keypad are centered, the keypad remains left. Also wrapping the CreateKeyPad in a Align or (as now in the snippet) Center the Row within CreateKeyPad does not help.

I have shrunk the code a bit to make it easier to understand, hope this still works.

In the screenshot below, the 0 on top is centered horizontally. enter image description here

import 'package:flutter/cupertino.dart';

class Tackle1x1Page extends StatefulWidget {
  Tackle1x1Page({Key key, this.title}) : super(key: key);
  final String title;

  @override
  _Tackle1x1PageState createState() => _Tackle1x1PageState();
}

class _Tackle1x1PageState extends State<Tackle1x1Page> {
  int value = 0;

  @override
  Widget build(BuildContext context) {
    return CupertinoPageScaffold(
        child: SafeArea(
            child: Column(
                crossAxisAlignment: CrossAxisAlignment.center,
                children: <Widget>[
                Text((value != null ? value : "0")),
                CreateKeypad(
                  prevInput: (value != null ? value : 0),
                  updtedInput: (int val) {
                    setState(() => value = val);
                  },
                ),
            ],
        ),),
    );
  }
}

// CREATE KEYPAD
class CreateKeypad extends StatelessWidget {
  final int prevInput;
  final Function(int) updtedInput;

  CreateKeypad({
    @required this.prevInput,
    @required this.updtedInput,
  });

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Row(
        children: <Widget> [
          Column(
            children: <Widget>[
              CreateKey(
                keyValue: 1,
                keyReturnValue: (int val) {
                  updtedInput(prevInput != null? 10 * prevInput + val : val);
                },
              ),
              CreateKey(
                keyValue: 4,
                keyReturnValue: (int val) {
                  updtedInput(prevInput != null? 10 * prevInput + val : val);
                },
              ),
              CreateKey(
                keyValue: 7,
                keyReturnValue: (int val) {
                  updtedInput(prevInput != null? 10 * prevInput + val : val);
                },
              ),
            ],
          ),
          Column(
              children: <Widget>[
                CreateKey(
                  keyValue: 2,
                  keyReturnValue: (int val) {
                    updtedInput(prevInput != null? 10 * prevInput + val : val);
                  },
                ),
                CreateKey(
                  keyValue: 5,
                  keyReturnValue: (int val) {
                    updtedInput(prevInput != null? 10 * prevInput + val : val);
                  },
                ),
              Padding(
                padding: const EdgeInsets.all(2.0),
                child: SizedBox(
                  width: 80.0,
                  height: 80.0,
                  child: Text("some text", style: TextStyle(color: CupertinoColors.black)),
                ),
              ),
            ],
          ),
        ]
    ),);
  }
}

// CREATE SINGLE KEY
class CreateKey extends StatelessWidget {
  final int keyValue;
  final VoidCallback keyTabbed;
  final Function(int) keyReturnValue;

  CreateKey({
    @required this.keyValue,
    @required this.keyReturnValue,
    this.keyTabbed,
  });

  @override
  Widget build(BuildContext context) {
    return
      Padding(
        padding: const EdgeInsets.all(2.0),
        child: SizedBox(
          width: 80.0,
          height: 80.0,
          child: CupertinoButton(
            child: Text(keyValue.toString(), style: TextStyle(color: CupertinoColors.black)),

            onPressed: () {
              keyReturnValue(keyValue);
            },
            color: CupertinoColors.systemGrey,
          ),
        ),
      );
  }
}

Solution

  • The CupertinoButton has a default padding of EdgeInsets.all(16.0) if it isn't given a color and it has a default padding of EdgeInsets.symmetric(vertical:14.0, horizontal: 64.0) if it is given a color. To be able to center the Text, you can give it a padding of zero.

    I provided an example using your code:

    class CreateKey extends StatelessWidget {
      final int keyValue;
      final VoidCallback keyTabbed;
      final Function(int) keyReturnValue;
    
      CreateKey({
        @required this.keyValue,
        @required this.keyReturnValue,
        this.keyTabbed,
      });
    
      @override
      Widget build(BuildContext context) {
        return Padding(
          padding: const EdgeInsets.all(2.0),
          child: SizedBox(
            width: 80.0,
            height: 80.0,
            child: CupertinoButton(
              // remove the default padding 
              padding: EdgeInsets.zero, // new line
              child: Text(
                keyValue.toString(),
                style: TextStyle(
                  color: CupertinoColors.black,
                ),
              ),
              onPressed: () {
                keyReturnValue(keyValue);
              },
              color: CupertinoColors.systemGrey,
            ),
          ),
        );
      }
    }
    
    

    To center the keypad horizontally, set the mainAxisAlignment property of the Row to MainAxisAlignment.center.

    I added a demo using your code as an example:

     return Center(
          child: Row(
            // set the mainaxisalignment property to center
            mainAxisAlignment: MainAxisAlignment.center, // new line
            children: <Widget>[
            ...... other widgets