I am trying to make a pin login for an app that is in landscape view. I am using Dart/flutter, and cannot figure out how to relocate the textinput keyboard.

Is it possible to use something like this, but force the keyboard to be NEXT to the text field instead of below the text field? How to create number input field in Flutter?


Solution 1: boformer

The position and shape of the keyboard is completely device-specific. There are even floating or split keyboards, and there is no way modify the position of the system keyboard.

I would recommend you to build a "fake" numerical keyboard widget in Flutter. That will give you full control over the position and size of the keyboard, as well as the displayed digits. For a simple PIN input, you don't even need to connect it to a real TextField, which makes things much easier.

Here is a very basic example:

enter image description here

import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: MyLoginPage(),
    );
  }
}

class MyLoginPage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => MyLoginPageState();
}

class MyLoginPageState extends State<MyLoginPage> {
  String _pin = '';

  void _onKeyPressed(int key) {
    if (key == NumericalKeyboard.backspaceKey) {
      if (_pin.length > 0) {
        setState(() {
          _pin = _pin.substring(0, _pin.length - 1);
        });
      }
    } else {
      setState(() {
        _pin += key.toString();
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('LOGIN'),
      ),
      body: Row(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: <Widget>[
          Expanded(child: _buildPage()),
          NumericalKeyboard(
            onKeyPressed: _onKeyPressed,
          )
        ],
      ),
    );
  }

  Widget _buildPage() {
    return Padding(
      padding: EdgeInsets.all(16.0),
      child: Center(
        child: Container(
          decoration: BoxDecoration(border: Border.all()),
          width: 150.0,
          padding: EdgeInsets.all(4.0),
          child: Text(
            _pin,
            textAlign: TextAlign.center,
            style: TextStyle(fontSize: 32.0, letterSpacing: 2.0),
          ),
        ),
      ),
    );
  }
}

typedef KeyboardCallback(int key);

class NumericalKeyboard extends StatelessWidget {
  const NumericalKeyboard({Key key, this.onKeyPressed}) : super(key: key);

  static const backspaceKey = 42;
  static const clearKey = 69;

  final KeyboardCallback onKeyPressed;

  @override
  Widget build(BuildContext context) {
    return Material(
      color: Colors.grey[200],
      child: Table(
        defaultColumnWidth: IntrinsicColumnWidth(flex: 1.0),
        border: TableBorder.all(),
        children: [
          TableRow(
            children: [
              _buildNumberKey(1),
              _buildNumberKey(2),
              _buildNumberKey(3),
            ],
          ),
          TableRow(
            children: [
              _buildNumberKey(4),
              _buildNumberKey(5),
              _buildNumberKey(6),
            ],
          ),
          TableRow(
            children: [
              _buildNumberKey(7),
              _buildNumberKey(8),
              _buildNumberKey(9),
            ],
          ),
          TableRow(
            children: [
              Container(),
              _buildNumberKey(0),
              _buildKey(Icon(Icons.backspace), backspaceKey),
            ],
          )
        ],
      ),
    );
  }

  Widget _buildNumberKey(int n) {
    return _buildKey(Text('$n'), n);
  }

  Widget _buildKey(Widget icon, int key) {
    return IconButton(
      icon: icon,
      padding: EdgeInsets.all(16.0),
      onPressed: () => onKeyPressed(key),
    );
  }
}