屏幕底部内容在某些手机中不可见

时间:2020-09-04 11:14:50

标签: android ios flutter flutter-layout

我正在开发一个Flutter应用,下面是我的UI代码

def draw_rotated_image(ctx, image_surface, left, top, width, height, angle=0.0, alpha=1.0):
    ctx.save()
    w = image_surface.get_width()
    h = image_surface.get_height()

    # get the new top-left position according to the given angle
    newTopLeft = getTopLeftForRectangleAtAngle(left, top, width, height, angle)

    # translate
    ctx.translate(newTopLeft[0], newTopLeft[1])
    # rotate
    ctx.rotate(angle * math.pi / 180)
    # scale & write
    ctx.scale(width/w, height/h)
    ctx.set_source_surface(image_surface, 0, 0)
    ctx.paint_with_alpha(alpha)

    ctx.restore()
    return

bELOW图像显示我在大多数手机中获得的用户界面是正确的,在某些手机中获得的用户界面是不正确的。

enter image description here 如您所见,在不准确的版本中,缺少底部的按钮。这特别发生在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"), ); } 系列中,其屏幕尺寸为4.6英寸,分辨率为720x1280。

最简单的解决方法是将Sony Xperia内的值更改为250,这会使图像下方的整个块更加向上。但这在某些手机中很难看,因为它覆盖了顶部图像。我有另一个与此问题相同的屏幕,它具有更多字段。因此,将positioned值设置为其他值之类的解决方案将行不通。

什么是最好的解决方案,以确保整个屏幕在所有手机中都可见?

2 个答案:

答案 0 :(得分:1)

我的方法如下:

然后将ScaffoldSafeArea包裹起来(这是可选的)

如果小部件已正确放置在当前设备(例如当前仿真器)中, 分辨率为480x800。小部件位于250px(您的用例中的一个示例)

然后将其定位在距离顶部((250/800)* 100)约31.25%的位置。

然后我将使用MediaQuery.of(Context).size.height*0.3125从顶部放置小部件。

现在,无论手机的高度如何,小部件都将始终位于顶部的31.25%处。

类似地,您也可以为left职位/


我的建议也是对小部件的宽度和高度执行相同的操作,以使小部件的尺寸也与设备屏幕相同。并且对于某些设备而言看起来也不算太大或太小。不是每个小部件,而是某些。

答案 1 :(得分:1)

我更改了您的代码,但没有资产文件,所以我改了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"),
  }
}