介绍

UIWidgets(https://github.com/UnityTech/UIWidgets)是Unity编辑器的一个插件包,可帮助开发人员通过Unity引擎来创建、调试和部署高效的跨平台应用。

UIWidgets主要来自Flutter。但UIWidgets通过使用强大的Unity引擎为开发人员提供了许多新功能,显著地改进他们开发的应用性能和工作流程。

效率

通过使用最新的Unity渲染SDK,UIWidgets应用可以非常快速地运行并且大多数时间保持大于60fps的速度。

跨平台

与任何其他Unity项目一样,UIWidgets应用可以直接部署在各种平台上,包括PC,移动设备和网页等。

多媒体支持

除了基本的2D UI之外,开发人员还能够将3D模型,音频,粒子系统添加到UIWidgets应用中。

文档

官方文档只是简单介绍,代码中没有任何中英文注释,部分demo还未完成。
不过由于基于Flutter,大部分API与Flutter一致,所以可以参考Flutter文档,或者先学习一下Flutter。

Unity Connect App

Unity Connect App是使用UIWidgets开发的一个移动App产品,可以在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

官方示例

在示例中,我们将创建一个非常简单的UIWidgets应用。 该应用只包含文本标签和按钮。 文本标签将计算按钮上的点击次数。

首先,使用Unity编辑器打开项目。

场景构建

选择 File > New Scene来创建一个新场景。

选择 GameObject > UI > Canvas
在场景中创建UI Canvas。

右键单击Canvas并选择UI > Panel,将面板添加到UI Canvas中。 然后删除面板中的 Image 组件。

最后为场景命名并保存至Assets/Scenes目录下

创建部件

创建一个新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函数即可创建一个Image并加载相应资源

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

注意不需要文件后缀。

加载网络资源

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

Image支持Gif!可以直接加载显示Gif。

除了上面两种方式,还可以通过文件和byte数组来加载资源,函数分别为file()和memory()。

改变大小等属性

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

这里涉及到默认参数,先来看一个aseet函数源码

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,其他参数都设置了默认参数,这样在使用这个函数时,无需改变默认参数的参数不必传入,这样就需要传參时带上参数名。但是如果只传一个name参数的时候,可以省略参数名。

所以想改变或设置Image或其他组件的属性时,只需要添加对应参数即可。

如改变图片的拉伸规则

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

Navigation页面跳转

参考官方示例中的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),//设置转场动画,去掉则没有转场动画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,详细见后续代码return new NavigationPage(body: new Container(//设置背景色color: new Color(0xFF888888),//Center组件可以实现相对parent居中child: new Center(//设置按钮点击后跳转到“/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>() {//设置按钮点击关闭页面,回到上一页new GestureDetector(onTap: () => { Navigator.pop(context); }, child: new Text("Back"))}))),title: "Detail");}}//转场动画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) {//设置滑动的偏移动画,并且添加了动画曲线fastOutSlowIn,具体见后面代码this._positionAnimation = _bottomUpTween.chain(_fastOutSlowInTween).animate(routeAnimation);//设置显隐动画,并且添加了动画曲线easeIn,具体见后面代码this._opacityAnimation = _easeInTween.animate(routeAnimation);this.child = child;}//设置(滑动)动画的x、y偏移,是百分比值。开始点是x无偏移,y偏移0.25,即从页面高度的1/4开始。结束点是无偏移,即原位置。所以动画是从页面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) {//转场动画是包含一个滑动动画和一个显隐动画,是一个层次关系return new SlideTransition(position: this._positionAnimation,child: new FadeTransition(opacity: this._opacityAnimation,//需要实现动画的组件child: this.child));}}//封装了一个导航布局,顶部导航栏,底部页面内容class NavigationPage : StatelessWidget {//页面内容public readonly Widget body;//页面标题,显示在导航栏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。如果可以则创建back按钮,点击关闭当前页回退到上一页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>() {//顶部是一个导航栏,这里可以看到用了ConstrainedBox和DecoratedBoxnew ConstrainedBox(constraints: new BoxConstraints(maxHeight: 80),child: new DecoratedBox(decoration: new BoxDecoration(color: new Color(0XFFE1ECF4)),//NavigationToolbar导航工具栏,其中分为三个区域:左侧leading、中间middle和右侧trailing。这里左侧放置了回退按钮child: new NavigationToolbar(leading: back,middle: new Text(this.title, textAlign: TextAlign.center)))),//内容部分。这里使用了一个Flexible,作用是可以填满剩余的空间,如果使用普通的container无法达到效果new Flexible(child: this.body)}));}}
}

可以看到在创建WidgetsApp时,设定所有路由的路径和实现,然后通过Navigator类切换路径来控制页面跳转。

Material

UIWidgets同样提供了Material风格的组件,通过一个demo简单认识一下

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设置样式data: new ThemeData(appBarTheme: new AppBarTheme(color: Colors.purple),bottomAppBarTheme: new BottomAppBarTheme(color: Colors.blue),cardTheme: new CardTheme(color: Colors.red,//设置深度,即阴影大小elevation: 2.0f)),//页面根布局是一个Scaffold,大致分为三个区域appBar、body和bottomNavigationBar。child: new Scaffold(//key: scaffoldKey,//导航栏AppBarappBar: new AppBar(//设置深度,即阴影大小//elevation: 25f,title: new Text("Test App Bar Theme")),body: new Center(//组件Card,自带阴影效果child: new Card(//设置深度,即阴影大小//elevation: 25f,//设置圆角borderRadius,还可以设置边框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,//设置对齐方式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));}}
}

有关Material部分跟Android基本一致,比如组件都有深度属性elevation,比如Card就是Material中的CardView。

IconButtom使用字体Font,实际上就是5.0之后引入的SVG,即Vector Image

我们简单补充一下:

Scaffold

实际上对应着Android中的CoordinateLayout,分为三大区域appBar、body和bottomNavigationBar,当未设置时则隐藏该区域,body会补充填充。

除了三大区域还包括:悬浮按钮floatingActionButton、bottomSheet、drawer、endDrawer等

其中floatingActionButton同样保持着android中的behavior效果,下面会详细介绍

AppBar

AppBar则包含:title、左侧leading、右侧扩展菜单actions

MainAxisAlignment

对齐方式,这个对齐方式相对于android更灵活一些,包括:

  • start 左(上)侧对齐
  • end 右(下)侧对齐
  • center 居中对齐
  • spaceBetween 每两个item的间隔space相同,两侧的item与父布局没有间隔
  • spaceAround 每个item四周都有同样的间隔,相当于margin,所以两个item之间是两倍间隔
  • spaceEvenly item在父布局中均匀分布,即所有间隔相同

FloatingActionButton

在Scaffold中floatingActionButton和floatingActionButtonLocation要搭配使用,floatingActionButtonLocation决定着按钮的位置,包含:

  • endFloat: body的右下角
  • endDocked: bottomNavigationBar右侧,中心锚点在bottomNavigationBar的顶端
  • centerDocked: bottomNavigationBar中间,中心锚点在bottomNavigationBar的顶端
  • centerFloat: body的底部中间
  • startTop:appBar左侧,中心锚点appBar的底端
  • miniStartTop:与startTop类似,与左侧间隔更小一点
  • endTop:appBar右侧,中心锚点appBar的底端

除了上面这些我们还可以实现FloatingActionButtonLocation这个抽象类自定义位置

SnackBar

在Android中FloatingActionButton是存在一个默认behavior的,最明显的就是与SnackBar互动。

在UIWidgets中也有SnackBar组件,使用起来比较简单。

首先需要创建一个GlobalKey,并将它赋给Scaffold的key。这样我们就可以使用
scaffoldKey.currentState.showSnackBar()这个函数来显示一个SnackBar。

Animation

在前面的示例中我们使用了转场动画,但是并没有体现动画的完整应用,因为部分逻辑比如执行动画等封装在底层了。下面这个例子将完整的展现如何创建并执行一个动画。

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才会认为是不同的组件,否则不会执行动画//        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风格的buttonnew CupertinoButton(onPressed: () => {//点击后通过controller执行动画textAnim.controller.forward(); },child: new Text("Go"),color: CupertinoColors.activeBlue),textAnim.build(context)});}}//继承SingleTickerProviderStateMixin,这是TickerProvider接口的实现类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);//设置动画监听,当结束时还原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)));//创建一个滑动动画组件return new SlideTransition(position: offset,child: Unity.UIWidgets.widgets.Image.asset(name: "test",height: 100));}}}}

执行后点击button,图片会执行下移动画,执行完回到原位置。

当然我们还可以设置动画曲线、组合多个动画等等。

而且我们可以看到使用了ios的Cupertino风格的button。与Material一样,UIWidgets也有一套Cupertino风格的组件。

vsync

创建AnimationController时,需要设置一个vsync,是TickerProvider类型的,即计时器。那么这个东西到底有什么用?

vsync对象会绑定动画的定时器到一个可视的widget,所以当widget不显示时,动画定时器将会暂停,当widget再次显示时,动画定时器重新恢复执行,这样就可以避免动画相关UI不在当前屏幕时消耗资源。

AnimatedSwitcher

切换动画,可以同时对其新、旧子元素添加显示、隐藏动画。新旧子元素可以是是两个组件,也可以利用key将一个组件同时用于新旧子元素。

Demo

github

Unity的Flutter——UIWidgets简介及入门相关推荐

  1. Python之路【第一篇】:Python简介和入门

    Python之路[第一篇]:Python简介和入门 Python简介 Python前世今生 python的创始人为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间,吉多·范罗 ...

  2. AI之FL:联邦学习(Federated Learning)的简介、入门、应用之详细攻略

    AI之FL:联邦学习(Federated Learning)的简介.入门.应用之详细攻略 导读       2019 年2 月,微众银行 AI 团队自主研发的全球首个工业级联邦学习框架 FATE(Fe ...

  3. DL之CG:Computational Graph计算图的简介、入门、使用之详细攻略

    DL之CG:Computational Graph计算图的简介.入门.使用之详细攻略 目录 计算图的简介 计算图的入门 CG与局部计算 计算图的使用 计算图的简介 计算图Computational G ...

  4. Windows PowerShell:Windows PowerShell的简介、入门、使用方法之详细攻略

    Windows PowerShell:Windows PowerShell的简介.入门.使用方法之详细攻略 目录 Windows PowerShell的简介 PowerShell VS Unix Sh ...

  5. Ubuntu:Ubuntu下安装Anaconda和Tensorflow的简介、入门、安装流程之详细攻略

    Ubuntu:Ubuntu下安装Anaconda和Tensorflow的简介.入门.安装流程之详细攻略 目录 安装流程 1.安装nvidia显卡驱动 2.安装cuda8 3.安装Cudnn 4.Ana ...

  6. Py之GUI之PyQt:PyQt5的简介、入门、安装(QtCreator和QtDesigner)图文教程之详细攻略

    Py之GUI之PyQt:PyQt5的简介.入门.安装(QtCreator和QtDesigner)图文教程之详细攻略 目录 PyQt的简介 1.Qt特点 2.QT中QT Widgets Applicat ...

  7. TF学习——TF之Tensorboard:Tensorflow之Tensorboard可视化简介、入门、使用方法之详细攻略

    TF学习--TF之Tensorboard:Tensorflow之Tensorboard可视化简介.入门.使用方法之详细攻略 目录 Tensorboard简介 Tensorboard各个板块入门 Ten ...

  8. OpenCV-Python实战(18)——深度学习简介与入门示例

    OpenCV-Python实战(18)--深度学习简介与入门示例 0. 前言 1. 计算机视觉中的深度学习简介 1.1 深度学习的特点 1.2 深度学习大爆发 2. 用于图像分类的深度学习简介 3. ...

  9. Python自动化开发【1】:Python简介和入门

    Python自动化开发之路 [第1篇]:Python简介和入门 编程与编程语言 一 编程与编程语言python是一门编程语言,作为学习python的开始,需要事先搞明白:编程的目的是什么?什么是编程语 ...

最新文章

  1. 微信小程序开发优秀教程及文章合集第一期
  2. python打开文件不存在-Python判断文件是否存在的三种方法
  3. 浅谈Dynamic 关键字系列之二:调用属性,方法,字段
  4. C# DataGrid 控件在winform里显示行号
  5. 提升购物体验,跨境电商如何做企业管理?
  6. pytorch简单代码实现deep dream图(即CNN特征可视化 features visualization)
  7. Qt 6的Qt 3D会是什么样?
  8. 《自卑与超越》读书笔记(part1)--行为举止永远受到人生意义的制约
  9. LeetCode 1312. 让字符串成为回文串的最少插入次数(区间DP)
  10. 有关javaScript面向对象和原型笔记
  11. 高性能HTTP加速器Varnish(管理维护篇)
  12. 软件测试面试题!收藏起来,每天看一看,月薪20K!
  13. EXCEL 趋势图生成的公式应用说明
  14. html浮窗音乐播放器插件,墨涩网 - WordPress浮窗音乐播放器Floating Window Music Player V3.2.6——墨涩网...
  15. 在腾讯云主机上使用URLOS一键安装yoshop萤火虫小程序商城
  16. jspstudy启动mysql失败_解决Mysql5.7.17在windows下安装启动时提示不成功问题
  17. word2016文档在正文分栏情况下而时脚注不分栏
  18. 2-2.基金的投资交易与结算
  19. 微软让草稿几秒钟变App,还推出了个像Mac Mini的迷你台式机 | Build 2022
  20. Android基础知识 — 1.3-ARM和Thumb指令详解1

热门文章

  1. android 开发时遇到的环境问题3--eclipse整个项目工程报错
  2. asp.net常用函数 选择自 UAM_Richard 的 Blog
  3. Vue 新手学习笔记:vue-element-admin 之安装,配置及入门开发
  4. 吴裕雄 Bootstrap 前端框架开发——Bootstrap 排版:移除默认的列表样式
  5. HP-UX平台安装Oracle11gR2数据库
  6. Modbus RTU 通信应用案例
  7. 基础 - jQuery选项卡
  8. emacs 新手笔记(四) —— 使用 dired 完成一些简单的文件和目录操作
  9. ecmall类关系图(转)
  10. 千山独行-一个人的创业路(连载五)