Flex移动skin – 第3部分: 多平台开发

在关于创建Flex移动皮肤系列文章的第二部分里,我们讨论了屏幕密度(DPI)对组件皮肤以及移动应用布局所带来的影响。 我还展示了如何使用缩放应用,特定密度的位图,以及CSS元媒介查询以调整和适应多种DPI值。

除了屏幕尺寸,屏幕密度以及外形差异以外,Flex移动应用开发者必须在着重于各个平台之间的不同点。 除了Android系统以外,Flex4.5.1以及Flash Builder4.5.1还支持两个目标为Flex Mobile项目的平台:苹果的iOS以及黑莓的TabletOS。 这些平台都有各自独特的外观,用户体验,UI图案,以及人机接口规范(HIG)。

Flex 4.5中的移动主题并不会偏向于任何一个特定的平台。 就像Spark那样,移动主题具有中性的外观以及感觉,其设计元素可以工作于各个平台。 根据您的需求以及客户的需求,可以利用CSS样式快速而自由地改变应用程序的外观,或者您还可以使用更加高级的机制,比如自定义皮肤,FXG,或者特定于平台的皮肤,与其它原本的应用程序结合使用,从而获得更多的控制余地。

显著的平台差异

AIR所支持的每一个平台均具有独特的特点,特质以及挑战。 Flex 4.5.1占据了这些挑战中的一部分,并且让用户可以在必需的时候添加新的,特定于平台的行为。 本部分将简单地涵盖那些将会影响应用程序的可视化设计以及行为设计的平台之间的主要不同点。

硬件按钮

Android上的AIR添加了对Android硬件上键盘按钮的支持:主页键,返回键,菜单键以及搜索键。 这些按钮可以是实实在在的硬件按钮,也可以是通过触摸屏显示出来的按钮。 某些设备制造商可能会忽略搜索按钮。

Android上的返回按钮用于导航回到上一个活动,即便该活动并非当前应用程序的一部分。

iOS设备以及黑莓的PlayBook并不具备这样的返回按钮。 相反,iOS和PlayBook的一个典型的应用可以在屏幕的左上方放置一个返回的软按键。 对于这两个平台,返回键的导航功能是局限在每个应用程序本身的。

Android上的菜单按钮将会打开一个选项菜单(即是Flex 4.5上的ViewMenu移动组件)。 选项菜单中会显示一个可用于当前活动的命令(作为按钮)列表。

在iOS中功能最接近的组件应该就是活动表了。 活动表能以列表的形式显示当前活跃或者当前已选择的条目的可用活动。

黑莓的PlayBook配备有一个触控的边框,应用程序可以通过该边框显示一个包含任意控件的容器。

Android上的搜索按钮通常使用在应用程序上下文的数据搜索当中。 比如,一个联系人应用程序就需要提供一个文本搜索功能,以筛选联系人的数据信息。 Android上的搜索操作对于所有应用程序均具有一致的外观和感觉。 iOS与黑莓的Tablet操作系统均不具备针对于特定应用程序的搜索UI设计元素。

可用的屏幕面积

Android 2.x以及iOS在应用程序顶部仅显示有一个状态栏,当应用程序进入全屏模式时,该状态栏便会隐藏。

在Android 3.x Honeycomb当中,屏幕底部的状态栏总是可见的,无论是否处于全屏状态下。

对于黑莓PlayBook上的应用程序,默认均运行在全屏模式下。 从右上角滑下便可以显示系统状态栏,但这并不会重设AIR应用程序窗口的大小。

活版印刷

AIR中所使用的默认sans serif 设备字体会根据设备的不同而有所不同。 PlayBook将使用Myriad Pro,而iOS则使用Helvetica,Android使用Droid Sans。

为了清晰起见,即使在不同的设备上使用相同的字体尺寸以及相同的DPI,其字体度量也会因为所使用的字体不同而有所不同。 在给定的面积中,用户所能够放置的文本总量会因为屏幕尺寸以及平台的不同而有所不同(参见图1)。

左图为黑莓的PlayBook(横向, cropped),中图为苹果iPod第四代(portrait),右图为三星Galaxy S(纵向)使用了Flex移动主题的默认样式。
图1,左图为黑莓的PlayBook(横向, cropped),中图为苹果iPod第四代(portrait),右图为三星Galaxy S(纵向)使用了Flex移动主题的默认样式。

在各个平台上,单行的文本内容通常会中央上升(也就是说,不包括文本高度的下行字母)。移动主题里的皮肤还会使用中央上升。

软键盘

全部三个平台的纵向以及横向情况下均支持使用软键盘。

然而,许多Android手机拥有一个固定的硬件键盘而不是软键盘(例如,摩托罗拉Droid Pro),而其它的一些Android手机具备可选的硬件键盘,可开启用于取代软键盘。

Android手机还允许使用第三方的软键盘。 比如,Swype和SwiftKey键盘便可以与AIR无缝集成。

软键盘的尺寸随着平台,设备,甚至设备方位的不同而有所差异。 但无论设备的方位如何,全部三个平台所使用的软键盘均与屏幕底部的边缘对齐。

默认情况下,当软键盘被激活或停用时,在Flash Builder中所创建的Flex移动项目均会自动配置以缩小或扩大应用程序的高度。

文本输入

在Android和黑莓的PlayBook平台中,AIR应用程序的TextField以及新的StyleableTextField控件中的文本输入均可正常工作。

然而,这些控件在iOS中的实现却是一个特例。 为了能在iOS中获得功能齐全的纠错和文本选择功能,文本编辑将会包含在一个原生的覆盖于屏幕最上方的控件之中。 当在iOS中编辑TextField和StyleableTextField内容时,该技术会带来一些限制,包括:

  • 在编辑时是不支持Restrict属性的。 限制操作将在退出TextField之后才可以使用。
  • 在进入或者退出可编辑的TextField时,由于空白和短划线字符较小,可能会导致多行文本回流。
  • 文本无法被父级容器所指定的scrollRect属性剪切。
  • 键盘事件将不会被触发。
  • 原生的清除按钮(带有X标记的灰色圆圈)总会出现在TextInput当中,并且这是不可配置的。
颜色的深浅

在苹果iOS和黑莓Talblet OS中,AIR均支持32位色。 而在Android中,AIR在使用RGB565时受限于16位颜色。

人机界面规范

每个平台供应商都具有其独特的人机接口规范(HIG),称为UI规范。

以下这些规范将有助于用户创建出外观和使用感受都与那些本土程序类似的Flex移动应用程序。

特定平台的综述

关于特定的平台,我仅仅触及到表面的问题。 想获取关于该主题的更多信息,您可以浏览www.androidpatterns.com以及pttrns.com,这两个网址将持续更新它们的UI模式目录。

在AIR允许设计者和开发者以通用的运行时来创建应用程序的同时,设计应用程序中很重要的一点是,您必须清楚何时以及如何将特定于平台的不同点考虑在内。 Flex移动项目为您提供了一个选择范围,从在所有平台上使用单一的UI,到为每个所支持的平台重新设计UI。

创建特定平台的外观和样式

4.5.1版本的Flex和Flash Builder为您在项目中定义和使用特定平台的样式和外观提供了基本工具。

使用CSS媒体查询

在关于创建Flex 移动外观系列的第二部分中,我讨论了如何在CSS媒体查询中使用自定义的媒体功能application-dpi来设置特定的DPI样式,比如字体大小和填充值。 4.5版本的Flex提供了一个额外的自定义媒体功能:os-platform。 此项功能允许开发人员指定特定于平台的样式。 下面是一个简单的例子,设置一个默认的 ActionBar chromeColor的数值,以及特定于Android以及特定于IOS的数值 :

ActionBar { chromeColor: #000000; }@media (os-platform: "Android"){ ActionBar { chromeColor: #999999; /* dark gray */ }}@media (os-platform: "IOS"){ ActionBar { chromeColor: #6DA482; /* blue */ }}

此示例代码使用了来自移动主题的默认ActionBarSkin皮肤类,并改变了chromeColor属性。 您可以使用同样的技术来完全替代特定于平台的默认外观。

主题的使用

为特定于平台的外观使用CSS的主要缺点是,无论何种平台,所有的外观及其附属文件都将被编译到您的应用程序中。 这是必要的,因为CSS媒体查询是在运行时,而不是编译时,进行计算的。 最终的结果是生成一个更大的二进制文件(APK,BAR,或者IPA类型的文件),该文件会增加下载时间和并添加到程序历史记录。

获取特定于平台的外观和样式的另一种方式是,分别为每一个平台编辑应用程序,通过每次改变theme 编辑器参数来覆盖不同的主题。 这将赋予您特定于平台的样式,而不会增大应用程序的二进制文件尺寸。

请注意:在单一的项目中,4.5.1版本的Flash Builder没有内置对每个平台编译器参数的支持。 您有三种选择:

  • 创建您自己的编译脚本
  • 对于每个平台,每当创建项目时都要手动修改参数。
  • 将您的项目重构到共享相同基础项目和/或库的多个项目当中。

第三个选项提供了最大程度的控制,为您提供更多用来添加特定平台操作的选择(例如,iOS和黑莓Talblet os中屏幕上的返回按钮)。

如果您选择以这种方式来使用主题的话,请选择一个最适合您的工作流程的构建选项。

想获取更多关于Flex 4.x中主题支持的信息,请参阅 Flex说明文档中关于主题的部分内容

ActionBar样式教程

通常情况下,对外观做出改变的最简单方法是使用CSS样式。 对于这个例子,我将详细叙述之前展示的ActionBar示例样式,以加入更多一些特定于平台的细节。

我正在为虚拟业务评测启动开发一个名为holr!的应用程序。 他们希望ActionBar看起来能够像那些在三个平台上的本地应用程序一样,但是他们没有预算将金钱花在自定义皮肤上。

在本教程中,我将展示每个平台的CSS示例。 请记住,那些样式应该定义在应用程序MXML文件中的 内嵌标签或者外部文件中。

我将从以下由Flex移动项目向导中的基于视图的应用程序模版所创建的应用程序MXML开始:

<?xml version="1.0" encoding="utf-8"?><s:ViewNavigatorApplication xmlns:fx=http://ns.adobe.com/mxml/2009 xmlns:s="library://ns.adobe.com/flex/spark" firstView="views.holrHomeView"> <fx:Style> @namespace s "library://ns.adobe.com/flex/spark"; </fx:Style> <s:navigationContent> <s:Button label="Back"/> </s:navigationContent> <s:actionContent> <s:Button label="Save"/> </s:actionContent></s:ViewNavigatorApplication>

理想情况下,如果我的目标是要获取一个二进制文件,那么当在Android中运行时,我将会添加一些逻辑来压缩ActionBar中的返回按钮。 而对于这一个样式示例,我将不会对它做任何的改变,从而避免事情复杂化。

Android

该移动主题很好地反映了当今Android应用程序的外观。 平面式的按钮非常适合工作。 我所要做的就是改变chromeColor的属性,以使客户端签名呈现红颜色(参见图2)。 由于我将在所有平台上使用同样的颜色,所以不需要在媒体查询中捆绑这项规则。

s|ActionBar{ chromeColor: #990000;}
图 2. 在Android(240 DPI)上的 holr!
图 2. 在Android(240 DPI)上的 holr!

默认情况下,ActionBar中的标题是左对齐的。 如果您想将标题居中(见图3),您可以将titleAlign:center添加到ActionBar样式规则中。

图 3.  在Android(240DPI)中的holr!,并且titleAlign=center
图 3. 在Android(240DPI)中的holr!,并且titleAlign=center
苹果iOS

适用于iOS的ActionBar样式变得有点复杂。 标题是居中对齐的,并且该按钮具有独特的形状和一些非零填充。 幸运的是,ActionBar的defaultButtonAppearance样式包含正常和倾斜两种选择。

将ActionBar的defaultButtonAppearance样式设置为beveled(倾斜),自动设置几个样式的参数值,包括斜角按钮,导航与活动类周围的填充,以及中心标题对齐(见图4)等。如果想要查看用于defaultButtonAppearance=beveled的所有设置,您可以在目录4.5.1/frameworks/projects/mobiletheme/defaults.css 中找到移动主题的defaults.css文件,并查看.beveled样式名称选择器的使用方法。

@media (os-platform: "IOS"){ s|ActionBar { defaultButtonAppearance: beveled; }}
图 4. 在苹果ipod touch第四代上的holr!
图 4. 在苹果ipod touch第四代上的holr!
黑莓的Tablet os(平板电脑操作系统)

为黑莓所设计的ActionBar样式可能会更加复杂一点。 我说这话的原因是,RIM公司利用他们自己以MovieClip为基础的组件提供了独有的Flash UI框架。 虽然在这个例子中可以集成原生的RIM组件,但是我将坚持使用Flex。

RIM在他们内置的应用程序顶部使用了一种类似于ActionBar的容器。 这些应用程序中的大部分都使用一种通过透明的ActionBar显示的背景图像或者纹理。 像IOS一样,RIM也采用了中心对齐的标题。 然而,RIM的标题使用了一种正常的字体粗细,而不是粗体。

RIM在ActionBar两侧使用了圆形按钮。 然而不同于iOS,RIM公司并没有使用一个箭头式的返回按钮(见图5)。

PlayBook拥有一块实际DPI(分辨率)为170的屏幕。这已经足够高了,Flex团队为160DPI分类所选择的字体大小要比RIM推荐的小一点点。 在这个例子中,我会对字体尺寸进行一些调整作为补充。 为了获取包括字体尺寸数值更新在内的全套样式,请下载defaults_BlackBerry_PlayBook.css 示例文件。

您可以无比接近RIM的外观并且亲自感受它,但是您必须覆盖一些来自于使用先进CSS选择器的移动主题的CSS规则。

@media (os-platform: "QNX"){ s|ActionBar { defaultButtonAppearance: beveled; } s|ActionBar #titleDisplay { fontSize: 22; fontWeight: normal; } s|ActionBar.beveled s|Group#navigationGroup s|Button { /* use the rounded button instead of the arrow button */ skinClass: ClassReference("spark.skins.mobile.BeveledActionButtonSkin"); } s|ActionBar.beveled s|Group#actionGroup s|Button, s|ActionBar.beveled s|Group#navigationGroup s|Button { fontSize: 16; fontWeight: normal; }}
图 5. 在黑莓的PlayBook (160 DPI)上的holr!
图 5. 在黑莓的PlayBook (160 DPI)上的holr!

最终的应用程序文件看起来像下面这样:

<?xml version="1.0" encoding="utf-8"?><s:ViewNavigatorApplication xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" firstView="views.holrHomeView"> <fx:Style> @namespace s "library://ns.adobe.com/flex/spark"; @namespace s "library://ns.adobe.com/flex/spark"; s|ActionBar { chromeColor: #990000; } @media (os-platform: "IOS") { s|ActionBar { defaultButtonAppearance: beveled; } } @media (os-platform: "QNX") { s|ActionBar { defaultButtonAppearance: beveled; } s|ActionBar #titleDisplay { fontSize: 24; fontWeight: normal; } s|ActionBar.beveled s|Group#navigationGroup s|Button { /* use the rounded button instead of the angled back button */ skinClass: ClassReference("spark.skins.mobile.BeveledActionButtonSkin"); } s|ActionBar.beveled s|Group#actionGroup s|Button, s|ActionBar.beveled s|Group#navigationGroup s|Button { fontSize: 20; fontWeight: normal; } global { fontSize: 20; } } </fx:Style> <s:navigationContent> <s:Button label="Back"/> </s:navigationContent> <s:actionContent> <s:Button label="Save"/> </s:actionContent></s:ViewNavigatorApplication>

一条关于高级CSS选择器的快速注解:移动主题会使用styleNameID选择器来将样式从具体的ActionBar皮肤组件中区分出来。 我这样做是为了避免无意中改变ActionBar内容组中其他组件的样式。 例如,我不想让ActionBar中的按钮与标题文本具有同样的字体尺寸值。 我真的希望标题使用更大的文本以便凸显出来。

样式总结

改变内置的移动主题的样式是非常简单的。 虽然特定于平台为ActionBar修改样式会更加复杂,但是归功于defaultButtonAppearance 和 titleAlign 风格,这并不是太困难。

移动主题覆盖教程

现在,轮到最困难的部分了。 这里的第二篇教程将会帮助您打下基础,从而为Flex移动项目创建您自己的主题。

如果您愿意的话,可以跳过主要教程,直接查看我的iOS主题示例。 这个主题仅仅是一种概念的证明,但它确实可以表现出Flex更换皮肤功能有多么强大。

为了简洁起见,下面的教程会介绍如何创建一个使用移动主题作为基本主题的主题覆盖。 在一般情况下,Flex4主题作者应该为桌面项目的Spark 主题或者移动应用程序的移动主题创建一些覆盖。 许多重要的样式特性仅仅在使用一些指定主题名称时才适用。 例如,chromecolor只在Spark 和移动主题中才适用。 如果您创建并使用了一个独立的主题,并且参考了CSS或MXML中的chromeColor,编译器便会记录到一个错误。

阶段1:创建一个主题项目

创建自定义主题的第一步是创建一个库项目。 这个项目将输出您可以通过任何兼容项目重复使用的主题SWC文件。

  1. 选择 File(文件) > New(新建) > Flex Library Project(Flex库项目)。
  2. 为该项目键入一个名称;例如,键入mobiletheme_ios
  3. 在Configuration(配置)项目栏中,选择Mobile Library(移动库)来包含一个mobilecomponents.swc文件(见图6)。
图6.创建一个移动库
图6.创建一个移动库
  1. 点击下一步。

    既然您想扩展该移动主题,便需要添加它的swc文件以便扩展类以及从该主题中引用其他的附属文件。

  2. 点击添加SWC。
  3. 在Add SWC对话框中 (见图 7), 输入在SDK中的移动主题swc文件路径:/path/to/Adobe Flash Builder 4.5/sdks/4.5.1/frameworks/themes/Mobile/mobile.swc
  4. 点击 "OK"。
图7. 添加移动主题swc
图7. 添加移动主题swc

一旦被添加到构建路径库树中,该swc文件便会被扩展。

  1. 双击链接类型(见图8)
图8. mobile.swc的连接类型。
图8. mobile.swc的连接类型。
  1. 选择External(外部)作为连接类型(见图9),并点击OK。
图9. 将连接类型改为External(外部)。
图9. 将连接类型改为External(外部)。

这一步是必需的,如此的话,从移动主题SWC所添加的附属文件将不会被编译到自定义主题当中。 默认的移动项目配置(参见/path/to/4.5.1/frameworks/airmobile-config.xml)会默认添加移动主题SWC。 之后,当创建Flex移动项目时,您就不必单独添加移动主题SWC了。

  1. 双击源附件中的mobile.swc
  2. 设置文件路径为 /path/to/Applications/Adobe Flash Builder 4.5/sdks/4.5.1/frameworks/projects/mobiletheme/src ,并单击"OK"(见图 10)。
图10. 改变源路径
图10. 改变源路径

对移动主题中诸如类的Go To Definition功能的支持是必需的。 在添加了该SWC后,Flash Builder最初使用的路径是不正确的。

  1. 单击"完成"以创建项目。
阶段2:为主题的开发配置库项目

现在您已经有了一个项目,但还需要几个步骤将它配置为一个主题。

  1. 在项目根目录下创建一个defaults.css文件(不是主src文件夹,而是项目文件夹本身)。 这个文件将会为该主题定义样式规则。
  2. 选择 Project (项目)> Properties(属性)。
  3. 在Flex Library Compiler(Flex库编译器)页面的Additional Compiler Arguments(附加编译器参数)中添加: -include-file defaults.css ../defaults.css.
-include-file defaults.css ../defaults.css.
  1. 点击 "OK"。

这样便完成了一个主题SWC的基本设置了。 在defaults.css中定义样式并添加其他皮肤类之后,在该项目的bin文件夹中的SWC文件可以通过两种方式被用作主题覆盖:

  • 在Flex编译器属性页面将-theme+=/path/to/theme.swc 添加到Additional Compiler Arguments(附加编译器参数)中。
  • 通过选择 Project (项目)> Properties (属性)> Flex Theme(Flex主题)来导入主题SWC。

如果您正在创建主题,为了获得更加醒目的导入体验,您可以将元数据以及预览图像连同自己主题的SWC或者CSS文件一起添加。 想获取更多关于主题创建的信息,请参见 Creating Themes(创建主题)。

第三阶段:创建一个Flex移动项目

在建立该主题之后,并且在创建皮肤之前,我将会设立一个项目来测试我的主题,正如我在开发主题时那样。 在这个项目中,我使用了一些技巧来使我的主题在迭代上更容易一些。

  1. 选择 File(文件) > New(新建) > Flex Mobile Project(Flex移动项目)。 键入一个项目名称,使用默认设置,然后点击"下一步"。
  2. 单击"Add Project(添加项目)",并添加您的主题项目。
  3. 单击Finish(完成),Flash Builder将会创建该项目。
  4. 选择 Project (项目)> Properties(属性).
  5. 在Flex编译器属性页,添加-theme+=//bin/.swc到Additional Compiler Arguments(附加编译器参数)。 这个参数会将应用主题覆盖到该项目。
  6. 点击 "OK"。
  7. 在主题项目中,将一个名为ThemeClasses的类添加到默认包。
  8. 在移动的项目的主应用程序MXML文件中,在一个<fx:Script>标签中添加一个对这个类的引用。 只需一个诸如ThemeClasses的简单声明便已足够了。

您可能在想为什么我不使用项目属性对话框中的Flex主题的属性页来设立一个主题呢。 简短的回答是,Flash Builder中的主题功能主要是设计用来导入预建的无法改变的主题。 正如我对主题项目进行的增量更改,我希望重新编译移动项目。 当主题项目发生改变时,这些步骤是让Flash Builder 重新编译移动项目所必需的。

第4阶段:创建外观和样式

这一阶段占据了这项工作的主体。 在关于创建Flex移动皮肤系列的 Part 1和 Part 2 中,我已经详细介绍了移动换肤开发过程。总括来说,其过程如下: 总括来说,其过程如下:

  1. 创建graphic assets(图形资源),如FXG。
  2. 创建一个新的基于MobileSkin的皮肤,或者继承一个现有的移动主题皮肤。
  3. 定义hostComponent 属性。
  4. 指定FXG assets。
  5. 适当地支持移动主题样式(比如,chromeColor )。
  6. 在该主题的defaults.css文件中指定Css样式规则。 对于您计划想要支持的每个组件,请指定不会被DPI影响的自定义skinclass和样式数值。
  7. 使用application-dpi媒体查询功能来指定额外的CSS样式规则,从而筛选针对每个DPI字体尺寸以及填充样式。
  8. 为每个主机组件重复这些步骤。

由于在先前的文章里已经介绍过这个过程,所以这里我将跳过一些细节内容。 如果您到目前为止都跟随这本指导的步骤,那么将可以从前一个指导中将CSS示例复制到主题库项目的defaults.css文件中。 当您运行移动项目的时候,它将从主题中拾取样式规则。

概念验证:iOS主题

我所创建的iOS主题很大程度上依赖基于MobileSkin 基类以及Flex 4.5移动主题默认皮肤中的自定义皮肤。

由于这些主题将要用于任意类型的项目,所以我没有使用特定于平台的查询功能来筛选基于平台的样式规则。 这为我在Android或者黑莓Tablet OS应用上根据需要使用自己的iOS主题提供了很大的灵活性。

为了测试Flash Builder 4.5.1下的iOS主题,请下载mobiletheme_ios_usage.fxp示例文件,并遵循以下的指导:

  1. 选择 File(文件) > Import Flash Builder Project(导入Flash Builder项目)。
  2. 导航至mobiletheme_ios_usage.fxp,并选中该文件。
  3. 点击完成。
  4. 选中mobiletheme_ios_usage项目,然后点击Run按钮(或者选择Run(运行) > Run As(运行为) > Mobile Application(移动应用程序))。

    Flash Builder将会自动为您创建一个运行配置。

  5. 对于Target Platform(目标平台),请选中苹果iOS。
  6. 对于Launch Method(运行方法),请选择On Desktop(在桌面上)。
  7. 选中一个用于仿真的iOS设备。
  8. 点击运行(参见图11)。
图11. 应用程序运行在第四代iPod上的概念验证。
图11. 应用程序运行在第四代iPod上的概念验证。

为了将该项目打包并部署在iOS设备上,用户需要设置一个苹果开发者账户。 更多信息,请阅读Andrew Shorten's的文章Using Flash Builder 4.5 to package applications for Apple iOS devices

要了解更多关于移动皮肤设置以及我所做过的概念验证工作,请访问我的博客文章 Example: iOS Theme for Flex Mobile Projects

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值