Как получить статический фон контейнера, но прокручиваемую форму входа?

#flutter #user-interface

#flutter #пользовательский интерфейс

Вопрос:

Я хочу прокручивать логинформ, но НЕ фон, но я заметил, что коинтанер, содержащий эти «круги», перемещается вверх при появлении клавиатуры, поэтому я добавил

 resizeToAvoidBottomInset: true,
 

К каркасу, но теперь я не могу прокручивать что-либо в форме входа, и это то, чего я не хочу, я хочу прокручивать ТОЛЬКО форму входа..

Вот скриншот эмулятора, просто нажмите на это

 import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:landscapes/bloc/inherited_provider.dart';
import 'package:landscapes/bloc/login_bloc.dart';
import 'package:landscapes/pages/register_page.dart';

class LoginPage extends StatefulWidget {
  LoginPage({Key key}) : super(key: key);

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

class _LoginPageState extends State<LoginPage> {
  final formKey = GlobalKey<FormState>();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        resizeToAvoidBottomInset: true,
        body: Form(
          key: formKey,
          child: Stack(
            children: <Widget>[
              _crearFondo(),
              _loginForm(context),
            ],
          ),
        ));
  }

  Widget _crearFondo() {
    Size size = MediaQuery.of(context).size;
    final fondoGris = Container(
        height: size.height, width: size.width, color: Colors.grey[850]);
    final circulo = Container(
      width: 90.0,
      height: 90.0,
      decoration: BoxDecoration(
          borderRadius: BorderRadius.circular(100.0),
          color: Color.fromRGBO(255, 255, 255, 0.05)),
    );
    return Stack(
      children: <Widget>[
        fondoGris,
        Positioned(top: 50.0, left: 30.0, child: circulo),
        Positioned(top: 150.0, right: 50.0, child: circulo),
        Positioned(bottom: 180.0, right: 20.0, child: circulo),
        Positioned(bottom: 280.0, left: 40.0, child: circulo),
      ],
    );
  }

  Widget _loginForm(context) {
    final bloc = InheritedProvider.loginBlocInherit(context);
    final size = MediaQuery.of(context).size;
    return SingleChildScrollView(
          child: Column(
        children: <Widget>[
          SafeArea(child: Container(height: size.height * 0.05)),
          SizedBox(height: size.height * 0.05),
          welcomeBackForm(),
          SizedBox(height: 55.0),
          _formEmail(bloc),
          SizedBox(height: 30.0),
          _formPassword(),
          SizedBox(height: 38),
          _button(),
          SizedBox(height: 50),
          _crearCuenta(),
        ],
      ),
    );
  }

  //MENSAJE BIENVENIDA
  Widget welcomeBackForm() {
    return Container(
      alignment: Alignment.topLeft,
      margin: EdgeInsets.only(left: 40.0),
      child: Text(
        'Hello!nWelcome back',
        style: GoogleFonts.playfairDisplay(
            fontSize: 30, fontWeight: FontWeight.w600, color: Colors.white),
      ),
    );
  }

  //TEXTFORMFIELD DEL EMAIL
  Widget _formEmail(LoginBloc bloc) {
    return Container(
      padding: EdgeInsets.symmetric(horizontal: 30.0),
      child: TextFormField(
        keyboardType: TextInputType.emailAddress,
        decoration: InputDecoration(
            icon: Icon(
              Icons.email,
              color: Colors.white,
            ),
            hintText: 'Email adress',
            filled: true,
            fillColor: Colors.grey[600],
            enabledBorder: OutlineInputBorder(borderSide: BorderSide.none),
            border: OutlineInputBorder(borderSide: BorderSide.none)),
        style: TextStyle(height: 1),
        validator: (value) {
          Pattern pattern =
              r'^(([^<>()[]\.,;:s@"] (.[^<>()[]\.,;:s@"] )*)|(". "))@(([[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}])|(([a-zA-Z-0-9] .) [a-zA-Z]{2,}))


Ответ №1:

Вы можете попробовать обернуть вашу _loginForm с помощью SingleChildScrollView следующим образом :

 SingleChildScrollView(child: _loginForm(context)),
 

При этом виджеты внутри _crearFondo() не будут прокручиваться, однако виджеты внутри _loginForm будут прокручиваться.

Пожалуйста, ознакомьтесь с документацией Flutter для SingleChildScrollView

SingleChildScrollView Синглчилдскроллвью

Окно, в котором можно прокручивать один виджет.

Этот виджет полезен, когда у вас есть единственное окно, которое обычно полностью видно, например циферблат часов в окне выбора времени, но вам нужно убедиться, что его можно прокручивать, если контейнер становится слишком маленьким по одной оси (направление прокрутки).

Это также полезно, если вам нужно выполнить сжатие по обеим осям (основное направление прокрутки, а также поперечная ось), как можно увидеть в диалоговом окне или всплывающем меню. В этом случае вы можете связать SingleChildScrollView с дочерним элементом ListBody.

Если у вас есть список дочерних элементов, и вам не требуется поведение сжатия по перекрестной оси, например, список прокрутки, который всегда имеет ширину экрана, рассмотрите ListView, который намного эффективнее, чем SingleChildScrollView, содержащий ListBody или столбец со многими дочерними элементами.

;
RegExp regExp = new RegExp(pattern);

if (regExp.hasMatch(value)) {
return null;
} else {
return ('El email no es correcto');
}
},
),
);
}

//TEXTFORMFIELD DEL PASSWORD
Widget _formPassword() {
return Container(
padding: EdgeInsets.symmetric(horizontal: 30.0),
child: TextFormField(
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
icon: Icon(
Icons.lock,
color: Colors.white,
),
hintText: 'Password',
filled: true,
fillColor: Colors.grey[600],
enabledBorder: OutlineInputBorder(borderSide: BorderSide.none),
border: OutlineInputBorder(borderSide: BorderSide.none),
),
style: TextStyle(height: 1),
),
);
}

//BOTON INGRESAR
Widget _button() {
return RaisedButton(
color: Color.fromRGBO(254, 200, 140, 1),
padding: EdgeInsets.symmetric(horizontal: 90.0, vertical: 15.0),
child: Text('ingresar'),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5.0),
),
elevation: 0.0,
onPressed: () => _submit(),
);
}

//FLATBUTTON DE CREAR CUENTA
Widget _crearCuenta() {
return FlatButton(
onPressed: () => Navigator.pushReplacementNamed(context, 'registerpage'),
child: Text(
'Crear una nueva cuenta',
style: TextStyle(fontSize: 14),
),
textColor: Colors.white,
);
}

//SUBMIT DEL BOTON
void _submit() async {
if (!formKey.currentState.validate()) return null;
formKey.currentState.save();

Navigator.pushReplacement(context,
MaterialPageRoute(builder: (BuildContext context) => RegisterPage()));
// Navigator.pushReplacementNamed(context, HomePage.routName).then((value) { setState(() { });});
}
}

Ответ №1:

Вы можете попробовать обернуть вашу _loginForm с помощью SingleChildScrollView следующим образом :


При этом виджеты внутри _crearFondo() не будут прокручиваться, однако виджеты внутри _loginForm будут прокручиваться.

Пожалуйста, ознакомьтесь с документацией Flutter для SingleChildScrollView

SingleChildScrollView Синглчилдскроллвью

Окно, в котором можно прокручивать один виджет.

Этот виджет полезен, когда у вас есть единственное окно, которое обычно полностью видно, например циферблат часов в окне выбора времени, но вам нужно убедиться, что его можно прокручивать, если контейнер становится слишком маленьким по одной оси (направление прокрутки).

Это также полезно, если вам нужно выполнить сжатие по обеим осям (основное направление прокрутки, а также поперечная ось), как можно увидеть в диалоговом окне или всплывающем меню. В этом случае вы можете связать SingleChildScrollView с дочерним элементом ListBody.

Если у вас есть список дочерних элементов, и вам не требуется поведение сжатия по перекрестной оси, например, список прокрутки, который всегда имеет ширину экрана, рассмотрите ListView, который намного эффективнее, чем SingleChildScrollView, содержащий ListBody или столбец со многими дочерними элементами.