UIWidgets没有提供完整文档, 称可以去看Flutter的文档 中文 英文
控件(Control)在Flutter中称为"Widget", 一个界面的若干控件是通过widget的组合实现的
通过UI容器类可以组合控件
Row
是其中一种容器
using System.Collections.Generic;
using Unity.UIWidgets.engine;
using Unity.UIWidgets.painting;
using Unity.UIWidgets.widgets;
using UnityEngine;
public class TestPanel : UIWidgetsPanel
{
protected override Widget createWidget() => new Counter1();
class Counter1 : StatelessWidget
{
public override Widget build(BuildContext context)
{
Text text = new Text(
data: "Hello world",
style: new TextStyle(
color: Unity.UIWidgets.ui.Color.white,
fontSize: 20,
fontStyle: Unity.UIWidgets.ui.FontStyle.italic
)
);
GestureDetector gestureDetector = new GestureDetector(
child: text,
onTap: () =>
{
Debug.Log("Rua!");
}
);
Text text2 = new Text(
data: "line 2!"
);
Row row = new Row(
children: new List<Widget>
{
gestureDetector,
text2,
}
);
return row;
}
}
}
效果如下
继承自MultiChildRenderObjectWidget
的大多数UI容器类的都可以设置children属性, 如Flex
, Row
, Column
, ListBody
, Stack
, Wrap
, CustomMultiChildLayout
等, 具体用法还需要查看Flutter文档
通过组合做一个稍复杂一点的界面
下面我打算做一个特别简单的表单, 可以输入几个值(不检验), 点击按钮可以输出一个拼接的字符串. 为了这个需求, 需要
- 查询UGUI的InputField在Flutter中对应的Widget
- 规划一下布局
- 编码测试
使用Material风格控件
基本widgets中似乎没有按钮, 前面使用Text + GestureDetectoronTap来实现一个点击响应很反麻烦
引入Material风格控件后可以简化一些操作using using Unity.UIWidgets.material;
RaisedButton button = new RaisedButton(
child: new Text(
data: "确定"
),
onPressed: () =>
{
Debug.Log("Rua!");
}
);
RaisedButton
是带阴影的按钮, 自带点击动效, 效果不错
然后是文本输入控件....不知道要怎么做才能对, TextFormFieldTextFieldEditableText直接报错
之后按照material风格结构创建一下, TextFormFieldTextField可以用了
using System.Collections.Generic;
using UIWidgets.Runtime.material;
using Unity.UIWidgets.animation;
using Unity.UIWidgets.engine;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.material;
using Unity.UIWidgets.painting;
using Unity.UIWidgets.rendering;
using Unity.UIWidgets.service;
using Unity.UIWidgets.ui;
using Unity.UIWidgets.widgets;
using Color = Unity.UIWidgets.ui.Color;
using UnityEngine;
public class TestPanel : UIWidgetsPanel
{
protected override Widget createWidget()
{
return new MaterialApp(
home: new MyWidget()
);
}
class MyWidget : StatefulWidget
{
public override State createState()
{
return new MyState();
}
}
class MyState : State<MyWidget>
{
public override Widget build(BuildContext context)
{
TextFormField text = new TextFormField(
decoration: new InputDecoration(
border: new OutlineInputBorder(),
labelText: "hello"
)
);
RaisedButton button = new RaisedButton(
child: new Text("confirm"),
onPressed: () => { Debug.Log("Rua!!!"); }
);
Column column = new Column(
children: new List<Widget>()
{
new Padding(padding: EdgeInsets.symmetric(vertical: 20.0f)),
text,
new Padding(padding: EdgeInsets.symmetric(vertical: 10.0f)),
button,
}
);
Center center = new Center(
child: column
);
Container container = new Container(
child: center
);
Scaffold scaffold = new Scaffold(
appBar: new AppBar(
title: new Text("Test")
),
body: container
);
return scaffold;
}
}
}
实现简单的表单
using System.Collections.Generic;
using UIWidgets.Runtime.material;
using Unity.UIWidgets.animation;
using Unity.UIWidgets.engine;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.material;
using Unity.UIWidgets.painting;
using Unity.UIWidgets.rendering;
using Unity.UIWidgets.service;
using Unity.UIWidgets.ui;
using Unity.UIWidgets.widgets;
using Color = Unity.UIWidgets.ui.Color;
using UnityEngine;
public class TestPanel : UIWidgetsPanel
{
protected override Widget createWidget()
{
return new MaterialApp(
home: new MyWidget()
);
}
class MyWidget : StatefulWidget
{
public override State createState()
{
return new MyState();
}
}
class MyState : State<MyWidget>
{
readonly TextEditingController m_NameController = new TextEditingController();
//readonly TextEditingController m_AgeController = new TextEditingController();
public override void dispose()
{
m_NameController.dispose();
//m_AgeController.dispose();
base.dispose();
}
public override Widget build(BuildContext context)
{
TextFormField nameField = new TextFormField(
controller: m_NameController,
decoration: new InputDecoration(
labelText: "姓名 *",
hintText: "在此输入姓名(不超过十个字)"
),
maxLength: 10,
autovalidate: true,
validator: (text) =>
{
if (string.IsNullOrEmpty(text))
{
return "名字不可为空";
}
else
{
return null;
}
},
onEditingComplete: () => { Debug.Log("编辑结束"); },
onSaved: (text) => { Debug.Log("保存 " + text); },
onFieldSubmitted: (text) => { Debug.Log("提交 " + text); }
);
//TextFormField ageField = new TextFormField(
// controller: m_AgeController,
// decoration: new InputDecoration(
// labelText: "年龄 *",
// hintText: "在此输入年龄"
// ),
// initialValue: "0",
// autovalidate: true,
// validator: (text) =>
// {
// if (!int.TryParse(text, out int age))
// {
// return "只能输入数字";
// }
// else
// {
// return null;
// }
// }
// );
RaisedButton button = new RaisedButton(
child: new Text("confirm"),
onPressed: () =>
{
Debug.Log($"名字: {nameField.controller?.text}, 年龄: ageField.controller?.text");
}
);
Column column = new Column(
children: new List<Widget>()
{
nameField,
//ageField,
button,
}
);
Container container = new Container(
child: column,
padding: EdgeInsets.all(10.0f)
);
Scaffold scaffold = new Scaffold(
appBar: new AppBar(
title: new Text("Test")
),
body: container
);
return scaffold;
}
}
}
不知道是bug还是规定feature...在同一个State的build中用两个TextEditorController就会报错...只好去掉一个
毕竟早期阶段...文档不全各种坑踩起来很难受