TSR
TSR

Reputation: 20406

Button overlaps on textfield when keyboard is open

Here is my issue: The button should Not overlap the textfield.

enter image description here

Notice that I added a SingleChildScrollView(). The user can still scroll up and achieve the desired the result but I want to make it automatic:

enter image description here

Here is my code:

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter_masked_text/flutter_masked_text.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:talking_dodo/dodo/pages/payment/credit_card.dart';

class WithdrawPage extends StatefulWidget {
  @override
  WithdrawPageState createState() {
    return new WithdrawPageState();
  }
}

class WithdrawPageState extends State<WithdrawPage> {
  bool isDataAvailable = true;
  int _radioValue = 0;
  MaskedTextController ccMask =
  MaskedTextController(mask: "0000 0000 0000 0000");
  Widget _buildBody() {
    return Stack(
      children: <Widget>[
        SingleChildScrollView(
          child: Padding(
            padding: const EdgeInsets.only(
                left: 16.0, right: 16.0, top: 16.0, bottom: 16.0),
            child: Column(
              children: <Widget>[
                Row(
                  children: <Widget>[
                    Padding(
                      padding: const EdgeInsets.only(left: 18.0),
                      child: Text('Please select withdrawal method below'),
                    ),
                  ],
                ),
                Container(
                  margin: EdgeInsets.only(top: 12.0),
                  child: Row(
                    children: <Widget>[
                      new Radio(
                        value: 0,
                        groupValue: _radioValue,
                        onChanged: ((value) {
                          setState(() {
                            _radioValue = value;
                          });
                        }),
                      ),
                      Text(
                        'ATM Withdrawal',
                      ),
                    ],
                  ),
                ),
                Container(
                  height: 220.0,
                  padding: EdgeInsets.only(left: 20.0, right: 10.0),
                  margin: const EdgeInsets.all(2.0),
                  decoration: BoxDecoration(
//                  color: Colors.white,
                    border: Border.all(color: Colors.black),
                    borderRadius: BorderRadius.all(Radius.circular(12.0)),
                  ),
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                    crossAxisAlignment: CrossAxisAlignment.stretch,
                    children: <Widget>[
                      Bullet('Visit mcb Branch'),
                      Bullet('Select "Dodo Wallet" in the options'),
                      Bullet('Select the amount to withdraw'),
                      Bullet('Input your dodo wallet pin'),
                      Bullet(
                          'Input the code in the input box below and click withdraw'),
                      Padding(
                        padding: const EdgeInsets.only(top:18.0),
                        child: TextField(
                          controller: ccMask,
                          keyboardType: TextInputType.number,
                          maxLength: 19,
                          style:
                              TextStyle(fontFamily: 'Raleway', color: Colors.black),
                          decoration: InputDecoration(
                              labelText: "Code",
                              labelStyle: TextStyle(fontWeight: FontWeight.bold),
                              border: OutlineInputBorder()),
                        ),
                      ),
                    ],
                  ),
                ),
                Row(
                  children: <Widget>[
                    new Radio(
                      value: 1,
                      groupValue: _radioValue,
                      onChanged: ((value) {
                        setState(() {
                          _radioValue = value;
                        });
                      }),
                    ),
                    Text(
                      'Transfer to card',
                    ),
                  ],
                ),
              ],
            ),
          ),
        ),
        Align(
          alignment: Alignment.bottomCenter,
          child: Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Container(
                child: isDataAvailable
                    ? Expanded(
                        child: ButtonTheme(
                          height: 65.0,
                          child: RaisedButton(
                              color: Theme.of(context).primaryColorLight,
                              child: Text('Withdraw funds'),
                              onPressed: () => showSuccessDialog()),
                        ),
                      )
                    : Padding(
                        padding: EdgeInsets.only(bottom: 10.0),
                        child: CircularProgressIndicator()),
              ),
            ],
          ),
        ),
      ],
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Withdrawal"),
      ),
      body: _buildBody(),
    );
  }

  void showSuccessDialog() {
    setState(() {
      isDataAvailable = false;
      Future.delayed(Duration(seconds: 1)).then((_) => goToDialog());
    });
  }

  goToDialog() {
    setState(() {
      isDataAvailable = true;
    });
    showDialog(
        context: context,
        barrierDismissible: true,
        builder: (context) => Center(
              child: SingleChildScrollView(
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    successTicket(),
                    SizedBox(
                      height: 10.0,
                    ),
                    FloatingActionButton(
                      backgroundColor: Colors.black,
                      child: Icon(
                        Icons.clear,
                        color: Colors.white,
                      ),
                      onPressed: () {
                        Navigator.pop(context);
                        Navigator.of(context).pushNamed('/chat');
                      },
                    )
                  ],
                ),
              ),
            ));
  }

  successTicket() => Container(
        width: double.infinity,
        padding: const EdgeInsets.all(16.0),
        child: Material(
          clipBehavior: Clip.antiAlias,
          elevation: 2.0,
          borderRadius: BorderRadius.circular(4.0),
          child: Padding(
            padding: const EdgeInsets.all(16.0),
            child: Column(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: <Widget>[
                ProfileTile(
                  title: "Thank You!",
                  textColor: Colors.purple,
                  subtitle: "Your transaction was successful",
                ),
                ListTile(
                  title: Text("Date"),
                  subtitle: Text("26 June 2018"),
                  trailing: Text("11:00 AM"),
                ),
                ListTile(
                  title: Text("Daniel Daniel"),
                  subtitle: Text("[email protected]"),
                  trailing: CircleAvatar(
                    radius: 20.0,
                    backgroundImage: NetworkImage(
                        "https://avatars0.githubusercontent.com/u/12619420?s=460&v=4"),
                  ),
                ),
                ListTile(
                  title: Text("Amount"),
                  subtitle: Text("\$423.00"),
                  trailing: Text("Completed"),
                ),
                Card(
                  clipBehavior: Clip.antiAlias,
                  elevation: 0.0,
                  color: Colors.grey.shade300,
                  child: ListTile(
                    leading: Icon(
                      FontAwesomeIcons.ccAmex,
                      color: Colors.blue,
                    ),
                    title: Text("Credit/Debit Card"),
                    subtitle: Text("Amex Card ending ***6"),
                  ),
                ),
              ],
            ),
          ),
        ),
      );
}

class Bullet extends Text {
  const Bullet(
    String data, {
    Key key,
    TextStyle style,
    TextAlign textAlign,
    TextDirection textDirection,
    Locale locale,
    bool softWrap,
    TextOverflow overflow,
    double textScaleFactor,
    int maxLines,
    String semanticsLabel,
  }) : super(
          '• $data',
          key: key,
          style: style,
          textAlign: textAlign,
          textDirection: textDirection,
          locale: locale,
          softWrap: softWrap,
          overflow: overflow,
          textScaleFactor: textScaleFactor,
          maxLines: maxLines,
          semanticsLabel: semanticsLabel,
        );
}

Upvotes: 2

Views: 6236

Answers (1)

rmtmckenzie
rmtmckenzie

Reputation: 40433

What you're looking for is the scrollPadding parameter of textfield. Flutter automatically scrolls the view to the top of the keyboard when the textfield is focused, but it has no idea about the fact that you've placed a button that sits at the bottom of the screen.

With your current code, you could simply replace scrollPadding with padding that has a larger bottom (i.e. the size of the yellow button) and flutter should do the rest for you.

Upvotes: 13

Related Questions