Unity基于UIWidgets的UI入门(三简单的入门)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_36848370/article/details/90268666

接着就开始继续学习UIWidgets主题材质等一系列

 

我们这节来学习 脚手架 Scaffold类  和 MaterialApp类

这张图是从flutter中找的图

ListTile 用法 必须在MaterialApp类里面才能使用

效果就是这样的

 

学习ListTile

 

给ListTile添加Icon

需要在代码中添加这样一段代码 添加一下字体


 
 
  1. protected override void OnEnable()
  2. {
  3. base.OnEnable();
  4. FontManager.instance.addFont(Resources.Load<Font>( "MaterialIcons-Regular"), "Material Icons",fontWeight:FontWeight.normal);
  5. FontManager.instance.addFont(Resources.Load<Font>( "GalleryIcons"), "GalleryIcons");
  6. }

然后这个是使用Icon方法


 
 
  1. public override Widget build(BuildContext context)
  2. {
  3. return
  4. new ListTile(
  5. leading: new Icon( icon:Icons.check ),
  6. // leading: new Text(data : "我是领导标题"),
  7. subtitle : new Text(data : "我是副标题"),
  8. //trailing : new Text(data : "我是补充说明"),
  9. trailing : new Icon( icon:Icons.delete ),
  10. title: FQ.Text.Data(mData).SetSize( 30).EndText().OnTap(
  11. ()=>{
  12. mOnFinish();
  13. }
  14. ));
  15. }

接着我们给输入框增加一个外边框 我们知道 Container 的才有外边框的属性 

decoration  :new BoxDecoration  添加一个BoxDecoration

然后看到的就是这种效果

  • 接着我们学习Drawer 这个是存在scaffold 下的 效果就是这种效果

 

  • 接着我们学习PopupMenuButton 这个 可以显示出一个 然后通过内部的itemBuilder 生成一个下拉列表 跟他的Demo一样 复制他的Demo过来

 
 
  1. class Choice
  2. {
  3. public Choice(string title, IconData icon)
  4. {
  5. this.title = title;
  6. this.icon = icon;
  7. }
  8. public readonly string title;
  9. public readonly IconData icon;
  10. public static List<Choice> choices = new List<Choice> {
  11. new Choice( "Car", Unity.UIWidgets.material.Icons.directions_car),
  12. new Choice( "Bicycle", Unity.UIWidgets.material.Icons.directions_bike),
  13. new Choice( "Boat", Unity.UIWidgets.material.Icons.directions_boat),
  14. new Choice( "Bus", Unity.UIWidgets.material.Icons.directions_bus),
  15. new Choice( "Train", Unity.UIWidgets.material.Icons.directions_railway),
  16. new Choice( "Walk", Unity.UIWidgets.material.Icons.directions_walk)
  17. };
  18. }

 

 然后构成还放在 scaffold 的actions下面


 
 
  1. actions: new List<Widget>(){
  2. new IconButton(icon: new Icon(Icons.image)),
  3. new IconButton(icon: new Icon(Icons.image)),
  4. new PopupMenuButton<Choice>(
  5. onSelected: (choice)=> { Debug.Log(choice.title); },
  6. itemBuilder: (BuildContext subContext) => {
  7. List<PopupMenuEntry<Choice>> popupItems = new List<PopupMenuEntry<Choice>>();
  8. for ( int i = 0; i < Choice.choices.Count; i++) {
  9. popupItems.Add( new PopupMenuItem<Choice>(
  10. value: Choice.choices[i],
  11. child: new Text(Choice.choices[i].title)));
  12. }
  13. return popupItems;
  14. }
  15. )
  16. }

 

实现的效果就是这样

好用

接着我们学习FloatingActionButton 类 依然是在scaffold下的

复制demo里面粘贴进来效果是这样的

就是红色框框圈住的小铃铛

然后接着咱们所做的内容就是如下图所示   

选中代办事项列表 和已经完成事项列表 添加保存删除 等操作

我先粘贴代码

这次多了几个类 这个类用来注册重新载入setState方法的


 
 
  1. using System;
  2. using MyTestUIWidgets;
  3. namespace MyTestUIWidgets.UIWidgets
  4. {
  5. public class ViewState
  6. {
  7. public static TodoListApp.TodoListPageMode todoListPageMode = TodoListApp.TodoListPageMode.List;
  8. public static Action OnStateChange;
  9. }
  10. }

这个类是从重写视图类 输入框 和下面的显示列表


 
 
  1. using Color = Unity.UIWidgets.ui.Color;
  2. using Unity.UIWidgets.foundation;
  3. using System;
  4. using System.Collections.Generic;
  5. using MyTestUIWidgets.UIWidgets;
  6. using Unity.UIWidgets.painting;
  7. using Unity.UIWidgets.widgets;
  8. using UnityEngine;
  9. using Unity.UIWidgets.material;
  10. namespace MyTestUIWidgets.UIWidgets
  11. {
  12. public class TodoView : StatelessWidget
  13. {
  14. private readonly Todo mData;
  15. private readonly Action mOnFinish;
  16. private readonly Action mDelete;
  17. public TodoView(Todo data, Action onFinish, Action onDelete)
  18. {
  19. mData = data;
  20. mOnFinish = onFinish;
  21. mDelete = onDelete;
  22. }
  23. public override Widget build(BuildContext context)
  24. {
  25. return
  26. new ListTile(
  27. leading: new IconButton(icon: new Icon(icon: Icons.check_box_outline_blank, color: Colors.blueAccent, size: 30), onPressed: () => { mOnFinish(); },iconSize: 50),
  28. // .OnTap(() =>
  29. // {
  30. // }),
  31. // leading: new Text(data : "我是领导标题"),
  32. subtitle: new Text(data: DateTime.Now.ToString( "yyyy年 m月 d日 HH:mm:ss ")),
  33. //trailing : new Text(data : "我是补充说明"),
  34. trailing: new IconButton(icon: new Icon(icon: Icons.delete_outline, color: Colors.redAccent, size: 30), onPressed: () => { mDelete(); },iconSize: 50),
  35. // .OnTap(() =>
  36. // {
  37. // mDelete();
  38. // // mOnFinish();
  39. // }),
  40. title: FQ.Text.Data(mData.Content).SetSize( 30).EndText());
  41. // FQ.Container
  42. // .Alignment(Alignment.center)
  43. // .Child(
  44. // FQ.Text
  45. // .Data(mData)
  46. // .SetSize(20).EndText()
  47. // )
  48. // .EndContainer().OnTap(() =>
  49. // {
  50. // mOnFinish();
  51. // }));
  52. }
  53. }
  54. public class TodoInputView : StatelessWidget
  55. {
  56. private string mInputContent = string.Empty;
  57. private Action< string> mOnAdd;
  58. public TodoInputView(Action<string> onAdd)
  59. {
  60. mOnAdd = onAdd;
  61. }
  62. public void AddTodo()
  63. {
  64. if (! string.IsNullOrWhiteSpace(mInputContent))
  65. {
  66. mOnAdd(mInputContent);
  67. }
  68. }
  69. public override Widget build(BuildContext context)
  70. {
  71. return
  72. new Container(child:
  73. new Row(children: new List<Widget>(){
  74. FQ.Container.Width( 190).Height( 40 ).Dec(Colors.lightBlue).Margin(EdgeInsets.only(left : 60))
  75. .Child(FQ.EditableText.FontSize( 30)
  76. .OnValueChanged(mInputContent => { this.mInputContent = mInputContent; } )
  77. .OnSubmit(inputvalue => AddTodo())
  78. .EndEditableTextBuilder())
  79. .EndContainer(),
  80. new IconButton( icon: new Icon(Icons.add_box,size: 40,color:Colors.green),onPressed:AddTodo),
  81. // FQ.Container.Child(
  82. // new Icon(Icons.add_box,size:40,color:Colors.green)
  83. // .OnTap(() => {
  84. // AddTodo();
  85. // Debug.Log("On Tap");})
  86. // ).Margin(EdgeInsets.only(left:30)).EndContainer()
  87. }
  88. ));
  89. }
  90. }
  91. }

这个类用来扩展UIWidgets


 
 
  1. using System;
  2. using System.Globalization;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using Unity.UIWidgets.gestures;
  6. using Unity.UIWidgets.painting;
  7. using Unity.UIWidgets.widgets;
  8. using UnityEngine;
  9. using Color = Unity.UIWidgets.ui.Color;
  10. using Unity.UIWidgets.foundation;
  11. using Unity.UIWidgets.material;
  12. namespace MyTestUIWidgets.UIWidgets
  13. {
  14. public class FQ
  15. {
  16. public static ContainerBuild Container => new ContainerBuild();
  17. public static TextBuilder Text => new TextBuilder();
  18. public static ListViewBuilder ListView => new ListViewBuilder();
  19. public static EditableTextBuilder EditableText => new EditableTextBuilder();
  20. }
  21. public class ContainerBuild
  22. {
  23. private Widget mChild { get; set; }
  24. private Alignment mAlignment { get; set; }
  25. private Color mColor { get; set; }
  26. private EdgeInsets mMargin = EdgeInsets.zero;
  27. //可空参数
  28. private float? mWidth = null;
  29. private float? mHeight = null;
  30. public static ContainerBuild GetBuilder()
  31. {
  32. return new ContainerBuild();
  33. }
  34. public ContainerBuild Child(Widget _child)
  35. {
  36. mChild = _child;
  37. return this;
  38. }
  39. public ContainerBuild Color(Color _color)
  40. {
  41. mColor = _color;
  42. return this;
  43. }
  44. public ContainerBuild Margin(EdgeInsets _edgInsets)
  45. {
  46. mMargin = _edgInsets;
  47. return this;
  48. }
  49. public ContainerBuild Width(float _width)
  50. {
  51. mWidth = _width;
  52. return this;
  53. }
  54. public ContainerBuild Height(float height)
  55. {
  56. mHeight = height;
  57. return this;
  58. }
  59. public ContainerBuild Alignment(Alignment _alignment)
  60. {
  61. mAlignment = _alignment;
  62. return this;
  63. }
  64. private Color mBorderColor = null;
  65. public ContainerBuild Dec(Color color)
  66. {
  67. mBorderColor = color;
  68. return this;
  69. }
  70. public Container EndContainer()
  71. {
  72. return new Container(child: mChild,
  73. alignment: mAlignment,
  74. color: mColor,
  75. width: mWidth,
  76. height:mHeight,
  77. margin: mMargin,
  78. decoration:
  79. mBorderColor != null ? new BoxDecoration(border: Border.all(mBorderColor)) : null);
  80. }
  81. }
  82. public class TextBuilder
  83. {
  84. private string mData { get; set; }
  85. private TextStyle mStyle { get; set; } = new TextStyle();
  86. private int mFontSize { get; set; }
  87. public static TextBuilder GetBuilder()
  88. {
  89. return new TextBuilder();
  90. }
  91. public TextBuilder Data(string _data)
  92. {
  93. mData = _data;
  94. return this;
  95. }
  96. public TextBuilder SetTextStyle(TextStyle _style)
  97. {
  98. mStyle = _style;
  99. return this;
  100. }
  101. public TextBuilder SetSize(int _fountSize)
  102. {
  103. mFontSize = _fountSize;
  104. return this;
  105. }
  106. public Text EndText()
  107. {
  108. if (mFontSize == 0)
  109. {
  110. return new Text(data: mData);
  111. }
  112. else
  113. {
  114. return new Text(data: mData, style: new TextStyle(fontSize: mFontSize));
  115. }
  116. }
  117. }
  118. public class ListViewBuilder
  119. {
  120. List<Widget> mChildren = new List<Widget>();
  121. EdgeInsets mPadding = null;
  122. public static ListViewBuilder GetBuilder()
  123. {
  124. return new ListViewBuilder();
  125. }
  126. public ListViewBuilder Padding(EdgeInsets _madding)
  127. {
  128. mPadding = _madding;
  129. return this;
  130. }
  131. public ListViewBuilder Child(List<Widget> _children)
  132. {
  133. mChildren = _children;
  134. return this;
  135. }
  136. public ListViewBuilder Child(Widget _child)
  137. {
  138. mChildren.Add(_child);
  139. return this;
  140. }
  141. public ListViewBuilder Child(params Widget[] _childeen)
  142. {
  143. mChildren.AddRange(_childeen);
  144. return this;
  145. }
  146. public ListView EndListView()
  147. {
  148. return new ListView(children: mChildren, padding: mPadding);
  149. }
  150. }
  151. public static class GestureDetectorExtension
  152. {
  153. public static GestureDetector OnTap(this Widget _widget, GestureTapCallback onTap)
  154. {
  155. return new GestureDetector(child: _widget, onTap: onTap);
  156. }
  157. }
  158. public class EditableTextBuilder
  159. {
  160. private TextEditingController mInputController = new TextEditingController(text: "");
  161. private FocusNode mFocusNode = new FocusNode();
  162. public TextStyle mStyle = new TextStyle();
  163. public Color mCursorColor = Color.black;
  164. public float mFontSize;
  165. ValueChanged< string> mOnValueChanged = null;
  166. ValueChanged< string> mOnSubmit = null;
  167. public EditableTextBuilder OnValueChanged(ValueChanged<string> _onValueChanged)
  168. {
  169. mOnValueChanged = _onValueChanged;
  170. return this;
  171. }
  172. public EditableTextBuilder OnSubmit(ValueChanged<string> _onSubmit)
  173. {
  174. mOnSubmit = _onSubmit;
  175. return this;
  176. }
  177. public EditableTextBuilder SetInputController(TextEditingController _inputController, FocusNode _focusNode, TextStyle _style, Color _cursorColor)
  178. {
  179. mInputController = _inputController;
  180. mFocusNode = _focusNode;
  181. mStyle = _style;
  182. mCursorColor = _cursorColor;
  183. return this;
  184. }
  185. public EditableTextBuilder FontSize(float size)
  186. {
  187. mFontSize = size;
  188. return this;
  189. }
  190. public EditableTextBuilder GetBuilder()
  191. {
  192. return new EditableTextBuilder();
  193. }
  194. public EditableText EndEditableTextBuilder()
  195. {
  196. return new EditableText(
  197. controller: mInputController,
  198. focusNode: mFocusNode,
  199. style: mFontSize == 0 ? mStyle : new TextStyle(fontSize: mFontSize),
  200. cursorColor: mCursorColor,
  201. onChanged: mOnValueChanged,
  202. onSubmitted: mOnSubmit);
  203. }
  204. }
  205. }

这个类用来保存列表中的数据


 
 
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using UnityEngine;
  6. namespace MyTestUIWidgets.UIWidgets
  7. {
  8. public class Todo
  9. {
  10. public string Content = string.Empty;
  11. public bool Finished = false;
  12. }
  13. public static class Model
  14. {
  15. public static List<Todo> Load()
  16. {
  17. //PlayerPrefs.DeleteAll();
  18. var toDoListContent = PlayerPrefs.GetString( "TODO_LIST_KEY", string.Empty);
  19. var splitDatas = toDoListContent.Split( new[] { "@@@@" }, StringSplitOptions.None);
  20. return splitDatas.Where(data => ! string.IsNullOrEmpty(data))
  21. .Select(toddData =>
  22. {
  23. var todo = new Todo();
  24. var todoSplitDatas = toddData.Split( new[] { "::::" }, StringSplitOptions.None);
  25. todo.Content = todoSplitDatas[ 0];
  26. if (todoSplitDatas.Length > 1)
  27. {
  28. todo.Finished = bool.Parse(todoSplitDatas[ 1]);
  29. }
  30. return todo;
  31. })
  32. .ToList();
  33. }
  34. public static void Save(this List<Todo> self)
  35. {
  36. StringBuilder stringBuilder = new StringBuilder();
  37. self.ForEach(
  38. data =>
  39. {
  40. stringBuilder.Append(data.Content);
  41. stringBuilder.Append( "::::");
  42. stringBuilder.Append(data.Finished);
  43. stringBuilder.Append( "@@@@");
  44. }
  45. );
  46. PlayerPrefs.SetString( "TODO_LIST_KEY", stringBuilder.ToString());
  47. }
  48. }
  49. }

这个类用来构成App


 
 
  1. using System.Xml.Linq;
  2. using System;
  3. using System.Text;
  4. using System.Linq;
  5. using System.Collections;
  6. using System.Collections.Generic;
  7. using Unity.UIWidgets.engine;
  8. using Unity.UIWidgets.painting;
  9. using Unity.UIWidgets.widgets;
  10. using UnityEngine;
  11. using Color = Unity.UIWidgets.ui.Color;
  12. using MyTestUIWidgets.UIWidgets;
  13. using Unity.UIWidgets.foundation;
  14. using Unity.UIWidgets.animation;
  15. using Unity.UIWidgets.material;
  16. using Unity.UIWidgets.ui;
  17. using UnityEditor;
  18. namespace MyTestUIWidgets
  19. {
  20. class Choice
  21. {
  22. public Choice(string title, IconData icon)
  23. {
  24. this.title = title;
  25. this.icon = icon;
  26. }
  27. public readonly string title;
  28. public readonly IconData icon;
  29. public static List<Choice> choices = new List<Choice> {
  30. new Choice( "Car", Unity.UIWidgets.material.Icons.directions_car),
  31. new Choice( "Bicycle", Unity.UIWidgets.material.Icons.directions_bike),
  32. new Choice( "Boat", Unity.UIWidgets.material.Icons.directions_boat),
  33. new Choice( "Bus", Unity.UIWidgets.material.Icons.directions_bus),
  34. new Choice( "Train", Unity.UIWidgets.material.Icons.directions_railway),
  35. new Choice( "Walk", Unity.UIWidgets.material.Icons.directions_walk)
  36. };
  37. }
  38. public class TodoListApp : UIWidgetsPanel
  39. {
  40. protected override void OnEnable()
  41. {
  42. base.OnEnable();
  43. FontManager.instance.addFont(Resources.Load<Font>( "MaterialIcons-Regular"), "Material Icons", fontWeight: FontWeight.normal);
  44. FontManager.instance.addFont(Resources.Load<Font>( "GalleryIcons"), "GalleryIcons");
  45. }
  46. protected override Widget createWidget()
  47. {
  48. return new MaterialApp(home:
  49. new Scaffold(
  50. appBar: new AppBar(title: new Center(child: FQ.Text.Data( "My App").SetSize( 20).EndText()),
  51. backgroundColor: Color.black,
  52. // leading: new Icon(Icons.home),
  53. actions: new List<Widget>(){
  54. new IconButton(icon: new Icon(Icons.image,color:Colors.white)),
  55. new IconButton(icon: new Icon(Icons.image,color:Colors.white)),
  56. new PopupMenuButton<Choice>(
  57. onSelected: (choice)=> { Debug.Log(choice.title); },
  58. itemBuilder: (BuildContext subContext) => {
  59. List<PopupMenuEntry<Choice>> popupItems = new List<PopupMenuEntry<Choice>>();
  60. for ( int i = 0; i < Choice.choices.Count; i++) {
  61. popupItems.Add( new PopupMenuItem<Choice>(
  62. value: Choice.choices[i],
  63. child: new Text(Choice.choices[i].title)));
  64. }
  65. return popupItems;
  66. }
  67. )
  68. }),
  69. drawer: new Drawer(
  70. child: FQ.ListView.Padding(EdgeInsets.zero).
  71. Child( new Divider()).
  72. Child( new ListTile(leading: new Icon(Icons.list),
  73. title: FQ.Text.Data( "代办事项").EndText(), onTap: () =>
  74. {
  75. ViewState.todoListPageMode = TodoListPageMode.List;
  76. Debug.Log( "点击了待办事项");
  77. ViewState.OnStateChange.Invoke();
  78. })).
  79. Child( new Divider()).
  80. Child( new ListTile(
  81. leading: new Icon(Icons.check_box),
  82. title: FQ.Text.Data( "已完成事项").EndText(), onTap: () =>
  83. {
  84. Debug.Log( "点击了已完成");
  85. ViewState.todoListPageMode = TodoListPageMode.Finished;
  86. ViewState.OnStateChange.Invoke();
  87. })
  88. ).Child( new Divider())
  89. .EndListView()
  90. ),
  91. body: new TodoListPage(),
  92. floatingActionButton: new FloatingActionButton(
  93. backgroundColor: Colors.redAccent,
  94. child: new Icon(Unity.UIWidgets.material.Icons.add_alert),
  95. onPressed: () => { Debug.Log( "OnbuttonClick"); }
  96. )
  97. ));
  98. }
  99. class TodoListPage : StatefulWidget
  100. {
  101. public override State createState()
  102. {
  103. return new TodoListState();
  104. }
  105. }
  106. public enum TodoListPageMode
  107. {
  108. List,
  109. Finished
  110. }
  111. class TodoListState : State< TodoListPage>
  112. {
  113. private TodoListPageMode mPageMode = TodoListPageMode.Finished;
  114. public override void initState()
  115. {
  116. ViewState.OnStateChange += OnChange;
  117. mTodoDatas = Model.Load();
  118. }
  119. public override void deactivate()
  120. {
  121. ViewState.OnStateChange -= OnChange;
  122. }
  123. void OnChange()
  124. {
  125. this.setState(() => { });
  126. }
  127. private List<Todo> mTodoDatas = null;
  128. public override Widget build(BuildContext context)
  129. {
  130. if (ViewState.todoListPageMode == TodoListPageMode.List)
  131. {
  132. return FQ.ListView
  133. //.Child(new Text(data: "哈哈哈哈哈"))
  134. .Child( new TodoInputView(data => { AddState(data); }))
  135. .Child(ListTodoViews)
  136. .Padding(EdgeInsets.only( 0, 50))
  137. .EndListView();
  138. }
  139. else
  140. {
  141. return FQ.ListView
  142. //.Child(new Text(data: "哈哈哈哈哈"))
  143. //.Child(new TodoInputView(data => { AddState(data); }))
  144. .Child(FinishedListView)
  145. .Padding(EdgeInsets.only( 0, 50))
  146. .EndListView();
  147. }
  148. }
  149. private void AddState(string data)
  150. {
  151. this.setState(() =>
  152. {
  153. mTodoDatas.Add( new Todo() { Content = data, Finished = false });
  154. Save();
  155. });
  156. }
  157. private void Save()
  158. {
  159. mTodoDatas.Save();
  160. }
  161. Widget[] FinishedListView
  162. {
  163. get
  164. {
  165. var retWidgets = new List<Widget>();
  166. foreach ( var data in mTodoDatas.Where(data => data.Finished))
  167. {
  168. retWidgets.Add( new TodoView(data, () =>
  169. {
  170. this.setState(() =>
  171. {
  172. Debug.Log(data.Finished + "未设置");
  173. data.Finished = false;
  174. Debug.Log(data.Finished + "设置后");
  175. });
  176. Save();
  177. },
  178. () =>
  179. {
  180. this.setState(() =>
  181. {
  182. mTodoDatas.Remove(data);
  183. Save();
  184. });
  185. }));
  186. retWidgets.Add( new Divider());
  187. }
  188. return retWidgets.ToArray();
  189. }
  190. }
  191. Widget[] ListTodoViews
  192. {
  193. get
  194. {
  195. var retWidgets = new List<Widget>();
  196. foreach ( var data in mTodoDatas.Where(data => !data.Finished))
  197. {
  198. retWidgets.Add( new TodoView(data, () =>
  199. {
  200. this.setState(() =>
  201. {
  202. Debug.Log(data.Finished + "未设置");
  203. data.Finished = true;
  204. Debug.Log(data.Finished + "设置后");
  205. });
  206. Save();
  207. },
  208. () =>
  209. {
  210. this.setState(() =>
  211. {
  212. mTodoDatas.Remove(data);
  213. Save();
  214. });
  215. }));
  216. retWidgets.Add( new Divider());
  217. }
  218. return retWidgets.ToArray();
  219. // return mTodoDatas.Where(data => !data.Finished).Select(data => new TodoView(data, () =>
  220. // {
  221. // this.setState(() =>
  222. // {
  223. // Debug.Log(data.Finished + "未设置");
  224. // data.Finished = true;
  225. // Debug.Log(data.Finished + "设置后");
  226. // });
  227. // Save();
  228. // }, () =>
  229. // {
  230. // this.setState(() =>
  231. // {
  232. // mTodoDatas.Remove(data);
  233. // Save();
  234. // });
  235. // })).ToArray();
  236. }
  237. }
  238. }
  239. }
  240. }

这三节课的Demo我会上传在github上 一会会在下面贴上连接

https://github.com/TaylorGeGe/UIWidgetsDemo

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值