# 插件UI(PluginUI)
PluginUI 是插件UI功能的核心接口,提供创建UI组件、显示对话框、管理样式、获取主题颜色等功能。通过 PluginUI 可以轻松构建插件界面,所有UI组件都通过链式调用的 Builder 模式创建。
# 快速开始
// 创建一个简单的界面
PluginView view = pluginUI.buildVerticalLayout()
.addTextView().text("Hello World")
.addButton().text("确定").onClick(v -> {
pluginUI.showToast("按钮被点击了");
})
.build();
// 在对话框中显示
pluginUI.buildDialog().setView(view).show();
# 接口概览
| 方法 | 说明 |
|---|---|
getContext() | 获取插件上下文对象 |
showToast() | 显示 Toast 消息(短) |
showToastL() | 显示 Toast 消息(长) |
cancelToast() | 取消 Toast 消息 |
disableStrictIdMode() | 禁用ID严格模式 |
setStrictIdModeEnabled() | 设置是否启用ID严格模式 |
isStrictIdModeEnabled() | 获取是否启用ID严格模式 |
defaultStyle() | 设置默认样式 |
getStyle() | 获取当前样式 |
buildHorizontalLayout() | 创建水平布局构建器 |
buildVerticalLayout() | 创建垂直布局构建器 |
buildFrameLayout() | 创建帧布局构建器 |
buildDialog() | 创建对话框构建器 |
createPopupMenu() | 创建弹出菜单 |
showMessage() | 显示消息对话框 |
showErrorMessage() | 显示错误消息对话框 |
showPreference() | 跳转设置界面 |
isDarkTheme() | 判断是否为深色主题 |
colorPrimary() | 获取主要颜色 |
colorAccent() | 获取强调色 |
colorDivider() | 获取分割线颜色 |
colorError() | 获取错误颜色 |
colorWarning() | 获取警告颜色 |
colorText() | 获取主要文本颜色 |
colorTextSecondary() | 获取次要文本颜色 |
colorTextStateList() | 获取带状态的主要文本颜色 |
colorTextSecondaryStateList() | 获取带状态的次要文本颜色 |
dialogPaddingHorizontal() | 获取对话框水平内边距推荐值 |
dialogPaddingVertical() | 获取对话框垂直内边距推荐值 |
selectableItemBackground() | 获取可选择项目背景 |
selectableItemBackgroundBorderless() | 获取无边框可选择项目背景 |
dp2px() | 将dp值转换为像素值 |
sp2px() | 将sp值转换为像素值 |
# 获取插件上下文
# getContext
PluginContext getContext()
获取当前 PluginUI 绑定的插件上下文对象。
返回值: PluginContext 插件运行时上下文
# Toast 消息
所有 Toast 方法都可以在非 UI 线程调用。
# showToast
void showToast(CharSequence msg)
void showToast(CharSequence msg, Object... formatArgs)
显示短时间的 Toast 提示消息,等价于 getContext().showToast(msg)。
参数:
msg- 要显示的消息内容,支持{key}格式的本地化文本formatArgs- 格式化参数
# showToastL
void showToastL(CharSequence msg)
void showToastL(CharSequence msg, Object... formatArgs)
显示长时间的 Toast 提示消息,等价于 getContext().showToastL(msg)。
参数:
msg- 要显示的消息内容,支持{key}格式的本地化文本formatArgs- 格式化参数
# cancelToast
void cancelToast()
取消当前正在显示的 Toast 提示消息。
# ID严格模式
# isStrictIdModeEnabled
boolean isStrictIdModeEnabled()
获取当前是否启用ID严格模式(默认启用)。
在ID严格模式下,同一个根布局构建器实例下的所有 PluginView 的 id 不能重复,如果出现重复将在配置 id 时抛出异常。
返回值: 是否启用ID严格模式
# setStrictIdModeEnabled
PluginUI setStrictIdModeEnabled(boolean enabled)
设置是否启用ID严格模式。
参数:
enabled- 是否启用ID严格模式
返回值: 当前 PluginUI 实例,支持链式调用
# disableStrictIdMode
PluginUI disableStrictIdMode()
禁用ID严格模式,等价于 setStrictIdModeEnabled(false)。
返回值: 当前 PluginUI 实例,支持链式调用
# 示例
// 启用ID严格模式(默认)
pluginUI.buildVerticalLayout()
.addTextView("text").text("Text 1")
.addTextView("text").text("Text 2") // 抛出异常:id重复
.build();
// 禁用ID严格模式
pluginUI.disableStrictIdMode()
.buildVerticalLayout()
.addTextView("text").text("Text 1")
.addTextView("text").text("Text 2") // 不会抛出异常
.build();
# 默认样式
# getStyle
Style getStyle()
获取当前使用的样式。
返回值: 非空的 Style 实例
# defaultStyle
PluginUI defaultStyle(Style style)
设置默认样式,该样式将应用到所有通过此 PluginUI 创建的组件。
参数:
style- 要应用的样式,不能为 null
返回值: 当前 PluginUI 实例,支持链式调用
# 示例
// 基于当前样式进行部分修改(推荐)
pluginUI.defaultStyle(new PluginUI.StyleWrapper() {
@Override
protected void handleTextView(PluginUI pluginUI, PluginTextViewBuilder builder) {
// 先应用当前样式
super.handleTextView(pluginUI, builder);
// 然后进行部分修改
builder.textSize(14);
}
});
// 使用无参构造创建的 StyleWrapper 会自动继承当前样式
更多介绍请查看样式系统章节
# 创建布局构建器
# buildHorizontalLayout
PluginRootLayoutBuilder buildHorizontalLayout()
创建以水平线性布局为底的根布局构建器。
返回值: PluginRootLayoutBuilder 根布局构建器实例
# buildVerticalLayout
PluginRootLayoutBuilder buildVerticalLayout()
创建以垂直线性布局为底的根布局构建器。
返回值: PluginRootLayoutBuilder 根布局构建器实例
# buildFrameLayout
PluginRootLayoutBuilder buildFrameLayout()
创建以帧布局为底的根布局构建器。
返回值: PluginRootLayoutBuilder 根布局构建器实例
# 示例
// 垂直布局
PluginView verticalView = pluginUI.buildVerticalLayout()
.addTextView().text("第一行")
.addTextView().text("第二行")
.build();
// 水平布局
PluginView horizontalView = pluginUI.buildHorizontalLayout()
.addTextView().text("第一列")
.addTextView().text("第二列")
.build();
// 帧布局 - 子View会叠加显示
PluginView frameView = pluginUI.buildFrameLayout()
.addTextView().text("底层").textSize(30)
.addTextView().text("顶层").layoutGravity(Gravity.CENTER)
.build();
# 对话框和菜单
# buildDialog
PluginDialog.Builder buildDialog()
创建对话框构建器。
返回值: PluginDialog.Builder 对话框构建器实例
更多介绍请查看对话框章节
# createPopupMenu
PluginPopupMenu createPopupMenu(PluginView anchor)
创建弹出菜单。
参数:
anchor- 锚点视图,弹出菜单将相对于此视图显示
返回值: PluginPopupMenu 弹出菜单实例
# showMessage
void showMessage(CharSequence title, CharSequence message)
弹出一个自定义标题和内容的对话框,并包含一个关闭按钮。
如果 title 或 message 类型为 String 且为 {key} 格式,将尝试转化为本地化文本。
参数:
title- 对话框标题内容,可选用内置语言包词条:{tip}、{notice}、{information}、{warning}、{error}message- 对话框消息内容
# showErrorMessage
void showErrorMessage(Throwable e)
弹出一个对话框显示错误信息,同时支持查看错误详情功能,传入的异常还会被记录到插件日志中。
参数:
e- 捕获到的异常
# showPreference
void showPreference(Class<? extends PluginPreference> clazz)
跳转并显示设置界面。
参数:
clazz- 设置界面类,需实现 PluginPreference 接口,为 null 则表示主设置界面类
# 示例
// 显示消息对话框
pluginUI.showMessage("{tip}", "这是提示内容");
// 显示错误消息
try {
// 可能出错的代码
} catch (Exception e) {
pluginUI.showErrorMessage(e);
}
// 打开主设置界面
pluginUI.showPreference(null);
// 打开指定设置界面
pluginUI.showPreference(AdvancedSettings.class);
# 主题和颜色
# isDarkTheme
boolean isDarkTheme()
判断当前是否为深色主题(夜间模式)。
返回值: true 表示深色主题,false 表示浅色主题
# colorPrimary
int colorPrimary()
获取主要颜色(Primary Color)。
返回值: 主要颜色值(ARGB格式)
# colorAccent
int colorAccent()
获取强调色(Accent Color)。
返回值: 强调色值(ARGB格式)
# colorDivider
int colorDivider()
获取分割线颜色。
返回值: 分割线颜色值(ARGB格式)
# colorError
int colorError()
获取错误颜色。
返回值: 错误颜色值(ARGB格式)
# colorWarning
int colorWarning()
获取警告颜色。
返回值: 警告颜色值(ARGB格式)
# colorText
int colorText()
获取主要文本颜色。
返回值: 主要文本颜色值(ARGB格式)
# colorTextSecondary
int colorTextSecondary()
获取次要文本颜色。相比主要文本颜色,次要文本颜色较浅。
返回值: 次要文本颜色值(ARGB格式)
# colorTextStateList
ColorStateList colorTextStateList()
获取带状态的主要文本颜色。
返回值: 带状态的主要文本颜色
# colorTextSecondaryStateList
ColorStateList colorTextSecondaryStateList()
获取带状态的次要文本颜色。相比主要文本颜色,次要文本颜色较浅。
返回值: 带状态的次要文本颜色
# 示例
// 使用主题颜色
pluginUI.buildVerticalLayout()
.addTextView().text("主要颜色").backgroundColor(pluginUI.colorPrimary())
.addTextView().text("强调色").backgroundColor(pluginUI.colorAccent())
.addTextView().text("错误颜色").textColor(pluginUI.colorError())
.addTextView().text("警告颜色").textColor(pluginUI.colorWarning())
.addView().height(1).widthMatchParent().backgroundColor(pluginUI.colorDivider())
.build();
// 使用带状态的文本颜色(禁用时会自动变灰)
pluginUI.buildVerticalLayout()
.addButton().text("启用状态").textColor(pluginUI.colorTextStateList())
.addButton().text("禁用状态").textColor(pluginUI.colorTextStateList()).enable(false)
.build();
# 布局相关
# dialogPaddingHorizontal
int dialogPaddingHorizontal()
获取对话框左右内边距推荐值,单位为 px。
返回值: 对话框水平内边距像素值
# dialogPaddingVertical
int dialogPaddingVertical()
获取对话框上下内边距推荐值,单位为 px。如果设置了对话框按钮,则不推荐设置底部内边距。
返回值: 对话框垂直内边距像素值
# selectableItemBackground
Drawable selectableItemBackground()
用于可选择项目背景,例如 PluginTextView 设置点击事件后,按下没有视觉效果,可调用此方法设置其背景。
返回值: 可选择项目背景 Drawable
# selectableItemBackgroundBorderless
Drawable selectableItemBackgroundBorderless()
获取无边框可选择项目背景 Drawable。
返回值: 无边框可选择项目背景 Drawable
# 示例
// 使用推荐的对话框内边距
PluginView view = pluginUI.buildVerticalLayout()
.paddingHorizontal(pluginUI.dialogPaddingHorizontal())
.paddingVertical(pluginUI.dialogPaddingVertical())
.addTextView().text("对话框内容")
.build();
// 设置可选择背景
pluginUI.buildVerticalLayout()
.addTextView().text("点我试试")
.background(pluginUI.selectableItemBackground())
.onClick(view -> {
pluginUI.showToast("被点击了");
})
.build();
# 单位转换
# dp2px
int dp2px(float dp)
将 dp 值转换为像素值。
参数:
dp- 要转换的 dp 值
返回值: 对应的像素值
# sp2px
int sp2px(float sp)
将 sp 值转换为像素值。
参数:
sp- 要转换的 sp 值
返回值: 对应的像素值
# 示例
// 使用dp单位设置尺寸
int width = pluginUI.dp2px(100); // 100dp转为px
int height = pluginUI.dp2px(50); // 50dp转为px
pluginUI.buildVerticalLayout()
.addView().size(width, height).backgroundColor(Color.RED)
.build();
# 样式系统
PluginUI 提供了强大的样式系统,可以通过 defaultStyle() 方法设置默认样式,该样式将应用到所有通过此 PluginUI 创建的组件。
# Style 类
Style 类用于定义组件的默认样式。通过继承此类并重写相应方法,可以自定义各种 UI 组件的默认样式。
# 样式处理方法
public class Style {
// 处理所有视图的基础样式
protected boolean handleBaseView(PluginUI pluginUI, PluginBaseViewBuilder<?> builder);
// 处理文本视图的基础样式
protected boolean handleBaseTextView(PluginUI pluginUI, PluginBaseTextViewBuilder<?> builder);
// 处理按钮的基础样式
protected boolean handleBaseButton(PluginUI pluginUI, PluginBaseButtonBuilder<?> builder);
// 处理复合按钮的基础样式
protected boolean handleBaseCompoundButton(PluginUI pluginUI, PluginBaseCompoundButtonBuilder<?> builder);
// 处理视图组的基础样式
protected boolean handleBaseViewGroup(PluginUI pluginUI, PluginBaseViewGroupBuilder<?> builder);
// 处理具体组件的样式
protected void handleView(PluginUI pluginUI, PluginViewBuilder builder);
protected void handleTextView(PluginUI pluginUI, PluginTextViewBuilder builder);
protected void handleButton(PluginUI pluginUI, PluginButtonBuilder builder);
protected void handleCheckBox(PluginUI pluginUI, PluginCheckBoxBuilder builder);
protected void handleSwitchButton(PluginUI pluginUI, PluginSwitchButtonBuilder builder);
protected void handleRadioButton(PluginUI pluginUI, PluginRadioButtonBuilder builder);
protected void handleRadioGroup(PluginUI pluginUI, PluginRadioGroupBuilder builder);
protected void handleSpinner(PluginUI pluginUI, PluginSpinnerBuilder builder);
protected void handleProgressBar(PluginUI pluginUI, PluginProgressBarBuilder builder);
protected void handleEditText(PluginUI pluginUI, PluginEditTextBuilder builder);
protected void handleImageView(PluginUI pluginUI, PluginImageViewBuilder builder);
protected void handleLinearLayout(PluginUI pluginUI, PluginLinearLayoutBuilder builder);
protected void handleRootLayout(PluginUI pluginUI, PluginRootLayoutBuilder builder);
}
# 调用时机
样式处理方法会在 builder 创建之后立刻调用。例如 addTextView() 的内部实现大致如下:
PluginTextViewBuilder addTextView() {
PluginTextViewBuilder builder = generateTextViewBuilder();
getStyle().dispatch(pluginUI, builder); // 创建后立刻分发样式
return builder;
}
这意味着:
- 样式处理方法在
addTextView()返回之前就已经执行 - 用户在
addTextView()后面链式调用的设置会覆盖样式中的设置
// 假设样式中设置了 textSize(14)
pluginUI.buildVerticalLayout()
.addTextView().text("Hello").textSize(20) // textSize(20) 会覆盖样式中的 14
.build();
handleBaseXxx 方法的返回值决定是否继续分发:
- 返回
false:继续向下分发到子类型(默认行为) - 返回
true:停止分发,不再调用后续的处理方法
组件继承关系图:
PluginBaseViewBuilder
├── PluginViewBuilder (handleView)
├── PluginEditTextBuilder (handleEditText)
├── PluginImageViewBuilder (handleImageView)
├── PluginSpinnerBuilder (handleSpinner)
├── PluginProgressBarBuilder (handleProgressBar)
├── PluginBaseTextViewBuilder
│ ├── PluginTextViewBuilder (handleTextView)
│ └── PluginBaseButtonBuilder
│ ├── PluginButtonBuilder (handleButton)
│ └── PluginBaseCompoundButtonBuilder
│ ├── PluginCheckBoxBuilder (handleCheckBox)
│ ├── PluginSwitchButtonBuilder (handleSwitchButton)
│ └── PluginRadioButtonBuilder (handleRadioButton)
└── PluginBaseViewGroupBuilder
└── PluginBaseLinearLayoutBuilder
├── PluginLinearLayoutBuilder (handleLinearLayout)
└── PluginRadioGroupBuilder (handleRadioGroup)
提示:如果需要为所有文本类组件(TextView、Button、CheckBox 等)设置统一样式,可以重写
handleBaseTextView()方法。
# StyleWrapper 类
StyleWrapper 类是基于装饰器模式的样式扩展工具,用于包装现有 Style 实例,可在不修改原有样式的基础上添加或覆盖样式处理逻辑。
提供两种构造方式:
StyleWrapper()- 自动继承当前样式(推荐)StyleWrapper(Style baseStyle)- 显式指定基础样式
# DEFAULT_STYLE
PluginUI 提供了默认样式 DEFAULT_STYLE,包含以下设置:
- 根布局:设置水平内边距为
dialogPaddingHorizontal() - 文本视图:设置文本颜色为
colorTextStateList(),文本大小为 16sp - 编辑框:设置宽度为
MATCH_PARENT,box 风格的编辑框默认多行模式 - 线性布局:水平布局默认宽度为
MATCH_PARENT - 单选按钮组:水平布局默认宽度为
MATCH_PARENT
# 示例
// 基于当前样式进行部分修改(推荐)
pluginUI.defaultStyle(new PluginUI.StyleWrapper() {
@Override
protected void handleTextView(PluginUI pluginUI, PluginTextViewBuilder builder) {
// 先应用当前样式
super.handleTextView(pluginUI, builder);
// 然后进行部分修改
builder.textSize(14);
}
});
// 上面的代码等价于
PluginUI.Style baseStyle = pluginUI.getStyle();
pluginUI.defaultStyle(new PluginUI.StyleWrapper(baseStyle) {
@Override
protected void handleTextView(PluginUI pluginUI, PluginTextViewBuilder builder) {
super.handleTextView(pluginUI, builder);
builder.textSize(14);
}
});
// 设置所有文本视图的默认颜色和大小
pluginUI.defaultStyle(new PluginUI.StyleWrapper() {
@Override
protected void handleTextView(PluginUI pluginUI, PluginTextViewBuilder builder) {
super.handleTextView(pluginUI, builder);
builder.textColor(0xFF000000).backgroundColor(0xFFAAAAAA);
}
});
// 创建视图时会自动应用样式
PluginView view = pluginUI.buildVerticalLayout()
.addTextView().text("这个文本会使用上面设置的样式")
.build();
# 完整示例
# 创建简单界面
// 创建一个垂直布局
PluginView view = pluginUI.buildVerticalLayout()
.addTextView().text("这是一个文本")
.addButton().text("点击我").onClick(v -> {
pluginUI.showToast("按钮被点击了");
})
.build();
// 在对话框中显示
pluginUI.buildDialog()
.setTitle("标题")
.setView(view)
.show();
# 组合布局
// 垂直布局嵌套水平布局
PluginView view = pluginUI.buildVerticalLayout()
.addHorizontalLayout().children(subBuilder -> subBuilder
.addTextView().text("第一列").width(0).layoutWeight(1)
.addTextView().text("第二列").width(0).layoutWeight(1)
)
.addHorizontalLayout().children(subBuilder -> subBuilder
.addTextView().text("第三列").width(0).layoutWeight(1)
.addTextView().text("第四列").width(0).layoutWeight(1)
)
.showDialog();
# 使用自定义样式
// 设置自定义样式
pluginUI.defaultStyle(new PluginUI.StyleWrapper() {
@Override
protected void handleTextView(PluginUI pluginUI, PluginTextViewBuilder builder) {
super.handleTextView(pluginUI, builder);
builder.textColor(0xFF000000).backgroundColor(0xFFAAAAAA);
}
});
// 创建界面
PluginView view = pluginUI.buildVerticalLayout()
.addTextView().text("第一行")
.addTextView().text("第二行")
.addTextView().text("第三行")
.build();
# 使用主题颜色
// 创建带颜色的界面
PluginView view = pluginUI.buildVerticalLayout()
.addTextView().text("主要颜色").backgroundColor(pluginUI.colorPrimary())
.addTextView().text("强调色").backgroundColor(pluginUI.colorAccent())
.addView().height(1).widthMatchParent().backgroundColor(pluginUI.colorDivider())
.addTextView().text("错误颜色").textColor(pluginUI.colorError())
.addTextView().text("警告颜色").textColor(pluginUI.colorWarning())
.showDialog();
# 相关接口
- PluginView - 插件视图
- PluginDialog - 插件对话框
- PluginPreference - 插件设置界面