接着就开始继续学习UIWidgets主题材质等一系列
我们这节来学习 脚手架 Scaffold类 和 MaterialApp类
这张图是从flutter中找的图
ListTile 用法 必须在MaterialApp类里面才能使用
效果就是这样的
学习ListTile
给ListTile添加Icon
需要在代码中添加这样一段代码 添加一下字体
protected override void OnEnable()
{
base.OnEnable();
FontManager.instance.addFont(Resources.Load<Font>("MaterialIcons-Regular"), "Material Icons",fontWeight:FontWeight.normal);
FontManager.instance.addFont(Resources.Load<Font>("GalleryIcons"), "GalleryIcons");
}
然后这个是使用Icon方法
public override Widget build(BuildContext context)
{
return
new ListTile(
leading:new Icon( icon:Icons.check ),
// leading: new Text(data : "我是领导标题"),
subtitle : new Text(data : "我是副标题"),
//trailing : new Text(data : "我是补充说明"),
trailing :new Icon( icon:Icons.delete ),
title: FQ.Text.Data(mData).SetSize(30).EndText().OnTap(
()=>{
mOnFinish();
}
));
}
接着我们给输入框增加一个外边框 我们知道 Container 的才有外边框的属性
decoration :new BoxDecoration 添加一个BoxDecoration
然后看到的就是这种效果
- 接着我们学习Drawer 这个是存在scaffold 下的 效果就是这种效果
- 接着我们学习PopupMenuButton 这个 可以显示出一个 然后通过内部的itemBuilder 生成一个下拉列表 跟他的Demo一样 复制他的Demo过来
class Choice
{
public Choice(string title, IconData icon)
{
this.title = title;
this.icon = icon;
}
public readonly string title;
public readonly IconData icon;
public static List<Choice> choices = new List<Choice> {
new Choice("Car", Unity.UIWidgets.material.Icons.directions_car),
new Choice("Bicycle", Unity.UIWidgets.material.Icons.directions_bike),
new Choice("Boat", Unity.UIWidgets.material.Icons.directions_boat),
new Choice("Bus", Unity.UIWidgets.material.Icons.directions_bus),
new Choice("Train", Unity.UIWidgets.material.Icons.directions_railway),
new Choice("Walk", Unity.UIWidgets.material.Icons.directions_walk)
};
}
然后构成还放在 scaffold 的actions下面
actions: new List<Widget>(){
new IconButton(icon: new Icon(Icons.image)),
new IconButton(icon: new Icon(Icons.image)),
new PopupMenuButton<Choice>(
onSelected: (choice)=> { Debug.Log(choice.title); },
itemBuilder: (BuildContext subContext) => {
List<PopupMenuEntry<Choice>> popupItems = new List<PopupMenuEntry<Choice>>();
for (int i = 0; i < Choice.choices.Count; i++) {
popupItems.Add(new PopupMenuItem<Choice>(
value: Choice.choices[i],
child: new Text(Choice.choices[i].title)));
}
return popupItems;
}
)
}
实现的效果就是这样
好用
接着我们学习FloatingActionButton 类 依然是在scaffold下的
复制demo里面粘贴进来效果是这样的
就是红色框框圈住的小铃铛
然后接着咱们所做的内容就是如下图所示
选中代办事项列表 和已经完成事项列表 添加保存删除 等操作
我先粘贴代码
这次多了几个类 这个类用来注册重新载入setState方法的
using System;
using MyTestUIWidgets;
namespace MyTestUIWidgets.UIWidgets
{
public class ViewState
{
public static TodoListApp.TodoListPageMode todoListPageMode = TodoListApp.TodoListPageMode.List;
public static Action OnStateChange;
}
}
这个类是从重写视图类 输入框 和下面的显示列表
using Color = Unity.UIWidgets.ui.Color;
using Unity.UIWidgets.foundation;
using System;
using System.Collections.Generic;
using MyTestUIWidgets.UIWidgets;
using Unity.UIWidgets.painting;
using Unity.UIWidgets.widgets;
using UnityEngine;
using Unity.UIWidgets.material;
namespace MyTestUIWidgets.UIWidgets
{
public class TodoView : StatelessWidget
{
private readonly Todo mData;
private readonly Action mOnFinish;
private readonly Action mDelete;
public TodoView(Todo data, Action onFinish, Action onDelete)
{
mData = data;
mOnFinish = onFinish;
mDelete = onDelete;
}
public override Widget build(BuildContext context)
{
return
new ListTile(
leading: new IconButton(icon: new Icon(icon: Icons.check_box_outline_blank, color: Colors.blueAccent, size: 30), onPressed: () => { mOnFinish(); },iconSize:50),
// .OnTap(() =>
// {
// }),
// leading: new Text(data : "我是领导标题"),
subtitle: new Text(data: DateTime.Now.ToString("yyyy年 m月 d日 HH:mm:ss ")),
//trailing : new Text(data : "我是补充说明"),
trailing: new IconButton(icon: new Icon(icon: Icons.delete_outline, color: Colors.redAccent, size: 30), onPressed: () => { mDelete(); },iconSize:50),
// .OnTap(() =>
// {
// mDelete();
// // mOnFinish();
// }),
title: FQ.Text.Data(mData.Content).SetSize(30).EndText());
// FQ.Container
// .Alignment(Alignment.center)
// .Child(
// FQ.Text
// .Data(mData)
// .SetSize(20).EndText()
// )
// .EndContainer().OnTap(() =>
// {
// mOnFinish();
// }));
}
}
public class TodoInputView : StatelessWidget
{
private string mInputContent = string.Empty;
private Action<string> mOnAdd;
public TodoInputView(Action<string> onAdd)
{
mOnAdd = onAdd;
}
public void AddTodo()
{
if (!string.IsNullOrWhiteSpace(mInputContent))
{
mOnAdd(mInputContent);
}
}
public override Widget build(BuildContext context)
{
return
new Container(child:
new Row(children: new List<Widget>(){
FQ.Container.Width(190).Height( 40 ).Dec(Colors.lightBlue).Margin(EdgeInsets.only(left :60))
.Child(FQ.EditableText.FontSize(30)
.OnValueChanged(mInputContent => { this.mInputContent = mInputContent; } )
.OnSubmit(inputvalue => AddTodo())
.EndEditableTextBuilder())
.EndContainer(),
new IconButton( icon: new Icon(Icons.add_box,size:40,color:Colors.green),onPressed:AddTodo),
// FQ.Container.Child(
// new Icon(Icons.add_box,size:40,color:Colors.green)
// .OnTap(() => {
// AddTodo();
// Debug.Log("On Tap");})
// ).Margin(EdgeInsets.only(left:30)).EndContainer()
}
));
}
}
}
这个类用来扩展UIWidgets
using System;
using System.Globalization;
using System.Collections;
using System.Collections.Generic;
using Unity.UIWidgets.gestures;
using Unity.UIWidgets.painting;
using Unity.UIWidgets.widgets;
using UnityEngine;
using Color = Unity.UIWidgets.ui.Color;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.material;
namespace MyTestUIWidgets.UIWidgets
{
public class FQ
{
public static ContainerBuild Container => new ContainerBuild();
public static TextBuilder Text => new TextBuilder();
public static ListViewBuilder ListView => new ListViewBuilder();
public static EditableTextBuilder EditableText => new EditableTextBuilder();
}
public class ContainerBuild
{
private Widget mChild { get; set; }
private Alignment mAlignment { get; set; }
private Color mColor { get; set; }
private EdgeInsets mMargin = EdgeInsets.zero;
//可空参数
private float? mWidth = null;
private float? mHeight = null;
public static ContainerBuild GetBuilder()
{
return new ContainerBuild();
}
public ContainerBuild Child(Widget _child)
{
mChild = _child;
return this;
}
public ContainerBuild Color(Color _color)
{
mColor = _color;
return this;
}
public ContainerBuild Margin(EdgeInsets _edgInsets)
{
mMargin = _edgInsets;
return this;
}
public ContainerBuild Width(float _width)
{
mWidth = _width;
return this;
}
public ContainerBuild Height(float height)
{
mHeight = height;
return this;
}
public ContainerBuild Alignment(Alignment _alignment)
{
mAlignment = _alignment;
return this;
}
private Color mBorderColor = null;
public ContainerBuild Dec(Color color)
{
mBorderColor = color;
return this;
}
public Container EndContainer()
{
return new Container(child: mChild,
alignment: mAlignment,
color: mColor,
width: mWidth,
height:mHeight,
margin: mMargin,
decoration:
mBorderColor != null ? new BoxDecoration(border: Border.all(mBorderColor)) : null);
}
}
public class TextBuilder
{
private string mData { get; set; }
private TextStyle mStyle { get; set; } = new TextStyle();
private int mFontSize { get; set; }
public static TextBuilder GetBuilder()
{
return new TextBuilder();
}
public TextBuilder Data(string _data)
{
mData = _data;
return this;
}
public TextBuilder SetTextStyle(TextStyle _style)
{
mStyle = _style;
return this;
}
public TextBuilder SetSize(int _fountSize)
{
mFontSize = _fountSize;
return this;
}
public Text EndText()
{
if (mFontSize == 0)
{
return new Text(data: mData);
}
else
{
return new Text(data: mData, style: new TextStyle(fontSize: mFontSize));
}
}
}
public class ListViewBuilder
{
List<Widget> mChildren = new List<Widget>();
EdgeInsets mPadding = null;
public static ListViewBuilder GetBuilder()
{
return new ListViewBuilder();
}
public ListViewBuilder Padding(EdgeInsets _madding)
{
mPadding = _madding;
return this;
}
public ListViewBuilder Child(List<Widget> _children)
{
mChildren = _children;
return this;
}
public ListViewBuilder Child(Widget _child)
{
mChildren.Add(_child);
return this;
}
public ListViewBuilder Child(params Widget[] _childeen)
{
mChildren.AddRange(_childeen);
return this;
}
public ListView EndListView()
{
return new ListView(children: mChildren, padding: mPadding);
}
}
public static class GestureDetectorExtension
{
public static GestureDetector OnTap(this Widget _widget, GestureTapCallback onTap)
{
return new GestureDetector(child: _widget, onTap: onTap);
}
}
public class EditableTextBuilder
{
private TextEditingController mInputController = new TextEditingController(text: "");
private FocusNode mFocusNode = new FocusNode();
public TextStyle mStyle = new TextStyle();
public Color mCursorColor = Color.black;
public float mFontSize;
ValueChanged<string> mOnValueChanged = null;
ValueChanged<string> mOnSubmit = null;
public EditableTextBuilder OnValueChanged(ValueChanged<string> _onValueChanged)
{
mOnValueChanged = _onValueChanged;
return this;
}
public EditableTextBuilder OnSubmit(ValueChanged<string> _onSubmit)
{
mOnSubmit = _onSubmit;
return this;
}
public EditableTextBuilder SetInputController(TextEditingController _inputController, FocusNode _focusNode, TextStyle _style, Color _cursorColor)
{
mInputController = _inputController;
mFocusNode = _focusNode;
mStyle = _style;
mCursorColor = _cursorColor;
return this;
}
public EditableTextBuilder FontSize(float size)
{
mFontSize = size;
return this;
}
public EditableTextBuilder GetBuilder()
{
return new EditableTextBuilder();
}
public EditableText EndEditableTextBuilder()
{
return new EditableText(
controller: mInputController,
focusNode: mFocusNode,
style: mFontSize == 0 ? mStyle : new TextStyle(fontSize: mFontSize),
cursorColor: mCursorColor,
onChanged: mOnValueChanged,
onSubmitted: mOnSubmit);
}
}
}
这个类用来保存列表中的数据
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
namespace MyTestUIWidgets.UIWidgets
{
public class Todo
{
public string Content = string.Empty;
public bool Finished = false;
}
public static class Model
{
public static List<Todo> Load()
{
//PlayerPrefs.DeleteAll();
var toDoListContent = PlayerPrefs.GetString("TODO_LIST_KEY", string.Empty);
var splitDatas = toDoListContent.Split(new[] { "@@@@" }, StringSplitOptions.None);
return splitDatas.Where(data => !string.IsNullOrEmpty(data))
.Select(toddData =>
{
var todo = new Todo();
var todoSplitDatas = toddData.Split(new[] { "::::" }, StringSplitOptions.None);
todo.Content = todoSplitDatas[0];
if (todoSplitDatas.Length > 1)
{
todo.Finished = bool.Parse(todoSplitDatas[1]);
}
return todo;
})
.ToList();
}
public static void Save(this List<Todo> self)
{
StringBuilder stringBuilder = new StringBuilder();
self.ForEach(
data =>
{
stringBuilder.Append(data.Content);
stringBuilder.Append("::::");
stringBuilder.Append(data.Finished);
stringBuilder.Append("@@@@");
}
);
PlayerPrefs.SetString("TODO_LIST_KEY", stringBuilder.ToString());
}
}
}
这个类用来构成App
using System.Xml.Linq;
using System;
using System.Text;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using Unity.UIWidgets.engine;
using Unity.UIWidgets.painting;
using Unity.UIWidgets.widgets;
using UnityEngine;
using Color = Unity.UIWidgets.ui.Color;
using MyTestUIWidgets.UIWidgets;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.animation;
using Unity.UIWidgets.material;
using Unity.UIWidgets.ui;
using UnityEditor;
namespace MyTestUIWidgets
{
class Choice
{
public Choice(string title, IconData icon)
{
this.title = title;
this.icon = icon;
}
public readonly string title;
public readonly IconData icon;
public static List<Choice> choices = new List<Choice> {
new Choice("Car", Unity.UIWidgets.material.Icons.directions_car),
new Choice("Bicycle", Unity.UIWidgets.material.Icons.directions_bike),
new Choice("Boat", Unity.UIWidgets.material.Icons.directions_boat),
new Choice("Bus", Unity.UIWidgets.material.Icons.directions_bus),
new Choice("Train", Unity.UIWidgets.material.Icons.directions_railway),
new Choice("Walk", Unity.UIWidgets.material.Icons.directions_walk)
};
}
public class TodoListApp : UIWidgetsPanel
{
protected override void OnEnable()
{
base.OnEnable();
FontManager.instance.addFont(Resources.Load<Font>("MaterialIcons-Regular"), "Material Icons", fontWeight: FontWeight.normal);
FontManager.instance.addFont(Resources.Load<Font>("GalleryIcons"), "GalleryIcons");
}
protected override Widget createWidget()
{
return new MaterialApp(home:
new Scaffold(
appBar: new AppBar(title: new Center(child: FQ.Text.Data("My App").SetSize(20).EndText()),
backgroundColor: Color.black,
// leading: new Icon(Icons.home),
actions: new List<Widget>(){
new IconButton(icon: new Icon(Icons.image,color:Colors.white)),
new IconButton(icon: new Icon(Icons.image,color:Colors.white)),
new PopupMenuButton<Choice>(
onSelected: (choice)=> { Debug.Log(choice.title); },
itemBuilder: (BuildContext subContext) => {
List<PopupMenuEntry<Choice>> popupItems = new List<PopupMenuEntry<Choice>>();
for (int i = 0; i < Choice.choices.Count; i++) {
popupItems.Add(new PopupMenuItem<Choice>(
value: Choice.choices[i],
child: new Text(Choice.choices[i].title)));
}
return popupItems;
}
)
}),
drawer: new Drawer(
child: FQ.ListView.Padding(EdgeInsets.zero).
Child(new Divider()).
Child(new ListTile(leading: new Icon(Icons.list),
title: FQ.Text.Data("代办事项").EndText(), onTap: () =>
{
ViewState.todoListPageMode = TodoListPageMode.List;
Debug.Log("点击了待办事项");
ViewState.OnStateChange.Invoke();
})).
Child(new Divider()).
Child(new ListTile(
leading: new Icon(Icons.check_box),
title: FQ.Text.Data("已完成事项").EndText(), onTap: () =>
{
Debug.Log("点击了已完成");
ViewState.todoListPageMode = TodoListPageMode.Finished;
ViewState.OnStateChange.Invoke();
})
).Child(new Divider())
.EndListView()
),
body: new TodoListPage(),
floatingActionButton: new FloatingActionButton(
backgroundColor: Colors.redAccent,
child: new Icon(Unity.UIWidgets.material.Icons.add_alert),
onPressed: () => { Debug.Log("OnbuttonClick"); }
)
));
}
class TodoListPage : StatefulWidget
{
public override State createState()
{
return new TodoListState();
}
}
public enum TodoListPageMode
{
List,
Finished
}
class TodoListState : State<TodoListPage>
{
private TodoListPageMode mPageMode = TodoListPageMode.Finished;
public override void initState()
{
ViewState.OnStateChange += OnChange;
mTodoDatas = Model.Load();
}
public override void deactivate()
{
ViewState.OnStateChange -= OnChange;
}
void OnChange()
{
this.setState(() => { });
}
private List<Todo> mTodoDatas = null;
public override Widget build(BuildContext context)
{
if (ViewState.todoListPageMode == TodoListPageMode.List)
{
return FQ.ListView
//.Child(new Text(data: "哈哈哈哈哈"))
.Child(new TodoInputView(data => { AddState(data); }))
.Child(ListTodoViews)
.Padding(EdgeInsets.only(0, 50))
.EndListView();
}
else
{
return FQ.ListView
//.Child(new Text(data: "哈哈哈哈哈"))
//.Child(new TodoInputView(data => { AddState(data); }))
.Child(FinishedListView)
.Padding(EdgeInsets.only(0, 50))
.EndListView();
}
}
private void AddState(string data)
{
this.setState(() =>
{
mTodoDatas.Add(new Todo() { Content = data, Finished = false });
Save();
});
}
private void Save()
{
mTodoDatas.Save();
}
Widget[] FinishedListView
{
get
{
var retWidgets = new List<Widget>();
foreach (var data in mTodoDatas.Where(data => data.Finished))
{
retWidgets.Add(new TodoView(data, () =>
{
this.setState(() =>
{
Debug.Log(data.Finished + "未设置");
data.Finished = false;
Debug.Log(data.Finished + "设置后");
});
Save();
},
() =>
{
this.setState(() =>
{
mTodoDatas.Remove(data);
Save();
});
}));
retWidgets.Add(new Divider());
}
return retWidgets.ToArray();
}
}
Widget[] ListTodoViews
{
get
{
var retWidgets = new List<Widget>();
foreach (var data in mTodoDatas.Where(data => !data.Finished))
{
retWidgets.Add(new TodoView(data, () =>
{
this.setState(() =>
{
Debug.Log(data.Finished + "未设置");
data.Finished = true;
Debug.Log(data.Finished + "设置后");
});
Save();
},
() =>
{
this.setState(() =>
{
mTodoDatas.Remove(data);
Save();
});
}));
retWidgets.Add(new Divider());
}
return retWidgets.ToArray();
// return mTodoDatas.Where(data => !data.Finished).Select(data => new TodoView(data, () =>
// {
// this.setState(() =>
// {
// Debug.Log(data.Finished + "未设置");
// data.Finished = true;
// Debug.Log(data.Finished + "设置后");
// });
// Save();
// }, () =>
// {
// this.setState(() =>
// {
// mTodoDatas.Remove(data);
// Save();
// });
// })).ToArray();
}
}
}
}
}
这三节课的Demo我会上传在github上 一会会在下面贴上连接