通过 API 自定义 UI 元素
本节介绍如何通过 UI Extensions 提供的 API,对内置 UI 进行“运行时”的显示/隐藏与增删改,例如:
- 顶部/底部工具栏(Top/Bottom Toolbar)
- 面板(Panel,例如 Outline)
- 视图设置栏(View Setting Bar)
- 更多菜单(More Menu)
说明
以下示例以 SDK 自带的 samples/complete_pdf_viewer 为参考场景。示例代码通常添加在 PDFReaderFragment.java 中(在 mUiExtensionsManager = new UIExtensionsManager(...) 之后)。
1. 自定义顶部/底部工具栏(Top/Bottom Toolbar)
本节示例较多。建议先阅读“位置与索引说明”,再按“需求分类”快速定位对应用法。
1.1 位置与索引说明(重要)
在调用 addItem / removeItem / getItemByIndex 等 API 时,需要通过 工具栏名称(BarName) 与 位置(TB_Position) 来定位“往哪一段工具栏、哪个区域”添加/移除 item。下面为相关枚举示意:
java
enum BarName {
TOP_BAR,
BOTTOM_BAR
}
enum TB_Position {
Position_LT,
Position_CENTER,
Position_RB
}
使用说明
- Phone/Tablet 差异:平板设备默认没有底部工具栏。
- 位置选择:
- 添加到顶部工具栏时,请使用
Position_LT或Position_RB。 - 添加到底部工具栏时,请使用
Position_CENTER。 - 若位置选择不当,可能导致 item 发生重叠或布局异常。
- 添加到顶部工具栏时,请使用
- 索引规则:手机端工具栏按"顶部左 / 顶部右 / 底部"分成 3 个区域,每个区域的按钮(item) 索引独立;平板端仅存在顶部左右两段。
- 文本长度建议:为避免布局错乱,建议顶部工具栏文字不超过 15 个字符、底部工具栏不超过 8 个字符。
1.2 示例(按需求分类)
提示
平板与手机的内置 UI 布局存在差异;部分示例仅适用于手机或平板。请以示例标题/注释中的适用范围为准。
1.2.1 显示/隐藏工具栏
示例 1:隐藏顶部工具栏
java
mUiExtensionsManager.enableTopToolbar(false);
示例 2:隐藏底部工具栏(仅 Phone)
java
mUiExtensionsManager.enableBottomToolbar(false);
1.2.2 添加工具栏按钮
示例 3:向顶部工具栏左侧添加自定义按钮
工具栏按钮的创建与点击事件写法基本一致,差异主要在于 加入的位置(Position_LT / Position_RB) 与 索引(index)。以下是添加 “左侧按钮”示例:
java
BaseItemImpl mTopItem1 = new BaseItemImpl(getContext(), R.drawable.rd_delete_menu);
mTopItem1.setImageTintList(ColorStateList.valueOf(Color.WHITE));
mTopItem1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
UIToast.getInstance(getActivity()).show("Add an item in the left top toolbar at the second position.");
}
});
mUiExtensionsManager.getBarManager().addItem(IBarsHandler.BarName.TOP_BAR, BaseBar.TB_Position.Position_LT, mTopItem1, 1);
示例 4:向顶部工具栏右侧添加自定义按钮
java
BaseItemImpl mTopItem2 = new BaseItemImpl(getContext(), R.drawable.rd_delete_menu);
mTopItem2.setImageTintList(ColorStateList.valueOf(Color.WHITE));
mTopItem2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
UIToast.getInstance(getActivity()).show("Add an item in the right top toolbar at the first position");
}
});
mUiExtensionsManager.getBarManager().addItem(IBarsHandler.BarName.TOP_BAR, BaseBar.TB_Position.Position_RB, mTopItem2, 0);
示例 5:向底部工具栏添加按钮(仅 Phone)
java
mUiExtensionsManager.getBarManager().addItem(
IBarsHandler.BarName.BOTTOM_BAR,
BaseBar.TB_Position.Position_CENTER,
"",
R.drawable.ic_bar_item_more,
0,
new IBarsHandler.IItemClickListener() {
@Override
public void onClick(View v) {
UIToast.getInstance(getActivity()).show("Add an item to the bottom toolbar at the first position.");
}
}
);
示例 6:向底部工具栏添加自定义样式按钮(仅 Phone)
java
BaseItemImpl mSettingBtn = new BaseItemImpl(this.getContext(), R.drawable.rd_annot_create_ok_selector);
mSettingBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
UIToast.getInstance(getActivity()).show("Add an item with custom style to the bottom toolbar at the second position.");
}
});
mUiExtensionsManager.getBarManager().addItem(IBarsHandler.BarName.BOTTOM_BAR, BaseBar.TB_Position.Position_CENTER, mSettingBtn, 1);
1.2.3 移除工具栏按钮
示例 7:按 index 移除按钮(仅 Phone)
java
mUiExtensionsManager.getBarManager().removeItem(
IBarsHandler.BarName.BOTTOM_BAR,
BaseBar.TB_Position.Position_CENTER,
0
);
示例 8:按 BaseItem 对象移除按钮
java
mUiExtensionsManager.getBarManager().removeItem(
IBarsHandler.BarName.TOP_BAR,
BaseBar.TB_Position.Position_LT,
mTopItem1
);
示例 9:移除底部工具栏所有按钮(仅 Phone)
java
mUiExtensionsManager.getBarManager().removeAllItems(IBarsHandler.BarName.BOTTOM_BAR);
1.2.4 动态控制指定按钮显示/隐藏
示例 10:显示/隐藏指定按钮(以 More Menu 按钮为例)
java
// 获取需要显示/隐藏的按钮引用
final IBarsHandler barsHandler = (IBarsHandler) mUiExtensionsManager.getBarManager();
final IBaseItem moreItem = barsHandler.getItemByIndex(
IBarsHandler.BarName.TOP_BAR,
BaseBar.TB_Position.Position_RB,
1
);
// 添加一个按钮,点击后隐藏 "moreItem"
BaseItemImpl topItem = new BaseItemImpl(getContext(), R.drawable.rd_delete_menu);
topItem.setImageTintList(ColorStateList.valueOf(Color.WHITE));
topItem.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 隐藏 "moreItem"
mUiExtensionsManager.getBarManager().removeItem(
IBarsHandler.BarName.TOP_BAR,
BaseBar.TB_Position.Position_RB,
moreItem
);
}
});
mUiExtensionsManager.getBarManager().addItem(IBarsHandler.BarName.TOP_BAR, BaseBar.TB_Position.Position_LT, topItem, 1);
// 添加一个按钮,点击后显示 "moreItem"
BaseItemImpl topItem2 = new BaseItemImpl(getContext(), R.drawable.common_add_icon);
topItem2.setImageTintList(ColorStateList.valueOf(Color.WHITE));
topItem2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 显示 "moreItem"
if (AppDisplay.isPad())
mUiExtensionsManager.getBarManager().addItem(IBarsHandler.BarName.TOP_BAR, BaseBar.TB_Position.Position_RB, moreItem, 3);
else
mUiExtensionsManager.getBarManager().addItem(IBarsHandler.BarName.TOP_BAR, BaseBar.TB_Position.Position_RB, moreItem, 1);
}
});
mUiExtensionsManager.getBarManager().addItem(IBarsHandler.BarName.TOP_BAR, BaseBar.TB_Position.Position_LT, topItem2, 2);
1.2.5 工具栏结构调整(工具栏 / 标签栏/ 入口)
示例 11:移除整个底部工具栏(仅 Phone)
java
mUiExtensionsManager.getBarManager().removeToolBar(IBarsHandler.BarName.BOTTOM_BAR);
示例 12:添加自定义工具栏
java
View topView = View.inflate(getContext(), R.layout.test_top_layout, null);
mUiExtensionsManager.getBarManager().addCustomToolBar(IBarsHandler.BarName.TOP_BAR, topView);
示例 13:移除顶部工具栏中间区域的 “表单” 标签
java
mUiExtensionsManager.getMainFrame().removeTab(ToolbarItemConfig.ITEM_FORM_TAB);
示例 14:移除 “视图” 入口
java
if (AppDisplay.isPad())
mUiExtensionsManager.getMainFrame().removeTab(ToolbarItemConfig.ITEM_VIEW_TAB);
else
mUiExtensionsManager.getBarManager().removeItem(
IBarsHandler.BarName.BOTTOM_BAR,
BaseBar.TB_Position.Position_CENTER,
1
);
2. 自定义面板(Panel)
2.1 API 概览
java
// 添加子面板。若面板类型已存在,则不会重复添加。
public void addPanel(PanelSpec panelSpec);
public void addPanel(int index, PanelSpec panelSpec);
// 移除子面板。
public void removePanel(int panelType);
public void removePanel(PanelSpec panelSpec);
使用 removePanel(PanelSpec) 移除内置面板时,可参考下面的内置面板与 PanelSpec 对照表;使用 removePanel(int panelType) 时,则需传入对应的 panelType(表格中的 panelType(integer) 列)。
| 面板 | PanelSpec | panelType(integer) |
|---|---|---|
| Bookmarks | PanelSpec.BOOKMARKS | 0 |
| Outline | PanelSpec.OUTLINE | 1 |
| Comments | PanelSpec.ANNOTATIONS | 2 |
| Attachments | PanelSpec.ATTACHMENTS | 3 |
| Digital Signatures | PanelSpec.SIGNATURES | 4 |
2.2 示例(按需求分类)
2.2.1 移除内置面板
示例 1:通过按钮移除 Outline 面板
java
BaseItemImpl removePanel = new BaseItemImpl(getActivity(), R.drawable.rd_delete_menu);
removePanel.setImageTintList(ColorStateList.valueOf(Color.WHITE));
removePanel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mUiExtensionsManager.getPanelManager().removePanel(PanelSpec.OUTLINE);
}
});
mUiExtensionsManager.getBarManager().addItem(IBarsHandler.BarName.TOP_BAR, BaseBar.TB_Position.Position_LT, removePanel, 1);
2.2.2 添加自定义面板
示例 2:在点击事件中添加一个自定义面板
java
BaseItemImpl customPanel = new BaseItemImpl(getActivity(), R.drawable.common_add_icon);
customPanel.setImageTintList(ColorStateList.valueOf(Color.WHITE));
customPanel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mUiExtensionsManager.getPanelManager().addPanel(new CustomPanel(getContext()));
}
});
mUiExtensionsManager.getBarManager().addItem(IBarsHandler.BarName.TOP_BAR, BaseBar.TB_Position.Position_LT, customPanel, 1);
CustomPanel 需实现 PanelSpec 接口,例如:
java
package com.foxit.home;
import android.content.Context;
import android.content.res.ColorStateList;
import android.view.View;
import android.widget.TextView;
import com.foxit.uiextensions.controls.panel.PanelSpec;
import com.foxit.uiextensions.controls.toolbar.BaseBar;
import com.foxit.uiextensions.controls.toolbar.IBaseItem;
import com.foxit.uiextensions.controls.toolbar.impl.BaseItemImpl;
import com.foxit.uiextensions.controls.toolbar.impl.TopBarImpl;
public class CustomPanel implements PanelSpec {
private Context mContext;
public CustomPanel(Context context) {
mContext = context;
}
@Override
public int getIcon() {
return R.drawable.toolbar_thumbnail_icon;
}
@Override
public ColorStateList getIconTint() {
return null;
}
@Override
public int getPanelType() {
return 100;
}
@Override
public View getTopToolbar() {
TopBarImpl topBar = new TopBarImpl(mContext);
IBaseItem baseItem = new BaseItemImpl(mContext);
baseItem.setText("Custom Panel");
topBar.addView(baseItem, BaseBar.TB_Position.Position_CENTER);
return topBar.getContentView();
}
@Override
public View getContentView() {
TextView textView = new TextView(mContext);
textView.setText("This is empty");
return textView;
}
@Override
public void onActivated() {
}
@Override
public void onDeactivated() {
}
}
3. 自定义视图设置栏(View Setting Bar)
可通过 setVisible 控制视图设置栏(View Setting Bar)中指定选项的显示/隐藏。
3.1 API 概览
java
public void setVisible(int type, boolean visible);
3.2 type 取值(常量)
java
IViewSettingsWindow.TYPE_SINGLE_PAGE // 1
IViewSettingsWindow.TYPE_FACING_PAGE // 2
IViewSettingsWindow.TYPE_COVER_PAGE // 4
IViewSettingsWindow.TYPE_DAY // 8
IViewSettingsWindow.TYPE_PAGE_COLOR // 16
IViewSettingsWindow.TYPE_NIGHT // 32
IViewSettingsWindow.TYPE_CONTINUOUS_PAGE // 64
IViewSettingsWindow.TYPE_FIT_PAGE // 128
IViewSettingsWindow.TYPE_FIT_WIDTH // 256
IViewSettingsWindow.TYPE_REFLOW // 288
IViewSettingsWindow.TYPE_CROP // 320
IViewSettingsWindow.TYPE_TTS // 384
IViewSettingsWindow.TYPE_AUTO_FLIP // 512
IViewSettingsWindow.TYPE_ROTATE_VIEW // 544
IViewSettingsWindow.TYPE_PAN_ZOOM // 576
IViewSettingsWindow.TYPE_RIGHT_TO_LEFT // 608
3.3 示例
示例 1:隐藏 “Fit Width” 选项
java
mUiExtensionsManager.getSettingWindow().setVisible(IViewSettingsWindow.TYPE_FIT_WIDTH, false);
4. 自定义更多菜单(More Menu)
More Menu 支持隐藏指定菜单组/菜单项,也支持新增自定义菜单组与菜单项。
4.1 API 概览
java
// 通过 IMenuItem 添加菜单项。
IMenuGroup.addItem(IMenuItem item);
IMenuGroup.addItem(CharSequence title);
IMenuGroup.addItem(Drawable icon, CharSequence title);
// 切换可见性。
IMenuGroup.setVisible(boolean visible);
IMenuItem.setVisible(boolean visible);
4.2 示例
示例 1:隐藏某个菜单组
java
IMenuView menuView = mUiExtensionsManager.getMenuView();
IMenuGroup menuGroup = menuView.getGroup(MoreMenuConstants.GROUP_ACTION_MENU_PRIMARY);
menuGroup.setVisible(false);
示例 2:隐藏某个菜单项
java
IMenuView menuView = mUiExtensionsManager.getMenuView();
IMenuGroup menuGroup = menuView.getGroup(MoreMenuConstants.GROUP_ACTION_MENU_SECONDARY);
IMenuItem menuItem = menuGroup.getItem(MoreMenuConstants.ITEM_SECONDARY_PRINT);
menuItem.setVisible(false);
示例 3:新增自定义菜单组与菜单项
java
IMenuView menuView = mUiExtensionsManager.getMenuView();
IMenuGroup customGroup = menuView.addGroup("Custom Group");
IMenuItem item1 = customGroup.addItem(AppResource.getDrawable(getActivity(), R.drawable.rd_comment_menu), "comment");
item1.setOnMenuItemClickListener(new IMenuItem.OnMenuItemClickListener() {
@Override
public void onClick(IMenuItem item) {
UIToast.getInstance(getActivity()).show("I am item1");
}
});
IMenuItem item2 = customGroup.addItem(AppResource.getDrawable(getActivity(), R.drawable.rd_delete_menu), "delete");
item2.setOnMenuItemClickListener(new IMenuItem.OnMenuItemClickListener() {
@Override
public void onClick(IMenuItem item) {
UIToast.getInstance(getActivity()).show("I am item2");
}
});
4.3 内置菜单项参考(MoreMenuConstants)
在隐藏内置菜单组/菜单项时,建议优先使用 SDK 提供的 MoreMenuConstants 常量进行定位。以下表格以 complete_pdf_viewer 的默认 More Menu 为参考列出常用项;实际可见项可能因授权、模块启用情况、设备形态(Phone/Tablet)或产品版本而不同。
4.3.1 菜单组(Group)
| 菜单组 | 常量 | ID |
|---|---|---|
| 主菜单组 | GROUP_ACTION_MENU_PRIMARY | 1000 |
| 次级菜单组 | GROUP_ACTION_MENU_SECONDARY | 1001 |
4.3.2 菜单项(Item)
| 菜单组 | 菜单项常量 | ID |
|---|---|---|
GROUP_ACTION_MENU_PRIMARY | ITEM_PRIMARY_PROTECT | 1 |
GROUP_ACTION_MENU_PRIMARY | ITEM_PRIMARY_COMMENT_FIELDS | 2 |
GROUP_ACTION_MENU_SECONDARY | ITEM_SECONDARY_SAVE_AS | 1 |
GROUP_ACTION_MENU_SECONDARY | ITEM_SECONDARY_REDUCE_FILE_SIZE | 2 |
GROUP_ACTION_MENU_SECONDARY | ITEM_SECONDARY_PRINT | 3 |
GROUP_ACTION_MENU_SECONDARY | ITEM_SECONDARY_FLATTEN | 4 |
GROUP_ACTION_MENU_SECONDARY | ITEM_SECONDARY_SCREEN | 5 |
4.3.3 子项(Sub-item)
部分菜单项包含子项(例如 ITEM_PRIMARY_PROTECT、ITEM_PRIMARY_COMMENT_FIELDS)。如需定位这些子项,可参考下表中的常量与 ID(取值以 MoreMenuConstants 定义为准)。
| 菜单项(Item) | 子项常量(Sub-item) | ID |
|---|---|---|
ITEM_PRIMARY_PROTECT | ITEM_PROTECT_REDACTION | 1 |
ITEM_PRIMARY_PROTECT | ITEM_PROTECT_REMOVE_PASSWORD | 2 |
ITEM_PRIMARY_PROTECT | ITEM_PROTECT_FILE_ENCRYPTION | 3 |
ITEM_PRIMARY_PROTECT | ITEM_PROTECT_TRUSTED_CERTIFICATES | 4 |
ITEM_PRIMARY_COMMENT_FIELDS | ITEM_COMMENTS_FIELDS_IMPORT_COMMENTS | 1 |
ITEM_PRIMARY_COMMENT_FIELDS | ITEM_COMMENTS_FIELDS_EXPORT_COMMENTS | 2 |
ITEM_PRIMARY_COMMENT_FIELDS | ITEM_COMMENTS_FIELDS_SUMMARIZE_COMMENTS | 3 |
ITEM_PRIMARY_COMMENT_FIELDS | ITEM_COMMENTS_FIELDS_RESET_FORM_FIELDS | 4 |
ITEM_PRIMARY_COMMENT_FIELDS | ITEM_COMMENTS_FIELDS_IMPORT_FORM_DATA | 5 |
ITEM_PRIMARY_COMMENT_FIELDS | ITEM_COMMENTS_FIELDS_EXPORT_FORM_DATA | 6 |