Flutter中的响应式UI
Posted
技术标签:
【中文标题】Flutter中的响应式UI【英文标题】:responsive Ui in flutter 【发布时间】:2019-06-21 07:05:46 【问题描述】:在 Ui 边距中,内边距、文本和图像大小被赋予恒定值。我没有使用Fractional box
和Constraint 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的主要内容,如果未能解决你的问题,请参考以下文章