日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Unity的Flutter——UIWidgets简介及入门

發(fā)布時間:2024/4/15 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Unity的Flutter——UIWidgets简介及入门 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

介紹

UIWidgets(https://github.com/UnityTech/UIWidgets)是Unity編輯器的一個插件包,可幫助開發(fā)人員通過Unity引擎來創(chuàng)建、調(diào)試和部署高效的跨平臺應(yīng)用。

UIWidgets主要來自Flutter。但UIWidgets通過使用強大的Unity引擎為開發(fā)人員提供了許多新功能,顯著地改進(jìn)他們開發(fā)的應(yīng)用性能和工作流程。

效率

通過使用最新的Unity渲染SDK,UIWidgets應(yīng)用可以非常快速地運行并且大多數(shù)時間保持大于60fps的速度。

跨平臺

與任何其他Unity項目一樣,UIWidgets應(yīng)用可以直接部署在各種平臺上,包括PC,移動設(shè)備和網(wǎng)頁等。

多媒體支持

除了基本的2D UI之外,開發(fā)人員還能夠?qū)?D模型,音頻,粒子系統(tǒng)添加到UIWidgets應(yīng)用中。

文檔

官方文檔只是簡單介紹,代碼中沒有任何中英文注釋,部分demo還未完成。
不過由于基于Flutter,大部分API與Flutter一致,所以可以參考Flutter文檔,或者先學(xué)習(xí)一下Flutter。

Unity Connect App

Unity Connect App是使用UIWidgets開發(fā)的一個移動App產(chǎn)品,可以在Android下載以及iOS App Store下載最新的版本.

github地址https://github.com/UnityTech/ConnectAppCN.

安裝

首先需要 Unity 2018.3 或更高版本。

新建一個unity項目或一個已有的項目。

訪問UIWidgets的github庫https://github.com/UnityTech/UIWidgets下載最新UIWidgets包,將其移至項目的Package文件夾中

或者可以在終端中通過git命令來完成這個操作:

cd <YourProjectPath>/Packagesgit clone https://github.com/UnityTech/UIWidgets.git com.unity.uiwidgets

官方示例

在示例中,我們將創(chuàng)建一個非常簡單的UIWidgets應(yīng)用。 該應(yīng)用只包含文本標(biāo)簽和按鈕。 文本標(biāo)簽將計算按鈕上的點擊次數(shù)。

首先,使用Unity編輯器打開項目。

場景構(gòu)建

選擇 File > New Scene來創(chuàng)建一個新場景。

選擇 GameObject > UI > Canvas
在場景中創(chuàng)建UI Canvas。

右鍵單擊Canvas并選擇UI > Panel,將面板添加到UI Canvas中。 然后刪除面板中的 Image 組件。

最后為場景命名并保存至Assets/Scenes目錄下

創(chuàng)建部件

創(chuàng)建一個新C#腳本,命名為“UIWidgetsExample.cs”

using System.Collections.Generic;using Unity.UIWidgets.animation;using Unity.UIWidgets.engine;using Unity.UIWidgets.foundation;using Unity.UIWidgets.material;using Unity.UIWidgets.painting;using Unity.UIWidgets.ui;using Unity.UIWidgets.widgets;using UnityEngine;using FontStyle = Unity.UIWidgets.ui.FontStyle;namespace UIWidgetsSample {public class UIWidgetsExample : UIWidgetsPanel {protected override void OnEnable() {// if you want to use your own font or font icons.// FontManager.instance.addFont(Resources.Load<Font>(path: "path to your font"), "font family name");// load custom font with weight & style. The font weight & style corresponds to fontWeight, fontStyle of// a TextStyle object// FontManager.instance.addFont(Resources.Load<Font>(path: "path to your font"), "Roboto", FontWeight.w500,// FontStyle.italic);// add material icons, familyName must be "Material Icons"// FontManager.instance.addFont(Resources.Load<Font>(path: "path to material icons"), "Material Icons");base.OnEnable();}protected override Widget createWidget() {return new WidgetsApp(home: new ExampleApp(),pageRouteBuilder: (RouteSettings settings, WidgetBuilder builder) =>new PageRouteBuilder(settings: settings,pageBuilder: (BuildContext context, Animation<float> animation,Animation<float> secondaryAnimation) => builder(context)));}class ExampleApp : StatefulWidget {public ExampleApp(Key key = null) : base(key) {}public override State createState() {return new ExampleState();}}class ExampleState : State<ExampleApp> {int counter = 0;public override Widget build(BuildContext context) {return new Column(children: new List<Widget> {new Text("Counter: " + this.counter),new GestureDetector(onTap: () => {//這里使用setState來改變counter的值則可以同步改變Text顯示,如果不用直接counter++則無法改變顯示 this.setState(() => {this.counter++;});},child: new Container(padding: EdgeInsets.symmetric(20, 20),color: Colors.blue,child: new Text("Click Me")))});}}}}

保存腳本,并附加到panel中作為其組件。
(如果添加失敗,請檢查文件名與類名是否一致)

保存場景,運行就可以看到效果了。

Image組件

簡單介紹一下Image組件

加載資源文件

將資源圖片放入Assets/Resources目錄下

使用asset函數(shù)即可創(chuàng)建一個Image并加載相應(yīng)資源

Unity.UIWidgets.widgets.Image.asset("test")

注意不需要文件后綴。

加載網(wǎng)絡(luò)資源

Unity.UIWidgets.widgets.Image.network("https://www.baidu.com/img/xinshouyedong_4f93b2577f07c164ae8efa0412dd6808.gif")

Image支持Gif!可以直接加載顯示Gif。

除了上面兩種方式,還可以通過文件和byte數(shù)組來加載資源,函數(shù)分別為file()和memory()。

改變大小等屬性

Unity.UIWidgets.widgets.Image.asset(name: "test",height: 100 )

這里涉及到默認(rèn)參數(shù),先來看一個aseet函數(shù)源碼

public static Image asset(string name,Key key = null,AssetBundle bundle = null,float? scale = null,float? width = null,float? height = null,Color color = null,BlendMode colorBlendMode = BlendMode.srcIn,BoxFit? fit = null,Alignment alignment = null,ImageRepeat repeat = ImageRepeat.noRepeat,Rect centerSlice = null,bool gaplessPlayback = false,FilterMode filterMode = FilterMode.Bilinear) {var image = scale != null? (AssetBundleImageProvider) new ExactAssetImage(name, bundle: bundle, scale: scale.Value): new AssetImage(name, bundle: bundle);return new Image(key,image,width,height,color,colorBlendMode,fit,alignment,repeat,centerSlice,gaplessPlayback,filterMode);}

除了name,其他參數(shù)都設(shè)置了默認(rèn)參數(shù),這樣在使用這個函數(shù)時,無需改變默認(rèn)參數(shù)的參數(shù)不必傳入,這樣就需要傳參時帶上參數(shù)名。但是如果只傳一個name參數(shù)的時候,可以省略參數(shù)名。

所以想改變或設(shè)置Image或其他組件的屬性時,只需要添加對應(yīng)參數(shù)即可。

如改變圖片的拉伸規(guī)則

Unity.UIWidgets.widgets.Image.asset(name: "test",height: 100,width: 100,fit: Unity.UIWidgets.painting.BoxFit.fill )

Navigation頁面跳轉(zhuǎn)

參考官方示例中的demo,簡化代碼如下:

using System; using System.Collections.Generic; using Unity.UIWidgets.animation; using Unity.UIWidgets.engine; using Unity.UIWidgets.foundation; using Unity.UIWidgets.gestures; using Unity.UIWidgets.painting; using Unity.UIWidgets.rendering; using Unity.UIWidgets.ui; using Unity.UIWidgets.widgets; using TextStyle = Unity.UIWidgets.painting.TextStyle;namespace UIWidgetsSample {public class NavigationEx : UIWidgetsPanel{protected override Widget createWidget() {return new WidgetsApp(initialRoute: "/",textStyle: new TextStyle(fontSize: 24),pageRouteBuilder: this.pageRouteBuilder,//初始化所有route路由routes: new Dictionary<string, WidgetBuilder> {{"/", (context) => new HomeScreen()},{"/detail", (context) => new DetailScreen()}});}protected PageRouteFactory pageRouteBuilder {get {return (RouteSettings settings, WidgetBuilder builder) =>new PageRouteBuilder(settings: settings,pageBuilder: (BuildContext context, Animation<float> animation,Animation<float> secondaryAnimation) => builder(context),//設(shè)置轉(zhuǎn)場動畫,去掉則沒有轉(zhuǎn)場動畫transitionsBuilder: (BuildContext context, Animation<float>animation, Animation<float> secondaryAnimation, Widget child) =>new _FadeUpwardsPageTransition(routeAnimation: animation,child: child));}}}//首頁class HomeScreen : StatelessWidget {public override Widget build(BuildContext context) {//封裝了一個NavigationPage,詳細(xì)見后續(xù)代碼return new NavigationPage(body: new Container(//設(shè)置背景色color: new Color(0xFF888888),//Center組件可以實現(xiàn)相對parent居中child: new Center(//設(shè)置按鈕點擊后跳轉(zhuǎn)到“/detail”child: new GestureDetector(onTap: () => { Navigator.pushNamed(context, "/detail"); },child: new Text("Go to Detail")))),title: "Home");}}//詳情頁class DetailScreen : StatelessWidget {public override Widget build(BuildContext context) {return new NavigationPage(body: new Container(color: new Color(0xFF1389FD),child: new Center(child: new Column(children: new List<Widget>() {//設(shè)置按鈕點擊關(guān)閉頁面,回到上一頁new GestureDetector(onTap: () => { Navigator.pop(context); }, child: new Text("Back"))}))),title: "Detail");}}//轉(zhuǎn)場動畫class _FadeUpwardsPageTransition : StatelessWidget {internal _FadeUpwardsPageTransition(Key key = null,Animation<float> routeAnimation = null, // The route's linear 0.0 - 1.0 animation.Widget child = null) : base(key: key) {//設(shè)置滑動的偏移動畫,并且添加了動畫曲線fastOutSlowIn,具體見后面代碼this._positionAnimation = _bottomUpTween.chain(_fastOutSlowInTween).animate(routeAnimation);//設(shè)置顯隱動畫,并且添加了動畫曲線easeIn,具體見后面代碼this._opacityAnimation = _easeInTween.animate(routeAnimation);this.child = child;}//設(shè)置(滑動)動畫的x、y偏移,是百分比值。開始點是x無偏移,y偏移0.25,即從頁面高度的1/4開始。結(jié)束點是無偏移,即原位置。所以動畫是從頁面1/4處向上滑動到頂部static Tween<Offset> _bottomUpTween = new OffsetTween(begin: new Offset(0.0f, 0.25f),end: Offset.zero);//動畫曲線fastOutSlowIn,先加速再減速static Animatable<float> _fastOutSlowInTween = new CurveTween(curve: Curves.fastOutSlowIn);//動畫曲線easeIn,初始緩動static Animatable<float> _easeInTween = new CurveTween(curve: Curves.easeIn);readonly Animation<Offset> _positionAnimation;readonly Animation<float> _opacityAnimation;public readonly Widget child;public override Widget build(BuildContext context) {//轉(zhuǎn)場動畫是包含一個滑動動畫和一個顯隱動畫,是一個層次關(guān)系return new SlideTransition(position: this._positionAnimation,child: new FadeTransition(opacity: this._opacityAnimation,//需要實現(xiàn)動畫的組件child: this.child));}}//封裝了一個導(dǎo)航布局,頂部導(dǎo)航欄,底部頁面內(nèi)容class NavigationPage : StatelessWidget {//頁面內(nèi)容public readonly Widget body;//頁面標(biāo)題,顯示在導(dǎo)航欄public readonly string title;public NavigationPage(Widget body = null, string title = null) {this.title = title;this.body = body;}public override Widget build(BuildContext context) {Widget back = null;//判斷是否可以回退頁面,即頁面列表的size大于1。如果可以則創(chuàng)建back按鈕,點擊關(guān)閉當(dāng)前頁回退到上一頁if (Navigator.of(context).canPop()) {back = new GestureDetector(onTap: () => { Navigator.pop(context); },child: new Text("Go Back"));back = new Column(mainAxisAlignment: MainAxisAlignment.center, children: new List<Widget>() {back});}return new Container(child: new Column(children: new List<Widget>() {//頂部是一個導(dǎo)航欄,這里可以看到用了ConstrainedBox和DecoratedBoxnew ConstrainedBox(constraints: new BoxConstraints(maxHeight: 80),child: new DecoratedBox(decoration: new BoxDecoration(color: new Color(0XFFE1ECF4)),//NavigationToolbar導(dǎo)航工具欄,其中分為三個區(qū)域:左側(cè)leading、中間middle和右側(cè)trailing。這里左側(cè)放置了回退按鈕child: new NavigationToolbar(leading: back,middle: new Text(this.title, textAlign: TextAlign.center)))),//內(nèi)容部分。這里使用了一個Flexible,作用是可以填滿剩余的空間,如果使用普通的container無法達(dá)到效果new Flexible(child: this.body)}));}} }

可以看到在創(chuàng)建WidgetsApp時,設(shè)定所有路由的路徑和實現(xiàn),然后通過Navigator類切換路徑來控制頁面跳轉(zhuǎn)。

Material

UIWidgets同樣提供了Material風(fēng)格的組件,通過一個demo簡單認(rèn)識一下

using System.Collections.Generic; using Unity.UIWidgets.animation; using Unity.UIWidgets.engine; 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 UnityEngine; using Image = Unity.UIWidgets.widgets.Image;namespace UIWidgetsEx {public class MaterialEx : UIWidgetsPanel{protected override Widget createWidget(){return new MaterialApp(home: new MaterialThemeSampleWidget(),darkTheme: new ThemeData(primaryColor: Colors.black26));}protected override void OnEnable(){//加載Material字體,用于iconFontManager.instance.addFont(Resources.Load<Font>(path: "MaterialIcons-Regular"), "Material Icons");base.OnEnable();}}public class MaterialThemeSampleWidget : StatefulWidget{public override State createState(){return new _MaterialThemeSampleWidgetState();}}class _MaterialThemeSampleWidgetState : State<MaterialThemeSampleWidget>{//GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>.key("lalala");public override Widget build(BuildContext context){return new Theme(//data設(shè)置樣式data: new ThemeData(appBarTheme: new AppBarTheme(color: Colors.purple),bottomAppBarTheme: new BottomAppBarTheme(color: Colors.blue),cardTheme: new CardTheme(color: Colors.red,//設(shè)置深度,即陰影大小elevation: 2.0f)),//頁面根布局是一個Scaffold,大致分為三個區(qū)域appBar、body和bottomNavigationBar。child: new Scaffold(//key: scaffoldKey,//導(dǎo)航欄AppBarappBar: new AppBar(//設(shè)置深度,即陰影大小//elevation: 25f,title: new Text("Test App Bar Theme")),body: new Center(//組件Card,自帶陰影效果child: new Card(//設(shè)置深度,即陰影大小//elevation: 25f,//設(shè)置圓角borderRadius,還可以設(shè)置邊框sideshape: new RoundedRectangleBorder(//side: new BorderSide(Colors.blue, 5.0f),borderRadius: BorderRadius.all(5.0f)),child: new Container(height: 250,child: new Column(children: new List<Widget> {Image.asset("products/backpack",fit: BoxFit.cover,width: 200,height: 200),new Text("Card Theme")})))),//底部是BottomAppBarbottomNavigationBar: new BottomAppBar(child: new Row(mainAxisSize: MainAxisSize.max,//設(shè)置對齊方式mainAxisAlignment: MainAxisAlignment.spaceBetween,children: new List<Widget> {//底部是兩個IconButton,使用字體中的iconnew IconButton(icon: new Icon(Unity.UIWidgets.material.Icons.menu), onPressed: () => { }),new IconButton(icon: new Icon(Unity.UIWidgets.material.Icons.account_balance), onPressed: () => { })}))//,//floatingActionButton: new FloatingActionButton(// child: new Text("go"),// onPressed: () => {// scaffoldKey.currentState.showSnackBar(// new SnackBar(// content: new Text("go")// )// );// }//),//floatingActionButtonLocation: FloatingActionButtonLocation.endDocked));}} }

有關(guān)Material部分跟Android基本一致,比如組件都有深度屬性elevation,比如Card就是Material中的CardView。

IconButtom使用字體Font,實際上就是5.0之后引入的SVG,即Vector Image

我們簡單補充一下:

Scaffold

實際上對應(yīng)著Android中的CoordinateLayout,分為三大區(qū)域appBar、body和bottomNavigationBar,當(dāng)未設(shè)置時則隱藏該區(qū)域,body會補充填充。

除了三大區(qū)域還包括:懸浮按鈕floatingActionButton、bottomSheet、drawer、endDrawer等

其中floatingActionButton同樣保持著android中的behavior效果,下面會詳細(xì)介紹

AppBar

AppBar則包含:title、左側(cè)leading、右側(cè)擴展菜單actions

MainAxisAlignment

對齊方式,這個對齊方式相對于android更靈活一些,包括:

  • start 左(上)側(cè)對齊
  • end 右(下)側(cè)對齊
  • center 居中對齊
  • spaceBetween 每兩個item的間隔space相同,兩側(cè)的item與父布局沒有間隔
  • spaceAround 每個item四周都有同樣的間隔,相當(dāng)于margin,所以兩個item之間是兩倍間隔
  • spaceEvenly item在父布局中均勻分布,即所有間隔相同

FloatingActionButton

在Scaffold中floatingActionButton和floatingActionButtonLocation要搭配使用,floatingActionButtonLocation決定著按鈕的位置,包含:

  • endFloat: body的右下角
  • endDocked: bottomNavigationBar右側(cè),中心錨點在bottomNavigationBar的頂端
  • centerDocked: bottomNavigationBar中間,中心錨點在bottomNavigationBar的頂端
  • centerFloat: body的底部中間
  • startTop:appBar左側(cè),中心錨點appBar的底端
  • miniStartTop:與startTop類似,與左側(cè)間隔更小一點
  • endTop:appBar右側(cè),中心錨點appBar的底端

除了上面這些我們還可以實現(xiàn)FloatingActionButtonLocation這個抽象類自定義位置

SnackBar

在Android中FloatingActionButton是存在一個默認(rèn)behavior的,最明顯的就是與SnackBar互動。

在UIWidgets中也有SnackBar組件,使用起來比較簡單。

首先需要創(chuàng)建一個GlobalKey,并將它賦給Scaffold的key。這樣我們就可以使用
scaffoldKey.currentState.showSnackBar()這個函數(shù)來顯示一個SnackBar。

Animation

在前面的示例中我們使用了轉(zhuǎn)場動畫,但是并沒有體現(xiàn)動畫的完整應(yīng)用,因為部分邏輯比如執(zhí)行動畫等封裝在底層了。下面這個例子將完整的展現(xiàn)如何創(chuàng)建并執(zhí)行一個動畫。

using System.Collections.Generic; using Unity.UIWidgets.animation; using Unity.UIWidgets.cupertino; using Unity.UIWidgets.engine; using Unity.UIWidgets.foundation; using Unity.UIWidgets.scheduler; using Unity.UIWidgets.ui; using Unity.UIWidgets.widgets;namespace UIWidgetsSample {public class AnimEx : UIWidgetsPanel{protected override void OnEnable(){base.OnEnable();}protected override Widget createWidget(){return new WidgetsApp(home: new ExampleApp(),pageRouteBuilder: (RouteSettings settings, WidgetBuilder builder) =>new PageRouteBuilder(settings: settings,pageBuilder: (BuildContext context, Animation<float> animation,Animation<float> secondaryAnimation) => builder(context)));}class ExampleApp : StatefulWidget{public ExampleApp(Key key = null) : base(key){}public override State createState(){return new ExampleState();}}class ExampleState : State<ExampleApp>{//IconData iconData = Unity.UIWidgets.material.Icons.menu;//Curve switchCurve = new Interval(0.4f, 1.0f, curve: Curves.fastOutSlowIn);//TextAnim類用一個動畫組件將Image組件封裝起來,見后面TextAnim textAnim = new TextAnim();public override Widget build(BuildContext context){return new Column(children: new List<Widget> {切換動畫//new AnimatedSwitcher(// duration: new System.TimeSpan(0, 0, 1),// switchInCurve: switchCurve,// switchOutCurve: switchCurve,// child: new IconButton(// //不同的key才會認(rèn)為是不同的組件,否則不會執(zhí)行動畫// key: new ValueKey<IconData>(iconData),// icon: new Icon(icon :iconData, color: Colors.white),// onPressed: () => {// this.setState(() => {// if (iconData.Equals(Unity.UIWidgets.material.Icons.menu))// {// iconData = Unity.UIWidgets.material.Icons.close;// }// else// {// iconData = Unity.UIWidgets.material.Icons.menu;// }// });// }// )//),//這里使用了Cupertino風(fēng)格的buttonnew CupertinoButton(onPressed: () => {//點擊后通過controller執(zhí)行動畫textAnim.controller.forward(); },child: new Text("Go"),color: CupertinoColors.activeBlue),textAnim.build(context)});}}//繼承SingleTickerProviderStateMixin,這是TickerProvider接口的實現(xiàn)類private class TextAnim : SingleTickerProviderStateMixin<ExampleApp>{public AnimationController controller = null;public override Widget build(BuildContext context){//定一個一個AnimationController。TimeSpan(0, 0, 2)代表0小時0分2秒,也就是動畫時長是兩秒controller = new AnimationController(duration: new System.TimeSpan(0, 0, 2), vsync: this);//設(shè)置動畫監(jiān)聽,當(dāng)結(jié)束時還原controller.addStatusListener((status) => {if(status == AnimationStatus.completed){controller.reset();}});//定義Animation,從原點下移自身兩個高度Animation<Offset> offset = controller.drive(new OffsetTween(begin: Offset.zero,end: new Offset(0.0f, 2f)));//創(chuàng)建一個滑動動畫組件return new SlideTransition(position: offset,child: Unity.UIWidgets.widgets.Image.asset(name: "test",height: 100));}}}}

執(zhí)行后點擊button,圖片會執(zhí)行下移動畫,執(zhí)行完回到原位置。

當(dāng)然我們還可以設(shè)置動畫曲線、組合多個動畫等等。

而且我們可以看到使用了ios的Cupertino風(fēng)格的button。與Material一樣,UIWidgets也有一套Cupertino風(fēng)格的組件。

vsync

創(chuàng)建AnimationController時,需要設(shè)置一個vsync,是TickerProvider類型的,即計時器。那么這個東西到底有什么用?

vsync對象會綁定動畫的定時器到一個可視的widget,所以當(dāng)widget不顯示時,動畫定時器將會暫停,當(dāng)widget再次顯示時,動畫定時器重新恢復(fù)執(zhí)行,這樣就可以避免動畫相關(guān)UI不在當(dāng)前屏幕時消耗資源。

AnimatedSwitcher

切換動畫,可以同時對其新、舊子元素添加顯示、隱藏動畫。新舊子元素可以是是兩個組件,也可以利用key將一個組件同時用于新舊子元素。

Demo

github

超強干貨來襲 云風(fēng)專訪:近40年碼齡,通宵達(dá)旦的技術(shù)人生

總結(jié)

以上是生活随笔為你收集整理的Unity的Flutter——UIWidgets简介及入门的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。