Содержимое нижней части экрана не отображается на некоторых телефонах

#android #ios #flutter #flutter-layout

#Android #iOS #флаттер #флаттер-макет

Вопрос:

Я разрабатываю приложение flutter, ниже приведен мой код пользовательского интерфейса

 import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

import 'package:flutter/widgets.dart';

class LoginPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      body: SingleChildScrollView(
        child: ConstrainedBox(
          constraints:  BoxConstraints(maxHeight: MediaQuery.of(context).size.height),
          child: Container(child: _LoginUI(),),)
      ),
    );
  }
}

class _LoginUI extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _LoginState();
  }
}



class _LoginState extends State<_LoginUI> {

  final _formKey = GlobalKey<FormState>();
  //FIXME When validate error occures, the fields get super small

  

  TextEditingController _phoneNumber = TextEditingController();
  TextEditingController _passwordController = TextEditingController();

  @override
  Widget build(BuildContext context) {


    return Container(
        height: double.infinity,
        width: double.infinity,
        child:
         Stack(
          fit: StackFit.loose,
          children: <Widget>[
            SafeArea(
              child: Container(
                margin: EdgeInsets.only(top: 25),
                child: Image.asset("assets/images/login_image.png"),
              ),
            ),
            
            Positioned(
              top: 275,
              child: Container(
                height: 600,
                width: MediaQuery.of(context).size.width,
                decoration: new BoxDecoration(
                    color: Colors.white,
                    borderRadius: new BorderRadius.only(
                        topLeft: const Radius.circular(40.0),
                        topRight: const Radius.circular(40.0))),
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.start,
                  children: <Widget>[
                    Row(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: <Widget>[
                        Flexible(
                          child: Container(
                            margin:
                                EdgeInsets.only(top: 20, left: 10, right: 10),
                            child: Image.asset(
                                "assets/images/logo.png",
                                width: 200,
                                height: 50),
                          ),
                        )
                      ],
                    ),
                    Form(
                      key: _formKey,
                      child: Column(
                        children: <Widget>[
                          Container(
                              margin: EdgeInsets.only(
                                top: 40,
                              ),
                              child: SizedBox(
                                width: MediaQuery.of(context).size.width * .90,
                                height: 36,
                                child: TextFormField(
                                  controller: _phoneNumber,
                                  validator: (value) {
                                    if (value.isEmpty) {
                                      return 'Please enter some text';
                                    }
                                    return null;
                                  },
                                  decoration: InputDecoration(
                                    filled: true,
                                    fillColor: Colors.white,
                                    contentPadding: const EdgeInsets.only(
                                        top: 2, bottom: 2, left: 8),
                                    border: OutlineInputBorder(
                                      borderRadius: BorderRadius.circular(30.0),
                                    ),
                                    hintText: "Email",
                                  ),
                                ),
                              )),
                          Container(
                            margin: EdgeInsets.only(
                              top: 15,
                            ),
                            child: SizedBox(
                              height: 36,
                              width: MediaQuery.of(context).size.width * .90,
                              child: TextFormField(
                                controller: _passwordController,
                                keyboardType: TextInputType.visiblePassword,
                                validator: (value) {
                                  if (value.isEmpty) {
                                    return 'Please enter some text';
                                  }
                                  return null;
                                },
                                decoration: InputDecoration(
                                  filled: true,
                                  fillColor: Colors.white,
                                  contentPadding: const EdgeInsets.only(
                                      top: 2, bottom: 2, left: 8),
                                  border: OutlineInputBorder(
                                    borderRadius: BorderRadius.circular(30.0),
                                  ),
                                  hintText: "Password",
                                ),
                              ),
                            ),
                          ),
                          Align(
                            alignment: Alignment.bottomRight,
                            child: Container(
                                margin: EdgeInsets.only(
                                    top: 1, left: 10, right: 10),
                                child: FlatButton(
                                  onPressed: () {
                                    Navigator.pushNamed(context, "/password-reset");
                                  },
                                  child: Text("Forgot Password?",
                                      style: TextStyle(
                                          fontFamily: 'Roboto-Medium',
                                          fontSize: 14.0,
                                          letterSpacing: 1.25,
                                          color:
                                              Color.fromRGBO(75, 56, 137, 80))),
                                )),
                          ),
                          Container(
                              margin:
                                  EdgeInsets.only(top: 1, left: 10, right: 10),
                              child: SizedBox(
                                width: MediaQuery.of(context).size.width * .90,
                                child: RaisedButton(
                                  color: Color.fromRGBO(75, 56, 137, 80),
                                  textColor: Colors.white,
                                  shape: RoundedRectangleBorder(
                                      borderRadius:
                                          new BorderRadius.circular(18.0),
                                      side: BorderSide(
                                          color:
                                              Color.fromRGBO(75, 56, 137, 80))),
                                  child: Text(
                                    "LOGIN",
                                    style: Theme.of(context).textTheme.button,
                                  ),
                                  onPressed: () {

                                    String email = _phoneNumber.text;
                                    String password = _passwordController.text;
                                    
                                    if (_formKey.currentState.validate()) {
                                      loginProcess(email, password);
                                    }
                                  },
                                ),
                              ))
                        ],
                      ),
                    ),
                    Container(
                        margin: EdgeInsets.only(top: 1, left: 10, right: 10),
                        child: FlatButton(
                          onPressed: () {
                            Navigator.pushNamed(context, "/register");
                          },
                          child: RichText(
                            text: TextSpan(children: <TextSpan>[
                              TextSpan(
                                text: "Not a member yet? ",
                                style: TextStyle(fontFamily: 'Roboto-Regular',  fontSize: 14.0, letterSpacing: 0.25, color:Color.fromRGBO(75, 56, 137, 80 )),
                              ),
                              TextSpan(
                                text: "Create an Account",
                                style: TextStyle(decoration: TextDecoration.underline,  fontFamily: 'Roboto-Regular',  fontSize: 14.0, letterSpacing: 0.25, color:Color.fromRGBO(75, 56, 137, 80 ),
                              ),)
                            ]),
                          ),
                        )),
                  ],
                ),
              ),
            ),
          ],
        )
        //child: Image.asset("assets/images/login_image.png"),
        );
  }

  
  

На рисунке ниже показан пользовательский интерфейс, который я получаю на большинстве телефонов, который является правильным, и пользовательский интерфейс, который я получаю на некоторых телефонах, который является неточным.

введите описание изображения здесь Как вы можете видеть, в неточной версии Боттон внизу отсутствует. Особенно это происходит в Sony Xperia серии, где размер экрана составляет 4,6 дюйма и разрешение 720×1280.

Самый простой способ решить эту проблему — изменить значение внутри positioned на 250, что приведет к увеличению всего блока под изображением. Но тогда это некрасиво в некоторых телефонах, потому что закрывает верхнее изображение. У меня есть другой экран, который имеет ту же проблему, что и этот, на нем больше полей. Таким образом, такое решение, как установка positioned значения во что-то другое, не будет работать.

Каково наилучшее решение, чтобы убедиться, что весь экран виден на всех телефонах?

Ответ №1:

Мой метод был бы следующим:

Затем оберните Scaffold с SafeArea (это необязательно)

Если виджет правильно расположен на текущем устройстве, например, на текущем эмуляторе, который имеет разрешение 480x800 . И виджет позиционируется 250px (пример из вашего варианта использования)

тогда оно расположено примерно на 31,25% от верхнего ((250/800) * 100).

Тогда я бы использовал MediaQuery.of(Context).size.height*0.3125 для позиционирования виджета сверху.

Теперь, независимо от высоты телефона, виджет всегда будет располагаться на 31,25% сверху.

Аналогично вы можете сделать и для left позиции/


Мое предложение также заключалось бы в том, чтобы сделать то же самое с шириной и высотой виджета, чтобы размер виджета также был таким же, как на экране устройства. и не выглядит слишком большим или маленьким для некоторых устройств. Не для каждого виджета, но для некоторых.

Ответ №2:

Я изменил ваш код, но у меня нет файлов ресурсов, поэтому вместо этого я изменил SizedBox.

 import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

import 'package:flutter/widgets.dart';

class LoginPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      body: _LoginUI(),
    );
  }
}

class _LoginUI extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _LoginState();
  }
}

class _LoginState extends State<_LoginUI> {
  final _formKey = GlobalKey<FormState>();
  //FIXME When validate error occures, the fields get super small

  TextEditingController _phoneNumber = TextEditingController();
  TextEditingController _passwordController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Container(
      child: SafeArea(
        child: LayoutBuilder(builder:
            (BuildContext context, BoxConstraints viewportConstraints) {
          return SingleChildScrollView(
            reverse: true,
            child: ConstrainedBox(
              constraints: BoxConstraints(
                minHeight: viewportConstraints.maxHeight,
              ),
              child: Column(
                children: <Widget>[
                  Container(
                    margin: EdgeInsets.only(top: 25),
                    // child: Image.asset("assets/images/login_image.png"),
                    child: SizedBox(
                      height: 200,
                      child: Text('Login_image'),
                    ),
                  ),
                  Container(
                    width: MediaQuery.of(context).size.width,
                    decoration: new BoxDecoration(
                        color: Colors.white,
                        borderRadius: new BorderRadius.only(
                            topLeft: const Radius.circular(40.0),
                            topRight: const Radius.circular(40.0))),
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.start,
                      children: <Widget>[
                        Row(
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: <Widget>[
                            Flexible(
                              child: Container(
                                margin: EdgeInsets.only(
                                    top: 20, left: 10, right: 10),
                                child: Container(
                                  height: 50,
                                  child: Text('LOGO'),
                                ),
                                //Image.asset("assets/images/logo.png",
                                //    width: 200, height: 50),
                              ),
                            )
                          ],
                        ),
                        Form(
                          key: _formKey,
                          child: Column(
                            children: <Widget>[
                              Container(
                                  margin: EdgeInsets.only(
                                    top: 40,
                                  ),
                                  child: SizedBox(
                                    width:
                                        MediaQuery.of(context).size.width * .90,
                                    height: 36,
                                    child: TextFormField(
                                      controller: _phoneNumber,
                                      validator: (value) {
                                        if (value.isEmpty) {
                                          return 'Please enter some text';
                                        }
                                        return null;
                                      },
                                      decoration: InputDecoration(
                                        filled: true,
                                        fillColor: Colors.white,
                                        contentPadding: const EdgeInsets.only(
                                            top: 2, bottom: 2, left: 8),
                                        border: OutlineInputBorder(
                                          borderRadius:
                                              BorderRadius.circular(30.0),
                                        ),
                                        hintText: "Email",
                                      ),
                                    ),
                                  )),
                              Container(
                                margin: EdgeInsets.only(
                                  top: 15,
                                ),
                                child: SizedBox(
                                  height: 36,
                                  width:
                                      MediaQuery.of(context).size.width * .90,
                                  child: TextFormField(
                                    controller: _passwordController,
                                    keyboardType: TextInputType.visiblePassword,
                                    validator: (value) {
                                      if (value.isEmpty) {
                                        return 'Please enter some text';
                                      }
                                      return null;
                                    },
                                    decoration: InputDecoration(
                                      filled: true,
                                      fillColor: Colors.white,
                                      contentPadding: const EdgeInsets.only(
                                          top: 2, bottom: 2, left: 8),
                                      border: OutlineInputBorder(
                                        borderRadius:
                                            BorderRadius.circular(30.0),
                                      ),
                                      hintText: "Password",
                                    ),
                                  ),
                                ),
                              ),
                              Align(
                                alignment: Alignment.bottomRight,
                                child: Container(
                                    margin: EdgeInsets.only(
                                        top: 1, left: 10, right: 10),
                                    child: FlatButton(
                                      onPressed: () {
                                        Navigator.pushNamed(
                                            context, "/password-reset");
                                      },
                                      child: Text("Forgot Password?",
                                          style: TextStyle(
                                              fontFamily: 'Roboto-Medium',
                                              fontSize: 14.0,
                                              letterSpacing: 1.25,
                                              color: Color.fromRGBO(
                                                  75, 56, 137, 80))),
                                    )),
                              ),
                              Container(
                                  margin: EdgeInsets.only(
                                      top: 1, left: 10, right: 10),
                                  child: SizedBox(
                                    width:
                                        MediaQuery.of(context).size.width * .90,
                                    child: RaisedButton(
                                      color: Color.fromRGBO(75, 56, 137, 80),
                                      textColor: Colors.white,
                                      shape: RoundedRectangleBorder(
                                          borderRadius:
                                              new BorderRadius.circular(18.0),
                                          side: BorderSide(
                                              color: Color.fromRGBO(
                                                  75, 56, 137, 80))),
                                      child: Text(
                                        "LOGIN",
                                        style:
                                            Theme.of(context).textTheme.button,
                                      ),
                                      onPressed: () {
                                        String email = _phoneNumber.text;
                                        String password =
                                            _passwordController.text;

                                        if (_formKey.currentState.validate()) {
                                          // loginProcess(email, password);
                                        }
                                      },
                                    ),
                                  ))
                            ],
                          ),
                        ),
                        Container(
                            margin:
                                EdgeInsets.only(top: 1, left: 10, right: 10),
                            child: FlatButton(
                              onPressed: () {
                                Navigator.pushNamed(context, "/register");
                              },
                              child: RichText(
                                text: TextSpan(children: <TextSpan>[
                                  TextSpan(
                                    text: "Not a member yet? ",
                                    style: TextStyle(
                                        fontFamily: 'Roboto-Regular',
                                        fontSize: 14.0,
                                        letterSpacing: 0.25,
                                        color: Color.fromRGBO(75, 56, 137, 80)),
                                  ),
                                  TextSpan(
                                    text: "Create an Account",
                                    style: TextStyle(
                                      decoration: TextDecoration.underline,
                                      fontFamily: 'Roboto-Regular',
                                      fontSize: 14.0,
                                      letterSpacing: 0.25,
                                      color: Color.fromRGBO(75, 56, 137, 80),
                                    ),
                                  )
                                ]),
                              ),
                            )),
                        SizedBox(height: 400),
                      ],
                    ),
                  ),
                ],
              ),
            ),
          );
        }),
      ),
    );
    //child: Image.asset("assets/images/login_image.png"),
  }
}