开发和使用 ADF Faces 外观 作者: Jonas Jacobi,Oracle Corporation 2006 年 1 月 介绍 ADF Faces 外观特性 ADF Faces 可让您更改应用程序的外观,而无需重写实现应用程序用户界面的代码。ADF Faces 提供了两个父系外观(Simple 和 Minimal),您可以扩展这两个外观以便为应用程序提供自定义外观。默认情况下,自定义外观会继承其父系外观的外观特性。如果您希望修改组件外观,只需提供自定义样式定义和自定义图标。 本方法文档演示了如何使用 Oracle JDeveloper 10.1.3 创建一个取代默认 Oracle 外观的简单 ADF Faces 外观。有关更多信息和方法文档,请参阅 Oracle 技术网 (OTN) 上的 JDeveloper 方法文档。对于这个简单的应用程序,我们仅使用 ADF Faces 组件,其中没有业务逻辑。 任务 本文包括下列任务: - 创建一个能够覆盖简单主题样式表的新样式表(使用 CSS 3.0 语法)
- 创建一个新的 ADF Faces 外观配置文件 — adf-faces-skins.xml
- 在需要的地方添加图像
- 更改特定组件上的文本
- 在 adf-faces-config.xml 文件中设置新的 ADF Faces 外观
前提条件 本方法文档以及构建这个新的 ADF Faces 外观没有特定编辑器要求,但出于教学目的,我们将使用 Oracle JDeveloper 10.1.3 EA1 版 — 此外,如果您希望编辑并取代本方法文档中提供的图像,可能需要图像编辑器。您还需要下载示例 WAR 文件 ( adffaces_skin.war ),该文件包含了本方法文档所需的较新版本的 ADF Faces 以及一个简单的 JSF 页面(该页面包含了一些将用于演示新外观效果的 ADF Faces 组件)。 ADF Faces 默认外观 ADF Faces 提供了三个您可以在应用程序中“按原样”使用的主要外观 — Oracle (oracle)、Minimal (minimal) 和 Simple (simple)。应用程序的默认外观设置为“oracle”,该外观可使应用程序符合 Oracle 的 UI 标准(浏览器外观 — BLAF)。Minimal 外观提供了某些格式,Simple 外观几乎不包含任何特殊格式。 关于外观 ADF Faces 中的外观是一个全局样式表,只需在一个地方设置,即可用于整个应用程序。您可以为整个应用程序创建一个外观,而无需设置每个组件的样式,或者在每个页面上插入样式表。每个组件将自动使用外观所描述的样式。对外观进行的所有更改将在运行时选出,不需要更改代码。外观基于层叠样式表规范,并且使用 CSS 3.0 语法。 除了使用 CSS 文件确定样式以外,外观还使用资源包确定文本。例如,ADF Faces 表格组件的导航栏中的“上一个”和“下一个”文字就是使用外观资源包确定的。所包含的所有外观都使用相同的资源包。 创建自定义外观 您可以通过扩展 Simple 外观并覆盖所提供的选择器来创建自定义外观。有三种不同类型的选择器 — 全局、按钮和组件级选择器。 - 全局样式选择器是影响多个组件的选择器。如果选择器名称以 :alias 伪类结尾,则该选择器很可能包含在其他特定于组件的选择器中。为以 :alias 结尾的选择器定义属性很可能会影响多个组件的外观。
- 组件级选择器是可用于定义特定 ADF Faces 组件外观的选择器。下面定义的选择器由它们所影响的组件指定。假设您要定义 af:chooseDate 组件的外观。其中一个选择器是 af|chooseDate::title。 ::title 伪元素指出,这是 af:chooseDate 组件的标题部分。如果您要定义 af:chooseDate 组件标题的外观,可以在 ADF Faces 外观的 .css 文件中设置 af|chooseDate::title 选择器的 css 属性。
您可以在组件级部分中看到以 :alias 结尾的选择器名称。这意味着,系统提供了定义共享特定样式或图标的多个组件的外观、或者定义某个组件多个部分的外观的快捷方式。例如, .AFMenuBarItem:alias 样式定义了由所有 af:menuBar 项共享的外观属性。这包含在 af|menuBar::enabled 和 af|menuBar::selected 样式类中。因此,如果您更改 .AFMenuBarItem:alias 样式,将影响 af|menuBar::enabled 和 af|menuBar::selected 样式选择器。 - ADF Faces 目前不支持按钮的组件级选择器。例如,您不能自定义与 commandButton 不同的 goButton。外观支持两个截然不同的按钮实现。默认情况下,使用标准浏览器按钮。然而,外观还支持动态生成基于图像的按钮。要启用基于图像的按钮,必须指定以下四个按钮图标:
1. .AFButtonStartIcon:alias 2. .AFButtonEndIcon:alias 3. .AFButtonTopBackgroundIcon:alias 4. .AFButtonBottomBackgroundIcon:alias 在指定这四个图标之后,ADF Faces 会将这些图标指定的图像组合到单一按钮图像中。(请注意:必须使用上下文图像图标或资源图像图标来指定这些图标。不允许使用基于文本的图标。) 创建自定义外观 在大多数情况下,您可能不需要自定义 ADF Faces 组件库中每个组件的外观(毕竟有 84 个 UI 组件)。例如,通过查看使用 Simple 外观的应用程序,您可以确定要自定义哪些组件。 注意:目前,应用程序开发人员只能扩展 Simple 外观。 如果您尚未下载 Oracle JDeveloper 10.1.3 EA 1 版,请立即下载。解压缩并启动 JDeveloper。 - 在 JDeveloper 中,创建一个新的应用程序工作区,并将其命名为 ADFFaces_skin_sample。取消要求创建新项目的对话框。
- 右键单击新的应用程序工作区,并创建一个新的“Project from WAR file”,然后单击 OK。
- 输入 view 作为该项目的新名称,然后单击 Next。
- 在选择 WAR 文件的对话框中,选择您刚刚下载的 adffaces_skin.war 文件。单击 FINISH 关闭对话框。
- 我们必须首先确保 WAR 文件随附的 ADF Faces 库在可视编辑器中执行,才能在可视编辑器中查看示例页面。双击 view 项目节点打开 Project Properties 对话框。
- 在 Project Properties 对话框中,选择 JSP Tag Libraries 并确保为两个 ADF Faces 库选中“Execute Tags in JSP Visual Editor”选项。
- 重要事项:您还需要添加 JSF Core 和 JSF HTML 标记库,如上图所示。
- 单击 OK 关闭对话框。
- 找到 sample.jspx 并在可视编辑器中打开它。
- 熟悉一下页面,以了解 ADF Faces 组件在页面上的形式。
- 确保您还查看了为该外观示例应用程序提供的文件。
![]() 图 1. JDeveloper 10.1.3 中所示的 sample.jspx 页面的屏幕截图 外观包含以下内容: - 定义组件实际外观的 CSS 文件
- 列出该应用程序可用的所有外观(不包括 Oracle、Minimal 和 Simple)的配置文件 — adf-faces-skins.xml。该文件必须位于应用程序的 WEB-INF 目录中
- ADF Faces 配置文件中的项 — adf-faces-config.xml
- 创建组件实际外观所需的任何其他资源 — 其他 CSS 文件、图像等……
修改 ADF Faces 外观 CSS 示例应用程序已经包含一个预先封装的 CSS 文件,我们将使用并扩展该文件以便为组件创建所需的外观。对于该文件,您可以将希望覆盖的任何选择器添加到您的 CSS 文件,然后根据需要设置属性。您可以设置 CSS 规范支持的任何属性,还可以创建自己的别名类。 示例应用程序还包含一个 adf-faces-skins-doc.xml 文件。该文件包含了有关 ADF Faces 提供的、并且您可以覆盖的所有样式类和选择器的信息。该文件位于 skins 目录中。 ![]() 图 2. skins 目录中的 adf-faces-skins-doc.xml 文件 更改外观的配色方案 更改应用程序外观的最简单部分就是更改外观的基类,令其使用其他颜色。例如,未更改的 Simple 外观如下所示: ![]() 然后,对以下别名类进行一些微小的更改: .AFDarkForeground:alias {color:#003366;} .AFDarkBackground:alias {background-color:#003366;} 您可以通过更改控制 Simple 外观基色的样式类来更改外观: ![]() 将外观添加到 ADF Faces 组件 我们将为其提供外观的组件是 af:selectOneShuttle、 af:selectManyShuttle 和 af:selectInputDate。下面将从 af:selectInputDate 组件开始。目前, af:selectInputDate 组件使用 Oracle 外观,如下所示: ![]() 但我们打算将外观更改如下: ![]() 为此,我们需要为 af:selectInputDate 组件添加组件选择器。通过将以下代码示例添加到 myComponent.css 文件,我们可以更改 Calendar 启动按钮的图标。 - 双击打开 myCompanySkin.css 文件。这将显示 JDeveloper CSS 编辑器。
- 在 myCompany.css 文件的顶部搜索以下列内容开头的部分:
/** Section where to add styles/selectors used in the ADF Faces Skin Sample **/ /** ======================================================================= **/ - 将以下 selectInputDate 样式类代码片段添加到注释
/** selectInputDate launch icon **/ 后面 af|selectInputDate::launch-icon { content:url(/skins/mycompany/skin_images/timedate_ena.png); } af|selectInputDate::launch-icon:rtl { content:url(/skins/mycompany/skin_images/timedate_ena.png); } - 保存更改。
接下来,我们来看一下 ADF Faces 移动控件。ADF Faces 中有两个移动控件 - af:selectOneShuttle 和 af:selectOneShuttle。您可以为每个控件调整外观,也可以为这两个控件创建一个外观。该组件比 af:selectInputDate 组件略微复杂一些,它具有更多可以调整的控件和属性。这两个控件的默认外观如下: ![]() 我们打算将其更改为: ![]() - 在 myCompany.css 文件中,将以下代码片段添加到 selectInputDate 样式后面
/** Shuttle icons selectOne, selectMany, and selectOrder shuttles**/ .AFShuttleMoveIcon:alias {content:url(/skins/mycompany/skin_images/move.png); width:16px; height:16px;} .AFShuttleMoveAllIcon:alias {content:url(/skins/mycompany/skin_images/moveAll.png); width:16px; height:16px;} .AFShuttleRemoveIcon:alias {content:url(/skins/mycompany/skin_images/remove.png); width:16px; height:16px;} .AFShuttleRemoveAllIcon:alias {content:url(/skins/mycompany/skin_images/removeAll.png); width:16px; height:16px;} /** Icons unique to the selectOrderShuttle for re-ordering user selections **/ af|selectOrderShuttle::reorder-top-icon { content:url(/skins/mycompany/skin_images/reordertop_enabled.png); width:16px; height:16px; } af|selectOrderShuttle::reorder-up-icon { content:url(/skins/mycompany/skin_images/reorderup_enabled.png); width:16px; height:16px; } af|selectOrderShuttle::reorder-down-icon { content:url(/skins/mycompany/skin_images/reorderdown_enabled.png); width:16px; height:16px; } af|selectOrderShuttle::reorder-bottom-icon { content:url(/skins/mycompany/skin_images/reorderbottom_enabled.png); width:16px; height:16px;} - 保存您的工作。
通过使用梭形控件的别名类,我们可以将一组对所有梭形控件通用的图标添加到外观。通过使用特定于组件的选择器,我们还可以将特殊图标添加到 selectOrderShuttle 控件。将 width 和 height 添加到使用图像/图标的任何样式很重要,因为某些浏览器在显示实际图标时可能会出现问题,如 Internet Explorer。 注意:ADF Faces 有一个错误,即:在实际 URI 周围添加 "" - 如 url("/skins/mycompany/skin_images/reorderdown_enabled.png") - 的情况下会破坏图像/图标, 这将导致图标在呈现时无法显示。解决方法是移除 ""。 与我们能够在本方法文档中涵盖的外观相比,示例外观包含了更多的样式。实际 CSS 文件中还包含了其他三个值得您探究的组件 - af:table、 af:showOneTab 和 af:menuTabs。 设置自定义外观 现在,我们来看一下如何设置应用程序使用 ADF Faces 自定义外观。 首先,我们需要 CSS 文件,该文件存储在 web 应用程序根目录下的某个地方。在示例应用程序中,它存储在 /skin/myCompany 目录中。我们还应该确保能够访问外观所需的所有资源,如图像和其他 CSS 文件。在示例应用程序中,这些资源存储在 /skin/myCompany/images 目录中。 其次,我们需要确保 ADF Faces 应用程序支持自定义外观。这是通过将配置文件添加到名为 adf-faces-skins.xml 的 WEB-INF 目录来完成的。 注册自定义外观 <id> 元素用于在 EL 表达式中引用外观。例如,如果您希望为不同的地域使用不同的外观,可以创建一个基于 ID 选择正确外观的 EL 表达式。 <family> 元素用于配置应用程序使用特定外观系列。这使您能够根据所使用的呈现器工具包将应用程序的外观组合在一起。 <render-kit-id> 用于决定对外观使用哪个呈现器工具包。您可以输入以下其中一个外观: - oracle.adf.desktop:当应用程序在桌面上呈现时,将自动使用该外观。
- oracle.adf.pda:在 PDA 上呈现时,将使用该外观。
<style-sheet-name> 元素用于定义自定义 CSS 文件的路径。 - 在 JDeveloper 中,右键单击示例项目的 WEB-INF 文件夹,然后创建一个新的 XML 文档并将其命名为 adf-faces-skins.xml。
- 使用以下代码替换生成的代码:
<?xml version="1.0" encoding="ISO-8859-1"?> <skins xmlns="http://xmlns.oracle.com/adf/view/faces/skin"> <skin> <id>mycompany.desktop</id> <family>mycompany</family> <render-kit-id>oracle.adf.desktop</render-kit-id> <style-sheet-name>skins/mycompany/myCompanySkin.css</style-sheet-name> </skin> </skins> - 保存您的工作。
配置应用程序使用自定义外观 如果需要,最好在 adf-faces-config.xml 文件中设置一个确定要使用哪个外观的元素。配置应用程序使用外观: - 打开 adf-faces-config.xml 文件。
- 使用您希望使用的外观的系列名称替换 <skin-family> 值。
- 要有条件地设置该值,请输入一个能够确定要显示外观的 EL 表达式。
例如,如果您希望对设置为 German 区域选项的用户浏览器使用 German 外观,并且对其他区域使用 English 外观,可以将以下项添加到 adf-faces-config.xml 文件。 <skin-family>#{facesContext.viewRoot.locale.language=='de' ?'german' :'english'}</skin-family> - 在示例应用程序中,我们将使用 selectOneChoice 组件在运行时切换外观,因此需要使用以下内容替换 adf-faces-config.xml 文件中的 <skin-family>oracle</skin-family>:
<skin-family>#{sessionScope.skinFamily}</skin-family> - 保存您的工作。
现在,我们来添加将在运行时执行实际切换的实际组件 - 在源代码编辑器中打开 sample.jspx 文件。
- 在源代码中找到以下注释:
<!-- ================================================================ --> <!-- Add the sample selectOneChoice component here. --> - 现在,添加以下代码片段:
<f:facet name="menuGlobal"> <af:selectOneChoice label="Select Skin" value="#{sessionScope.skinFamily}" onchange="form.submit();"> <af:selectItem label="Simple" value="simple"/> <af:selectItem label="Minimal" value="minimal"/> <af:selectItem label="Oracle" value="oracle"/> <af:selectItem label="MyCompany" value="mycompany"/> </af:selectOneChoice> </f:facet> 只要在 selectOneChoice 组件中选择一个外观,onchange 事件处理程序就会执行一个表单 POST。此外,您还可以将一个用于重新提交页面的 commandButton 添加到页面。每当有一个 POST,就会计算 EL 表达式,如果有一个新值,就会使用新外观重绘页面。 - 保存您的工作,然后运行 sample.jspx 页面。使用切换器选择一个外观!
![]() 总结 创建 ADF Faces 外观很简单,使用它们甚至更简单。应用程序开发人员可以使用 EL 表达式和 JSF 支持 bean(本示例中没有说明)根据任何条件设置一个外观。这使应用程序开发人员能够针对每个用户、页面、应用程序等使用不同的外观,而不会影响实际应用程序逻辑! |