目录
2.1使用按钮实例构建菜单组件
2.2为替代属性准备符号
2.3 合并导入
2.4 设计图标资产
2.5 -交换图标的源代码
本文翻译自:Qt Design Studio - Sketch Bridge Tutorial Part 2 原文作者:Brook Cronin,Qt公司高级软件工程师兼UX设计师 校审:Kenny Zhang
欢迎回到Qt Design Studio-Sketch Bridge系列教程,在第1部分中我们创建了第一个按钮,并让它在Qt Design Studio(以下简称QDS)中不同状态下正确显示。在第2部分中,我们在该按钮的实例中创建一个菜单组件,并尝试替代每个实例的图标和文本。
打开Sketch文件,创建菜单背景,并拉大至足以容纳四个按钮,为了简单,现在只用矩形。
我们再次需要创建矩形,将其转换为符号,然后删除该实例并在Symbol页上处理主符号。
我们可以任意调整矩形的大小和颜色。在这个实例中,我们可以将单个设置设为Merge(合并),因为我们想从简单的单个资产开始。
我们还将为背景提供合适的QML ID,在这个实例中是myMenu_Symbol_background
有了菜单背景后,我们就可以开始使用符号来创建按钮实例,这些实例来自我们在Sketch中创建的主按钮组件,并在Design Studio中添加了交互。
我们通过Sketch 上的菜单添加资产,点击顶部的+按钮,并导航到symbols / document —— 这里会展现当前文档中可用的符号,目前只有一个符号,就是我们的按钮,所以让我们继续把它拖放到我们的新菜单组件中。
现在我们有了第一个实例,让我们重复这个流程,复制粘贴,或使用Alt加拖拽动来添加三个按钮到我们的菜单。
然后,我们需要做的是检查分配给新符号实例的QML ID,同时我们还需要确保菜单具有友好的QML ID。
让我们从菜单开始,因为它本身也是一个符号,让我们使用与上一个类似的命名方案,并称其为myMenu_Symbol
现在到了按钮本身,在本实例中,我们将对这些实例使用以下命名方案:
myButton_myMenu_1myButton_myMenu_2myButton_myMenu_3myButton_MyMenu_4
但更好的做法是定制每个按钮角色的名称,我们需要考虑希望这些按钮基于UI实现什么,以提出更清晰的命名方案。
我们不能在项目过程中更改这些ID,尽管理论上可行,因为合并机制会跟踪这些ID的更改,但最好还是在整个过程中坚持使用您的命名机制。
因此,我们可以使用以下ID:
myButton_myMenu_homemyButton_myMenu_dashboardmyButton_myMenu_profilemyButton_myMenu_settings
这样可以更清楚地看出每个实例的具体用途,还可以确保符号的每个实例都有惟一的ID。
现在我们可以将它重新导出到QDS了,但是让我们为按钮添加一些东西,比如一个label(标签)和一个icon(图标)。
首先,要把这些添加到按钮的主符号,从标签开始,要确保它可见,但仍在之前添加的鼠标区域热点下方。
现在点击Sketch菜单上的+按钮,选择text item,并添加到设计中,确保它在第二层,在鼠标区域的正下方。
接下来还需要确定文本框的尺寸,覆盖整个按钮宽度,且文本对象中心对齐,这样当我们想替代这个实例的文本时新标签还是居中的,当我们导出QDS时,这些属性也会被导出。
因为想要替代这个文本,这里请使用“default text”作为占位符。
同样,我们要确保文本对象有一个友好的QML ID,因此命名为myButton_Symbol_label, 然后把它拖动到鼠标区域下方,并确保这个层的名称与QML ID相同。
现在添加一个图标,实际上是图标的三个版本,我们将再次使用一个占位符图标作为主符号,以便稍后回来更改单个图标,我们可以在Sketch的形状菜单选项中拉出一个形状,比如三角形。
确保它也在鼠标区域下方,但在背景层的上方。然后,将其复制两次,为按钮的每个状态(默认、悬停、按下)创建一个版本,并微调每个版本,以便稍后在QDS中测试。
在本实例中,我只是微调颜色,因为这些是稍后要替换的占位符图形,只要能区分它们就行。
现在,就像处理所有图层那样,我们要更改ID并检查导出设置,确保本实例中的所有图标都被导出类型设置为child。我们将ID命名为:
myButton_icon_placeholder_default myButton_icon_placeholder_hover myButton_icon_placeholder_pressed
我们还将确保这些图层具有与ID相同的名称,并设置导出类型为Children,然后在图层导航器中将它们拖放到鼠标区域下方。
完成该设置后,回到menu symbol,查看它对实例的影响,它们现在都有了图标和文本标签。稍后我们会回来用不同方式处理这些图标,现在我们可以使用标签来创建第一个替代属性。
简单说明一下替代属性,使用Sketch中的符号,您可以更改符号实例的某些部分,这不会影响原先的主符号,而只会在本地实例中进行更改。
虽然Sketch中有多种类型的符号替代,但QDS只支持少数几种,主要是文本。另一种方法是替代符号本身,但这是相当高级的概念,我们暂时不讨论它,只关注文本选项。
我们回到名为Home的第一个按钮实例,在按钮草图的属性面板中,我们可以看到有一个文本替代的新字段。我们只需在这里输入新文本,第一个在替代文本中添加" Home ",然后就会看到第一个实例中的新文本。
当稍后将其重新导入Design Studio时,会在按钮组件上为该文本字段创建一个别名属性,并自动将“Home”文本添加到该实例的别名中。现在,让我们为所有按钮添加新的文本标签,然后我们可以导出设计,并在QDS中继续操作。
让我们继续添加文本,第二个实例是“Dashboard”,第三个是“Profile”,第四个是“Settings”。
现在可以看到为什么我们将文本框设置为按钮的固定宽度,并使用居中对齐选项,因为无论文本长度如何,文本始终在按钮设计的居中位置。
让我们再次导出,此时我们会得到一个警告,说我们将替代元数据,这没关系,所以我们继续,当它完成时,我们将回到QDS。
要确保进入QSD正确的项目,然后重复这些步骤以导入元数据文件,在QML库中点击import assets按钮会启动asset importer(资产导入器),这一点是非常重要,它确保我们在导入时选择的是合并选项,如果我们忘记这样做,将替代所有之前的工作,所以在继续之前,请确保选中合并选项。该项设置是固定的,所以只需要这样做一次,但为了安全起见,我们应在每次导入时确认一下。
只要选中合并,我们就可以导入设计,如果之前没有犯任何错误,这里应该没有错误或警告,所以我们可以继续查看导入文档。
要检查的第一项是新菜单组件,因此让我们在项目文件夹中查找myMenu_Symbol.ui.qml,并在表单编辑器中打开它。
应可看到带有四个按钮的菜单,每个按钮都有别名文本,因为已经为这些按钮创建了状态和交互,除了需要更改图标以外,该菜单应该可以正常使用。
让我们运行实时预览并开始测试,悬停并点击按钮,如您所见,基于第1部分教程完成的工作,无需任何重复工作,每个新添加的按钮都有了悬停、按下状态。希望这有效展示了组件化的强大功能,需要完成该步骤的开发者会喜欢这种功能。
当要更改这些按钮的整体行为时,我们只需要在主组件上操作,它将自动应用到所有实例。现在,我们将实现图标的正确状态。
让我们切换到按钮组件,并处理图标。
当按钮组件处于活动状态时,我们可以在导航器中看到每个图标的三个全新资产层,我们要重复第1部分教程中的步骤,让每个图标在每个状态下都可见,让我们单击每个状态,并使用属性中的可视性标志来实现这一点。确保默认状态时仅默认可见,悬停状态时仅悬停可见,按下状态时仅按下可见。
完成后,我们可以直接用实时预览来测试按钮,应该可以看到它能立即工作正常,我们还可以在菜单组件中对其快速测试,以确认它是否适用于所有的实例。
接下来,回到Sketch创建单个图标。在此之前,我们要准备这个按钮来换掉所有用例图标,为此需要在QDS中创建别名。首先确保我们的组件都处于基础状态,然后为我们的第一个图标(默认图标)选择资产。
在导航器中选择图标后,在属性面板中找到相关属性,即图标的源文件,然后使用操作图标打开菜单并选择add alias选项。这将意味着我们可以从菜单组件中的图标实例中为该按钮设置一个新的图标资产。
对每个图标资产重复该步骤,分别设置悬停和按下状态。设置图标源别名后,查看我们的菜单组件。
我们在表单编辑器加载myMenu_Symbol组件,选择一个按钮实例,我们可以在右侧属性面板中看到该实例的所有可用别名,包括我们在Sketch中添加的文本别名和和刚才在QDS中添加的三种图标状态的别名。
在Sketch中创建并修改一些图标后,我会再回来处理这些资产。
在Sketch中,我们将为这些图标创建一个artboard ,在QDS中导入的artboard通常就是组件,之后在设计屏幕时会经常使用到,但在本案例中,我们仅需从artboard导入资产、不生成任何QML,稍后我会详细说明。
现在,我们可以使用一个Sketch功能为资产创建单独页面,以便稍后区分它们和屏幕设计。点击Sketch的左上角菜单,添加一个新页面,并称之为Assets,然后拖出artboard开始设计图标,此artboard 的确切尺寸并不重要,它只是暂时存放资产,所以要确保它足够大,能容纳所有设计元素,我们可以专注于创建图标。
我们将在Sketch中直接绘制,并使用一些组合的形状来研究使用Bridge插件的合并功能。
让我们先画一个主页图标,一个矩形和一个三角形就可以实现,一旦把这两者放在一起,我们可以使用Combine Shape来创建一个元素,它将成为我们的图标,然后在Bridge插件中是看看组合结构是否合适。
组合形状看上去有点像该组件的迷你版,并是之前绘制形状的两个child的parent,因为只要一个图标资产,我们可以确保组合形状本身是Child,两个child设置为merge。我们要做的是在导出过程中将这两个图层合并为一个图像,该图像成为组合形状,因此会有ID。
在考虑非破坏性工作流时,这是一种特别有用的技术,因为我们可以最小化项目中的资产,但总是可以返回Sketch修改其中的部分设计。
因为想为每个图标做一些变体,我们可以简单地复制两次。在复制了两个额外版本后,我们可以微调颜色,同时,由于artboard 并非实际屏幕,我们可以把所有图标放在一起,不用担心它们的位置。在做第一个图标时,我也确保为每个图标变体和子形状创建唯一的QML ID。
第一个图标完成后,我们可以使用相同的技术快速完成其余三个,通过多个部分创建组合形状,确保合并形状的child设置为merge,合并后的形状本身就是Child,复制图标两次并使为每个图标制作三个变体。
为节省时间,我加快了这些视频的速度,但在设计过程中,每次我都重命名QML ID和图层,并检查只有顶部组合形状被设置为导出为Child,所有子形状被设置为合并。
现在我们有了四个图标,各有三个变体,让我们检查一下所有QML ID,确保它们在项目中是唯一且有意义。
首先从artboard开始,可将其命名为iconAssets,尽管我们不打算从该artboard 生成QML,但每次检查ID是好习惯,希望某天它能成为您的第二天性。
myButton_icon_home_default myButton_icon_home_hovermyButton_icon_home_pressedmyButton_icon_dashboard_defaultmyButton_icon_dashboard_hovermyButton_icon_dashboard_pressedmyButton_icon_profile_defaultmyButton_icon_profile_hovermyButton_icon_profile_pressedmyButton_icon_settings_defaultmyButton_icon_settings_hovermyButton_icon_settings_pressed
我们还应确保所有child的ID(即便不是项目的一部分,因此不那么重要)也是唯一的,以确保导入过程中不会出现任何错误。因此,与其使用命名方案,不如简单在此处列举。
例如,home图标将该模式用于合并形状。
homeSquare1homeTriangle1
homeSquare2homeTriangle2
homeSquare3homeTriangle3
现在,所有图标都设置好了,QML ID均以选中,我们可以重新导出项目、回到QDS,把这些图标添加到按钮中。让我们按下Export按钮,并选择替代元数据。
现在我们可以回到QDS和asset importer,这次使用asset importer的另一个功能,通过取消选择生成QML只导入新的图标资产,我们依然要选择merge,然后继续导入我们的项目。
现在我们有了所有图标资产,无需生成任何新的QML,因为只需要使用实例的别名属性来交换图标的正确版本。让我们选择第一个组件实例,利用先前为此创建的别名属性,点击第一个按钮,home图标,并在属性面板中使用下拉框选择图标的新资产,为每个状态将选择合适的资产,然后在实时预览中进行测试。
现在有了第一个按钮的新工作图标,让我们对其余图标重复该过程,直至每个实例中都有正确的图标,然后在实时预览中再次测试以确保所有状态都正常运行。
本部分教程到此结束,在本系列的下篇,我们将使用菜单组件来绘制和构建不同的屏幕设计,并关注一些更高级的功能。
以下是所有项目文件:
https://www.dropbox.com/sh/0hirm3a8ut5n3w5/AABqukZ-Xc88QCT7RFVYzDDZa?dl=0
以下是两个组件的QML代码:
MyButton_Symbol.ui.qml
import QtQuick 2.8 Item { id: myButton_Symbol width: 211 height: 211 property alias myButton_icon_placeholder_defaultSource: myButton_icon_placeholder_default.source property alias myButton_icon_placeholder_pressedSource: myButton_icon_placeholder_pressed.source property alias myButton_icon_placeholder_hoverSource: myButton_icon_placeholder_hover.source state: "default" property alias myButton_Symbol_labelText: myButton_Symbol_label.text Image { id: myButton_SymbolAsset x: 0 y: 0 source: "assets/myButton_Symbol.png" } Image { id: myButton_Symbol_default x: 0 y: 0 source: "assets/myButton_Symbol_default.png" } Image { id: myButton_Symbol_hover x: 0 y: 0 source: "assets/myButton_Symbol_hover.png" } Image { id: myButton_Symbol_pressed x: 0 y: 0 source: "assets/myButton_Symbol_pressed.png" } Text { id: myButton_Symbol_label x: 6 y: 150 width: 200 height: 23 color: "#ff818181" text: "default text" font.styleName: "Light" horizontalAlignment: Text.AlignHCenter font.family: "Helvetica Neue" font.pixelSize: 20 verticalAlignment: Text.AlignVCenter } Image { id: myButton_icon_placeholder_pressed x: 70 y: 55 source: "assets/myButton_icon_placeholder_pressed.png" } Image { id: myButton_icon_placeholder_hover x: 70 y: 55 source: "assets/myButton_icon_placeholder_hover.png" } Image { id: myButton_icon_placeholder_default x: 70 y: 55 source: "assets/myButton_icon_placeholder_default.png" } MouseArea { id: myButton_Symbol_MouseArea x: 0 y: 0 width: 211 height: 211 hoverEnabled: true } states: [ State { name: "default" when: !myButton_Symbol_MouseArea.containsMouse && !myButton_Symbol_MouseArea.pressed PropertyChanges { target: myButton_Symbol_hover visible: false } PropertyChanges { target: myButton_Symbol_pressed visible: false } PropertyChanges { target: myButton_icon_placeholder_pressed visible: false } PropertyChanges { target: myButton_icon_placeholder_hover visible: false } }, State { name: "hover" when: myButton_Symbol_MouseArea.containsMouse && !myButton_Symbol_MouseArea.pressed PropertyChanges { target: myButton_Symbol_pressed visible: false } PropertyChanges { target: myButton_Symbol_default visible: false } PropertyChanges { target: myButton_icon_placeholder_pressed visible: false } PropertyChanges { target: myButton_icon_placeholder_default visible: false } }, State { name: "pressed" when: myButton_Symbol_MouseArea.pressed PropertyChanges { target: myButton_Symbol_default visible: false } PropertyChanges { target: myButton_Symbol_hover visible: false } PropertyChanges { target: myButton_icon_placeholder_default visible: false } PropertyChanges { target: myButton_icon_placeholder_hover visible: false } }myMenu_Symbol.ui.qml
import QtQuick 2.8 Item { id: myMenu_Symbol width: 250 height: 850 Image { id: myMenu_SymbolAsset x: 0 y: 0 source: "assets/myMenu_Symbol.png" } MyButton_Symbol { id: myButton_myMenu_settings x: 20 y: 639 width: 211 height: 211 myButton_icon_placeholder_defaultSource: "assets/myButton_icon_settings_default.png" myButton_icon_placeholder_hoverSource: "assets/myButton_icon_settings_hover.png" myButton_icon_placeholder_pressedSource: "assets/myButton_icon_settings_pressed.png" myButton_Symbol_labelText: "Settings" } MyButton_Symbol { id: myButton_myMenu_profile x: 20 y: 428 width: 211 height: 211 myButton_icon_placeholder_defaultSource: "assets/myButton_icon_profile_default.png" myButton_icon_placeholder_hoverSource: "assets/myButton_icon_profile_hover.png" myButton_icon_placeholder_pressedSource: "assets/myButton_icon_profile_pressed.png" myButton_Symbol_labelText: "Profile" } MyButton_Symbol { id: myButton_myMenu_dashboard x: 20 y: 217 width: 211 height: 211 myButton_icon_placeholder_defaultSource: "assets/myButton_icon_dashboard_default.png" myButton_icon_placeholder_hoverSource: "assets/myButton_icon_dashboard_hover.png" myButton_icon_placeholder_pressedSource: "assets/myButton_icon_dashboard_pressed.png" myButton_Symbol_labelText: "Dashboard" } MyButton_Symbol { id: myButton_MyMenu_home x: 20 y: 6 width: 211 height: 211 myButton_icon_placeholder_defaultSource: "assets/myButton_icon_home_default.png" myButton_icon_placeholder_hoverSource: "assets/myButton_icon_home_hover.png" myButton_icon_placeholder_pressedSource: "assets/myButton_icon_home_pressed.png" myButton_Symbol_labelText: "Home" } }