Developer123
Developer123

Reputation: 85

Changing keyboard from lower to upper case flutter

I have a keyboard that I created in flutter where I need to be able to switch from uppercase to lower case when a button is pressed which is shown on my keyboard as the up arrow with a line below it. in both of my keyboard classes I have a conditional isCapital which changes between true and false every time the button is pressed. I also have a a fucnction which returns a widget where if isCapital is true it returns the capital keyboard and if false the lowercase keyboard. I placed this inside a container in my widget tree and am having a problem where the Boolean isCapital is being updated correctly and if I do a hot restart the keyboard changes from the capital to the lowercase board, but it does not change automatically, therefore when I press the button to change the board nothing happens. I am trying to understand what I need to do to implement this functionality where when I press the button the keyboard will change from one to the other.

Update: Also should probably mention that my keyboard class, as well as my capital key class and toggleKeyBoard() are all in a separate widget tree, so calling set state doesn't seem to work correctly.

I started looking into streams, not sure if my answer lies here.

Lowercase board enter image description here

Uppercase board enter image description here

Code for the capital button on the keyboard

class CapitalKey extends StatelessWidget
{

  @override
  Widget build(BuildContext context)
  {
    return Expanded(
      flex: 100,
      child: Padding(
        padding: const EdgeInsets.all(6.0),
        child: Material(
          color: Color.fromRGBO(246, 246, 246, 1),
          child: Container(
            decoration: BoxDecoration(
              border: Border.all(color: Color.fromRGBO(92, 103, 148, 1)),
              borderRadius: BorderRadius.circular(5.0),
            ),
            child: Center(
              child: IconButton(
                icon: Image.asset('assets/text_key/capital.png'),
                onPressed: () {
                  isCapital = !isCapital;
                },
              ),
            ),
          ),
        ),
      ),
    );
  }
}

Code for lowercase keyboard, uppercase keyboard just follows the same logic, and I implement the capital key on row three.


class KeyBoardLower extends StatelessWidget
{
  KeyBoardLower({
    required this.onTextInput,
    required this.onBackspace,
  });

  final double width = 1200;
  final double height = 80;

  final ValueSetter<String> onTextInput;
  final VoidCallback onBackspace;

  void _textInputHandler(String text) => onTextInput.call(text);

  void _backspaceHandler() => onBackspace.call();

  Container buildRowOne()
  {
    return Container(
      width: width,
      height: height,
      child: Row(
        children: [
          TextKey(
            text: 'q',
            onTextInput: _textInputHandler,
          ),
          TextKey(
            text: 'w',
            onTextInput: _textInputHandler,
          ),
          TextKey(
            text: 'e',
            onTextInput: _textInputHandler,
          ),
          TextKey(
            text: 'r',
            onTextInput: _textInputHandler,
          ),
          TextKey(
            text: 't',
            onTextInput: _textInputHandler,
          ),
          TextKey(
            text: 'y',
            onTextInput: _textInputHandler,
          ),
          TextKey(
            text: 'u',
            onTextInput: _textInputHandler,
          ),
          TextKey(
            text: 'i',
            onTextInput: _textInputHandler,
          ),
          TextKey(
            text: 'o',
            onTextInput: _textInputHandler,
          ),
          TextKey(
            text: 'p',
            onTextInput: _textInputHandler,
          ),
          BackspaceKey(
            onBackspace: _backspaceHandler,
          ),
        ],
      ),
    );
  }

  Container buildRowTwo()
  {
    return Container(
      width: width,
      height: height,
      child: Row(
        children: [
          TextKey(
            text: 'a',
            onTextInput: _textInputHandler,
          ),
          TextKey(
            text: 's',
            onTextInput: _textInputHandler,
          ),
          TextKey(
            text: 'd',
            onTextInput: _textInputHandler,
          ),
          TextKey(
            text: 'f',
            onTextInput: _textInputHandler,
          ),
          TextKey(
            text: 'g',
            onTextInput: _textInputHandler,
          ),
          TextKey(
            text: 'h',
            onTextInput: _textInputHandler,
          ),
          TextKey(
            text: 'j',
            onTextInput: _textInputHandler,
          ),
          TextKey(
            text: 'k',
            onTextInput: _textInputHandler,
          ),
          TextKey(
            text: 'l',
            onTextInput: _textInputHandler,
          ),
          EnterKey(),
        ],
      ),
    );
  }

  Container buildRowThree()
  {
    return Container(
      width: width,
      height: height,
      child: Row(
        children: [
          CapitalKey(),
          TextKey(
            text: 'z',
            onTextInput: _textInputHandler,
          ),
          TextKey(
            text: 'x',
            onTextInput: _textInputHandler,
          ),
          TextKey(
            text: 'c',
            onTextInput: _textInputHandler,
          ),
          TextKey(
            text: 'v',
            onTextInput: _textInputHandler,
          ),
          TextKey(
            text: 'b',
            onTextInput: _textInputHandler,
          ),
          TextKey(
            text: 'n',
            onTextInput: _textInputHandler,
          ),
          TextKey(
            text: 'm',
            onTextInput: _textInputHandler,
          ),
          TextKey(
            text: '!',
            onTextInput: _textInputHandler,
          ),
          TextKey(
            text: '?',
            onTextInput: _textInputHandler,
          ),
          CapitalKey(),
        ],
      ),
    );
  }

  Container buildRowFour()
  {
    return Container(
        width: width,
        height: height,
        child: Row(
          children: [
            NumberKey(),
            TextKey(
                text: ',',
                onTextInput: _textInputHandler,
            ),
            TextKey(
              text: ' ',
              onTextInput: _textInputHandler,
              flex: 200,
            ),
            TextKey(
                text: '.',
                onTextInput: _textInputHandler,
            ),
            NumberKey(),
          ],
        ),
    );
  }

  @override
  Widget build(BuildContext context)
  {
    return SafeArea(
      child: Padding(
        padding: const EdgeInsets.only(left: 80),
        child: Container(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.end,
            children: [
              buildRowOne(),
              buildRowTwo(),
              buildRowThree(),
              buildRowFour(),
            ],
          ),
        ),
      ),
    );
  }
}

Function I am using to change from one keyboard to the other, using a Boolean isCapital which I have initialized to false. I am calling this function which will return either keyboard to a container that I have on my main screen, if true return capital board and if false return lowercase board.

Widget toggleKeyboard()
 {
   if (isCapital == true) {
     return KeyBoardCapital(
       onTextInput: (myText) {
         insertText(myText, toggleTextField()); //Accepts either myController1 or myController2 based on conditional
       },
       onBackspace: () {
         backspace(toggleTextField());
       },
     );
   } else {
     return KeyBoardLower(
       onTextInput: (myText) {
         insertText(myText, toggleTextField());
       },
       onBackspace: () {
         backspace(toggleTextField());
       },
     );
   }
 }

Upvotes: 0

Views: 636

Answers (1)

thecodexhub
thecodexhub

Reputation: 181

Actually on pressing the CapitalKey the value of isCapital is getting changed but the widgets are not rebuilding, so you can't see the changes. A simple solution will be to call a setState from the main screen assuming your main screen is a StatefulWidget.

class CapitalKey extends StatelessWidget {
  CapitalKey({
    required this.onCapitalKeyPressed;
  });

  final VoidCallback onCapitalKeyPressed;

  @override
  Widget build(BuildContext context) {
    // REST OF THE CODE IS SAME
    child: IconButton(
      icon: Image.asset('assets/text_key/capital.png'),
      onPressed: onCapitalKeyPressed,
     ),
   // REST OF THE CODE IS SAME
  }
}

Similarly, you have to pass the onCapitalKeyPressed to main screen from KeyBoardLower and KeyBoardHigher.

class KeyBoardLower extends StatelessWidget {
  KeyBoardLower({
    // ---
    required this.onCapitalKeyPressed,
  });

  final VoidCallback onCapitalKeyPressed;
  // REST OF THE CODE SAME
}

Now on the main screen toggle the flag isCapital inside the setState.

class MyKeyboard extends StatefulWidget {
  const MyKeyboard({Key? key}) : super(key: key);

  @override
  State<MyKeyboard> createState() => _MyKeyboardState();
}

class _MyKeyboardState extends State<MyKeyboard> {
  bool isCapital = false;

  @override
  Widget build(BuildContext context) {
    return toggleKeyboard();
  }

  Widget toggleKeyboard() {
    if (isCapital == true) {
      return KeyBoardCapital(
        // REST OF THE CODE SAME
        onCapitalKeyPressed: () {
          setState(() {
            isCapital = !isCapital;
          });
        },
      );
    } else {
      return KeyBoardLower(
        // REST OF THE CODE SAME
        onCapitalKeyPressed: () {
          setState(() {
            isCapital = !isCapital;
          });
        },
      );
    }
  }
}

Hope it helps! Also let me know if I missed or misunderstood something :)

Upvotes: 1

Related Questions