Flutter中的响应式UI

Posted

技术标签:

【中文标题】Flutter中的响应式UI【英文标题】:responsive Ui in flutter 【发布时间】:2019-06-21 07:05:46 【问题描述】:

在 Ui 边距中,内边距、文本和图像大小被赋予恒定值。我没有使用Fractional boxConstraint box等。我需要根据屏幕大小通过media query设置

我使用了这样的媒体查询,但无法正确设置。

    double width = MediaQuery.of(context).size.width;
    double height = MediaQuery.of(context).size.height;
    double height35 = height * 0.35;

如果我的填充是padding:const EdgeInsets.only(left: 25.0,right: 25.0),我如何从媒体查询中设置填充和其他固定大小。 Here 1, Here 2 是文档和示例,但没有从媒体查询中获得方法..

我也用过这个library,但效果不如我所愿。

这是我的代码。

class _LoginPageState extends State<LoginPage> 
  @override
  Widget build(BuildContext context) 
    MediaQueryData queryData;
    queryData = MediaQuery.of(context);


    double width = MediaQuery.of(context).size.width;
    double height = MediaQuery.of(context).size.height;
    double height35 = height * 0.35;

    return Scaffold(
      body: Container(
          decoration: BoxDecoration(color: Color(0xFFE7F6FD)),
        child: Column(
          children: <Widget>[
            SizedBox(height: height35,),
            Row(
              mainAxisAlignment: MainAxisAlignment.start,
              children: <Widget>[
                Container(
                  height: 50.0,
                  child: IconButton(icon: Icon(Icons.close,color: Color(0xFF005283),size: 36.0,), onPressed: null),
                ),
              ],),
            Container(child: SingleChildScrollView(
              padding:const EdgeInsets.only(left: 25.0,right: 25.0),
              child: Column(
                mainAxisSize: MainAxisSize.max,
                crossAxisAlignment: CrossAxisAlignment.stretch,
                children: <Widget>[
                  Container(
                    height: 60.0,
                    child: Image.asset('assets/images/login_logo.png')),

                  SizedBox(
                    height: 30.0,
                  ),
                  TextFormField(
                    style: new TextStyle(fontSize:18.0,color: Color(0xFF005283)),
                    decoration: InputDecoration(
                      // prefixIcon: Icon(Icons.email, color: Colors.grey),
                        enabledBorder: UnderlineInputBorder(borderSide: new BorderSide(color: Color(0xFF005283))),
                        hintStyle: TextStyle(color: Color(0xFF005283),fontSize:18.0,fontFamily: "WorkSansLight"),
                        hintText: 'Email/Mobile No.'),
                  ),
                  SizedBox(
                    height: 30.0,
                  ),
                  TextFormField(
                    style: new TextStyle(fontSize:18.0,color: Color(0xFF005283)),
                    obscureText: true,
                    decoration: InputDecoration(
                      // prefixIcon: Icon(Icons.email, color: Colors.grey),
                        labelStyle: new TextStyle(color: Colors.blue),
                        enabledBorder: UnderlineInputBorder(borderSide: new BorderSide(color: Color(0xFF005283))),
                        hintStyle: TextStyle(color: Color(0xFF005283),fontSize:18.0,fontFamily: "WorkSansLight"),
                        hintText: 'Password'),
                  ),
                  SizedBox(
                    height: 30.0,
                  ),

                  RaisedButton(
                    onPressed: () 

                    ,
                    shape: new RoundedRectangleBorder(borderRadius: new BorderRadius.circular(60.0)),
                    child: Padding(
                        padding: EdgeInsets.only(top:18.0,bottom: 18.0,left: 10.0,right: 10.0),
                        child: Text('LOG IN',style: new TextStyle(fontSize:18.0,color: Color(0xFF005283),fontFamily: "WorkSansMedium"),)),
                    color: Color(0xFFc1ff02),
                    textColor: Colors.white,),

                  SizedBox(
                    height: 30.0,),
                  Row(
                    children: <Widget>[
                      Expanded(
                        child: Divider(
                          color: Color(0xFF005283),
                          height: 8.0,
                        ),
                      ),
                      SizedBox(
                        width: 8.0,
                      ),
                      Text(
                        'OR CONNECT WITH',
                        style: TextStyle(fontSize:14.0,color: Color(0xFF005283),fontFamily: "WorkSansLight",fontWeight: FontWeight.normal),
                      ),
                     SizedBox(
                          width: 8.0,
                      ),
                      Expanded(
                        child: Divider(
                          color: Color(0xFF005283),
                          height: 8.0,
                        ),
                      )
                    ],
                  ),

                  Row(
                    children: <Widget>[
                      FlatButton.icon(
                          onPressed: null,
                          label: Text('Login with Facebook',style: TextStyle(color: Colors.white),),
                          icon: Icon(Icons.local_gas_station,color: Colors.white,),
                          shape: Border.all(color: Colors.grey,width: 2.0,style: BorderStyle.none ),
                          //shape: new RoundedRectangleBorder(borderRadius: new BorderRadius.circular(30.0),)
                      ),

                      OutlineButton(
                        color: Colors.black,
                          child: new Text("Button text"),
                          onPressed: null,
                          shape: new RoundedRectangleBorder(borderRadius: new BorderRadius.circular(30.0))
                      ),
                    ],
                  ),
                  SizedBox(
                    height: 20.0,
                  ),
              Center(
                child: GestureDetector(
                  onTap: () 
                    Navigator.pushNamed(context, "myRoute");
                  ,
                  child:  RichText(
                    text: new TextSpan(
                      children: <TextSpan>[
                        TextSpan(text:'Not a Member? ',style: TextStyle(color: Color(0xFF005283),fontSize: 14.0,fontWeight: FontWeight.w400),),
                        TextSpan(text:'Register Now',style: TextStyle(color: Color(0xFF005283),fontSize: 18.0,fontWeight: FontWeight.w600),),
                      ],
                    ),
                  ),
                ) ,
              ),
                  SizedBox(
                    height: 20.0,
                  ),

                  OutlineButton(
                      color: Color(0xFF005283),
                      child: new Text("CONTINUE AS GUEST",style: TextStyle(color: Color(0xFF005283),fontSize: 14.0,)),
                      onPressed: null,
                      shape: new RoundedRectangleBorder(borderRadius: new BorderRadius.circular(30.0))
                  ),
            ],),))
          ],
        ),
      ),
    );
  

【问题讨论】:

这有点宽泛。如果您成功获得了MediaQuery,您遇到了什么问题导致您无法使用它? 我已经构建了这个 UI,没有考虑 UI 的响应性只是为了学习。但我没有得到计算媒体查询的方法。例如,如果我有 25 个 dp 填充,我们如何测量 media.query,就像我们可以在 xml 中所做的那样,对于不同的不同设备有不同的 sd 和 dp。 MediaQuery 将返回设备的大小。我倾向于将宽度/高度乘以一小部分。以padding:const EdgeInsets.only(left: width*0.1, right: width*0.1) 为例 @Ross 你是如何决定将宽度乘以 0.1 的? @Ross 你是怎么决定的? 【参考方案1】:

来自 devicePixelRatio 属性的文档: https://docs.flutter.io/flutter/dart-ui/Window/devicePixelRatio.html

每个逻辑像素的设备像素数。这个数字可能 不是二的幂。事实上,它甚至可能不是整数。为了 例如,Nexus 6 的设备像素比为 3.5。

设备像素也称为物理像素。逻辑像素 也称为与设备无关或与分辨率无关 像素。

根据定义,每厘米大约有 38 个逻辑像素,或者 物理显示器每英寸大约有 96 个逻辑像素。价值 devicePixelRatio 返回的最终是从 硬件本身、设备驱动程序或存储在 操作系统或固件,并且可能不准确,有时由 很大的利润。

Flutter 框架以逻辑像素运行,因此很少使用 需要直接处理此属性。

所以你不必担心设备分辨率,但如果你想访问该属性,你可以像下面这样:

double devicePixelRatio = MediaQuery.of(context).devicePixelRatio;

【讨论】:

我如何在填充字段中使用devicePixelRatio @farhana 这取决于你想用它做什么。您究竟想如何根据分辨率更改填充?您想为高分辨率手机添加更多填充吗? 如果我有 25dp 那么我应该相应地更改为屏幕。 @farhana 我真的不明白你到底想做什么。你必须更具体一点。当我编辑我的答案时,您不必担心设备分辨率。

以上是关于Flutter中的响应式UI的主要内容,如果未能解决你的问题,请参考以下文章

Windows Phone 8 中的响应式 UI

如何制作响应式 svg -flutter

Flutter:响应式定位在堆栈中

Flutter Textfield 响应式字体

[UWP]XAML中的响应式布局技术

Getx在flutter中响应式设计