# 插件设置界面(PluginPreference)
PluginPreference 用于构建插件的配置界面,提供了丰富的设置选项类型,包括文本显示、输入框、开关、单选列表等。设置数据会自动保存到 SharedPreferences,无需手动处理存储逻辑。
# 快速开始
public class MyPreference implements PluginPreference {
@Override
public void onBuild(PluginContext context, Builder builder) {
// 设置标题
builder.title("插件设置");
// 添加分组标题
builder.addHeader("基础设置");
// 添加开关选项
builder.addSwitch("启用功能", "enable_feature")
.defaultValue(true)
.summaryOn("已启用")
.summaryOff("已禁用");
// 添加输入选项
builder.addInput("API 地址", "api_url")
.defaultValue("https://api.example.com")
.valueAsSummary();
}
}
在 build.gradle 中配置:
mtPlugin {
// 主设置界面(可选)
mainPreference = "com.example.myplugin.MyPreference"
}
提示:关于完整的项目配置说明,请查看 开发环境搭建。
# 接口概览
# PluginPreference 接口
| 方法 | 说明 |
|---|---|
onBuild() | 构建设置界面的回调方法 |
# Builder 接口
| 方法 | 说明 |
|---|---|
title() | 设置界面标题 |
subtitle() | 设置界面副标题 |
addHeader() | 添加分组标题头 |
addText() | 添加纯文本显示项 |
addInput() | 添加文本输入选项 |
addSwitch() | 添加开关选项 |
addList() | 添加单选列表选项 |
onPreferenceChange() | 注册设置项值变化监听器 |
onCreated() | 注册界面创建完成监听器 |
# Header 接口
| 方法 | 说明 |
|---|---|
visible() | 设置可见性 |
enable() | 设置启用状态 |
# Text 接口
| 方法 | 说明 |
|---|---|
summary() | 设置摘要文本 |
url() | 设置点击后跳转的URL |
onClick() | 设置自定义点击事件 |
interceptClick() | 设置点击拦截器 |
visible() | 设置可见性 |
enable() | 设置启用状态 |
# Input 接口
| 方法 | 说明 |
|---|---|
defaultValue() | 设置默认值 |
summary() | 设置摘要文本 |
hint() | 设置输入框提示文本 |
valueAsSummary() | 使用当前值作为摘要 |
inputType() | 设置输入类型 |
validator() | 设置输入校验器 |
interceptClick() | 设置点击拦截器 |
visible() | 设置可见性 |
enable() | 设置启用状态 |
# Switch 接口
| 方法 | 说明 |
|---|---|
defaultValue() | 设置默认状态 |
summary() | 设置摘要文本 |
summaryOn() | 设置开启时的摘要 |
summaryOff() | 设置关闭时的摘要 |
interceptClick() | 设置点击拦截器 |
visible() | 设置可见性 |
enable() | 设置启用状态 |
# List 接口
| 方法 | 说明 |
|---|---|
defaultValue() | 设置默认选中值 |
summary() | 设置摘要文本 |
addItem() | 添加子选项 |
interceptClick() | 设置点击拦截器 |
visible() | 设置可见性 |
enable() | 设置启用状态 |
# PreferenceScreen 接口
| 方法 | 说明 |
|---|---|
recreate() | 重新创建设置界面 |
getTitle() / setTitle() | 获取/设置标题 |
getSubtitle() / setSubtitle() | 获取/设置副标题 |
findHeader() / requireHeader() | 查找分组标题头 |
findPreference() / requirePreference() | 查找设置选项 |
# PreferenceHeader 接口
| 方法 | 说明 |
|---|---|
getPreferenceScreen() | 获取所属的设置界面实例 |
getKey() | 获取键名 |
getTitle() / setTitle() | 获取/设置标题 |
isEnabled() / setEnabled() | 获取/设置启用状态 |
isVisible() / setVisible() | 获取/设置可见性 |
# PreferenceItem 接口
| 方法 | 说明 |
|---|---|
getPreferenceScreen() | 获取所属的设置界面实例 |
getKey() | 获取键名 |
getTitle() / setTitle() | 获取/设置标题 |
getSummary() / setSummary() | 获取/设置摘要 |
isEnabled() / setEnabled() | 获取/设置启用状态 |
isVisible() / setVisible() | 获取/设置可见性 |
# 创建设置界面
# onBuild
void onBuild(PluginContext context, Builder builder)
构建设置界面时的回调方法,在此方法中通过 Builder 添加各种设置选项。
参数:
context- 插件上下文,提供插件运行环境builder- 界面构建器,用于添加设置选项
示例:
public class MyPreference implements PluginPreference {
@Override
public void onBuild(PluginContext context, Builder builder) {
builder.title("设置");
builder.addSwitch("启用", "enable").defaultValue(true);
}
}
# 界面配置
# title 和 subtitle
Builder title(CharSequence title)
Builder subtitle(CharSequence subtitle)
设置界面顶栏的标题和副标题。
参数:
title- 标题文本,默认为"设置",支持{key}格式的本地化文本subtitle- 副标题文本,默认为空,支持{key}格式的本地化文本
示例:
builder.title("插件设置")
.subtitle("配置插件的各项参数");
// 使用本地化文本
builder.title("{settings}")
.subtitle("{settings_description}");
# addHeader
Header addHeader(CharSequence title)
Header addHeader(CharSequence title, String key)
添加一个分组标题头,用于将相关的设置选项进行分组显示。
参数:
title- 分组标题文本,支持{key}格式的本地化文本key- 可选,分组标题头的键名,用于后续通过PreferenceScreen.findHeader()/requireHeader()查找
返回值: Header 实例,可进行进一步配置
示例:
builder.addHeader("基础设置");
builder.addSwitch("选项1", "key1");
builder.addSwitch("选项2", "key2");
builder.addHeader("高级设置");
builder.addInput("选项3", "key3");
// 带 key 的分组标题头,便于后续动态访问
builder.addHeader("可控设置", "controllable_header")
.visible(true)
.enable(true);
# onPreferenceChange
Builder onPreferenceChange(OnPreferenceChangeListener listener)
注册设置项值变化时的回调监听器。当用户修改 Input、Switch、List 设置项的值时,会触发此监听器的回调。
参数:
listener- 设置项值变化的监听器
监听器接口:
interface OnPreferenceChangeListener {
void onChange(PluginUI pluginUI, PreferenceItem preferenceItem, Object newValue);
}
pluginUI- 插件UI实例preferenceItem- 内容发生变更的设置选项实例newValue- 设置选项的新值,对于 Input 和 List 类型为 String,对于 Switch 类型为 Boolean
示例:
builder.onPreferenceChange((pluginUI, preferenceItem, newValue) -> {
String key = preferenceItem.getKey();
if ("theme".equals(key)) {
// 主题变更时的处理逻辑
pluginUI.toast("主题已切换为:" + newValue);
}
});
# onCreated
Builder onCreated(OnPreferenceScreenCreatedListener listener)
注册设置界面创建完成时的回调监听器。当设置界面构建完成后,可以通过此监听器获取 PreferenceScreen 实例,用于动态修改界面元素或执行其他初始化操作。
参数:
listener- 界面创建完成的监听器
监听器接口:
interface OnPreferenceScreenCreatedListener {
void onPreferenceScreenCreated(PluginUI pluginUI, PreferenceScreen preferenceScreen);
}
pluginUI- 插件UI实例preferenceScreen- 已创建完成的设置界面实例
示例:
builder.onCreated((pluginUI, screen) -> {
// 界面创建完成后,动态修改标题
screen.setTitle("动态标题");
// 根据条件显示或隐藏某个设置项
PreferenceItem advancedItem = screen.findPreference("advanced_option");
if (advancedItem != null) {
advancedItem.setVisible(isAdvancedUser());
}
});
# 分组标题头(Header)
# visible
Header visible(boolean visible)
设置分组标题的可见性。
参数:
visible- true 为可见,false 为隐藏
# enable
Header enable(boolean enable)
设置分组标题的启用状态。
参数:
enable- true 为启用,false 为禁用(显示为灰色)
示例:
// 根据条件控制分组标题头的显示
boolean showAdvanced = preferences.getBoolean("show_advanced", false);
builder.addHeader("高级设置", "advanced_header")
.visible(showAdvanced);
# 设置选项
所有设置选项的 key 参数用于 SharedPreferences 的键名,通过 context.getPreferences() 可以获取和修改这些值。
# 通用方法
以下方法在 Text、Input、Switch、List 接口中都可用:
# visible
visible(boolean visible)
设置选项的可见性。
参数:
visible- true 为可见,false 为隐藏
# enable
enable(boolean enable)
设置选项的启用状态。
参数:
enable- true 为启用,false 为禁用(显示为灰色且不可点击)
# interceptClick
interceptClick(OnClickInterceptListener listener)
设置点击拦截器。当用户点击该选项时,会触发拦截器的回调方法,可通过返回值控制是否继续执行默认行为。
参数:
listener- 点击拦截器
拦截器接口:
interface OnClickInterceptListener {
boolean onClick(PluginUI pluginUI, PreferenceItem preferenceItem);
}
- 返回
true表示已拦截点击事件,不再执行默认行为 - 返回
false表示继续执行默认行为
示例:
// 在执行默认行为前进行确认
builder.addSwitch("危险选项", "dangerous_option")
.interceptClick((pluginUI, preferenceItem) -> {
pluginUI.buildDialog()
.setTitle("警告")
.setMessage("确定要修改此选项吗?")
.setPositiveButton("{ok}", (dialog, which) -> {
// 用户确认后,手动切换开关状态
SharedPreferences prefs = context.getPreferences();
boolean current = prefs.getBoolean("dangerous_option", false);
prefs.edit().putBoolean("dangerous_option", !current).apply();
// 刷新界面
preferenceItem.getPreferenceScreen().recreate();
})
.setNegativeButton("{cancel}", null)
.show();
return true; // 拦截默认行为
});
# 文本选项(Text)
# addText
Text addText(CharSequence title)
Text addText(CharSequence title, String key)
添加一个纯文本显示项,可用于显示说明信息或链接。
参数:
title- 显示的标题文本,支持{key}格式的本地化文本key- 可选,文本选项的键名,用于后续通过PreferenceScreen.findPreference()/requirePreference()查找
返回值: Text 实例,可进行进一步配置
# summary
Text summary(CharSequence summary)
设置摘要文本,显示在标题下方的详细说明信息。
参数:
summary- 摘要文本内容,支持{key}格式的本地化文本
示例:
builder.addText("关于")
.summary("插件版本 1.0.0");
# url
Text url(String url)
设置点击后跳转的URL地址。
参数:
url- 要跳转的URL地址,应为有效的HTTP/HTTPS链接
注意: 如果同时设置了 onClick() 监听器,自定义点击事件的优先级更高,URL跳转将不会执行。
示例:
builder.addText("官方网站")
.summary("访问插件官方网站")
.url("https://example.com");
# onClick
Text onClick(OnTextItemClickListener listener)
设置自定义点击事件监听器。
与 interceptClick() 的主要区别:
onClick()的监听器不需要返回值,简化代码编写,且设置后会拦截默认行为(URL 跳转)interceptClick()需要返回 boolean 值来控制是否继续执行默认行为
如果只需要处理点击事件而不关心默认行为,推荐使用 onClick()。
参数:
listener- 点击事件监听器
监听器接口:
interface OnTextItemClickListener {
void onClick(PluginUI pluginUI, PreferenceItem preferenceItem);
}
pluginUI- PluginUI 实例,可用于显示对话框等item- 被点击的文本项实例,可通过setTitle()、setSummary()动态修改
示例:
// 计数器示例
AtomicInteger count = new AtomicInteger();
builder.addText("点击计数")
.summary("点击了 0 次")
.onClick((pluginUI, item) -> {
item.setSummary("点击了 " + count.incrementAndGet() + " 次");
});
# 输入选项(Input)
# addInput
Input addInput(CharSequence title, String key)
添加一个文本输入选项,用户可以输入文本内容,值以 String 类型存储到 SharedPreferences。
参数:
title- 选项标题,支持{key}格式的本地化文本key- 存储选项值的键名
返回值: Input 实例,可进行进一步配置
# defaultValue
Input defaultValue(CharSequence defaultValue)
设置输入框的默认值。
参数:
defaultValue- 默认文本内容,支持{key}格式的本地化文本
# summary
Input summary(CharSequence summary)
设置摘要文本,显示在标题下方的说明信息。
参数:
summary- 摘要文本内容,支持{key}格式的本地化文本
# hint
Input hint(CharSequence hint)
设置输入框的提示文本,当输入框为空时显示的灰色提示信息。
参数:
hint- 提示文本内容,支持{key}格式的本地化文本
示例:
builder.addInput("API 密钥", "api_key")
.hint("请输入您的 API 密钥")
.valueAsSummary();
# valueAsSummary
Input valueAsSummary()
使用当前输入值作为摘要显示。此选项会覆盖通过 summary() 方法设置的摘要。
# inputType
Input inputType(int inputType)
设置文本输入类型,用于控制软键盘类型和输入限制。
参数:
inputType- 输入类型,参考android.text.InputType常量
示例:
import android.text.InputType;
// 数字输入
builder.addInput("端口", "port")
.inputType(InputType.TYPE_CLASS_NUMBER)
.defaultValue("8080");
// 密码输入
builder.addInput("密码", "password")
.inputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
# validator
Input validator(Validator validator)
设置输入内容校验器,用于检测用户输入内容的格式是否正确。
参数:
validator- 校验器实例
校验器接口:
interface Validator {
String validate(String value);
}
- 校验通过返回 null
- 校验失败返回错误信息(支持
{key}格式的本地化文本)
示例:
builder.addInput("端口号", "port")
.validator(value -> {
if (value.isEmpty()) {
return "端口号不能为空";
}
try {
int port = Integer.parseInt(value);
if (port < 1 || port > 65535) {
return "端口号范围:1-65535";
}
return null; // 校验通过
} catch (NumberFormatException e) {
return "请输入有效的数字";
}
});
完整示例:
builder.addInput("服务器地址", "server_url")
.defaultValue("https://api.example.com")
.valueAsSummary();
builder.addInput("端口", "port")
.inputType(InputType.TYPE_CLASS_NUMBER)
.defaultValue("8080")
.validator(value -> {
try {
int port = Integer.parseInt(value);
return (port >= 1 && port <= 65535) ? null : "端口号范围:1-65535";
} catch (NumberFormatException e) {
return "请输入有效的数字";
}
});
# 开关选项(Switch)
# addSwitch
Switch addSwitch(CharSequence title, String key)
添加一个开关选项,用户可以开启或关闭,值以 boolean 类型存储到 SharedPreferences。
参数:
title- 选项标题,支持{key}格式的本地化文本key- 存储选项值的键名
返回值: Switch 实例,可进行进一步配置
# defaultValue
Switch defaultValue(boolean defaultValue)
设置开关的默认状态。
参数:
defaultValue- true 为开启,false 为关闭
# summary
Switch summary(CharSequence summary)
设置摘要文本,显示在标题下方的说明信息。
参数:
summary- 摘要文本内容,支持{key}格式的本地化文本
# summaryOn 和 summaryOff
Switch summaryOn(CharSequence summary)
Switch summaryOff(CharSequence summary)
设置开关为"开启"或"关闭"状态时显示的摘要。这两个方法会覆盖通过 summary() 方法设置的摘要。
参数:
summary- 对应状态下的摘要文本,支持{key}格式的本地化文本
示例:
// 固定摘要
builder.addSwitch("启用调试模式", "debug_mode")
.defaultValue(false)
.summary("开启后会输出详细日志");
// 动态摘要
builder.addSwitch("自动更新", "auto_update")
.defaultValue(true)
.summaryOn("已启用自动更新")
.summaryOff("已禁用自动更新");
# 列表选项(List)
# addList
List addList(CharSequence title, String key)
添加一个单选列表选项,用户可以从预定义的选项中选择一个,值以 String 类型存储到 SharedPreferences。
参数:
title- 选项标题,支持{key}格式的本地化文本key- 存储选项值的键名
返回值: List 实例,可进行进一步配置
# defaultValue
List defaultValue(String defaultValue)
设置列表的默认选中值。
参数:
defaultValue- 默认选中项的值
# summary
List summary(CharSequence summary)
设置摘要文本,显示在标题下方的说明信息。
参数:
summary- 摘要文本内容,支持{key}格式的本地化文本
# addItem
Item addItem(CharSequence name, String value)
添加一个子选项到列表中。
参数:
name- 子选项显示名称,支持{key}格式的本地化文本value- 子选项对应的值
返回值: Item 实例,可进行进一步配置或添加更多选项
# Item.summary
Item summary(CharSequence summary)
设置该子选项被选中时显示的摘要。此选项会覆盖父列表通过 summary() 方法设置的摘要。
参数:
summary- 选中时的摘要文本,支持{key}格式的本地化文本
示例:
// 基础用法
builder.addList("语言", "language")
.defaultValue("zh-CN")
.addItem("简体中文", "zh-CN")
.addItem("English", "en")
.addItem("日本語", "ja");
// 带动态摘要
builder.addList("主题", "theme")
.summary("未选择主题")
.addItem("浅色", "light").summary("当前主题:浅色")
.addItem("深色", "dark").summary("当前主题:深色")
.addItem("跟随系统", "auto").summary("当前主题:跟随系统");
# 动态界面控制
# PreferenceScreen
设置界面实例,用于在设置界面创建完成后动态访问和修改界面元素。
# recreate
void recreate()
重新创建设置界面。调用此方法会重新执行 onBuild() 方法,重新构建整个设置界面。
# getTitle / setTitle
CharSequence getTitle()
void setTitle(CharSequence title)
获取/设置设置界面的标题。支持 {key} 格式的本地化文本。
# getSubtitle / setSubtitle
CharSequence getSubtitle()
void setSubtitle(CharSequence subtitle)
获取/设置设置界面的副标题。支持 {key} 格式的本地化文本。
# findHeader / requireHeader
PreferenceHeader findHeader(String key)
PreferenceHeader requireHeader(String key)
根据 key 查找分组标题头。
参数:
key- 分组标题头的键名
返回值:
findHeader()- 找到的 PreferenceHeader 实例,未找到返回 nullrequireHeader()- 找到的 PreferenceHeader 实例,未找到时抛出 IllegalArgumentException
# findPreference / requirePreference
PreferenceItem findPreference(String key)
PreferenceItem requirePreference(String key)
根据 key 查找设置选项。
参数:
key- 设置选项的键名
返回值:
findPreference()- 找到的 PreferenceItem 实例,未找到返回 nullrequirePreference()- 找到的 PreferenceItem 实例,未找到时抛出 IllegalArgumentException
# PreferenceHeader
分组标题头实例,用于在设置界面创建完成后动态访问和修改分组标题头。
| 方法 | 说明 |
|---|---|
getPreferenceScreen() | 获取所属的设置界面实例 |
getKey() | 获取分组标题头的键名 |
getTitle() / setTitle() | 获取/设置标题文本 |
isEnabled() / setEnabled() | 获取/设置启用状态 |
isVisible() / setVisible() | 获取/设置可见性 |
# PreferenceItem
设置选项实例,用于在设置界面创建完成后动态访问和修改设置选项。
| 方法 | 说明 |
|---|---|
getPreferenceScreen() | 获取所属的设置界面实例 |
getKey() | 获取设置选项的键名 |
getTitle() / setTitle() | 获取/设置标题文本 |
getSummary() / setSummary() | 获取/设置摘要文本 |
isEnabled() / setEnabled() | 获取/设置启用状态 |
isVisible() / setVisible() | 获取/设置可见性 |
示例:
builder.addText("版本信息", "version_info")
.summary("加载中...");
builder.onCreated((pluginUI, screen) -> {
// 界面创建完成后,异步获取版本信息并更新
PreferenceItem versionItem = screen.requirePreference("version_info");
fetchVersionAsync(version -> {
versionItem.setSummary("当前版本:" + version);
});
});
# 数据存储
设置选项的值会自动保存到 SharedPreferences,可以通过 PluginContext.getPreferences() 获取和修改。
// 在 onBuild 中添加设置选项
builder.addSwitch("启用功能", "enable_feature").defaultValue(true);
builder.addInput("API地址", "api_url").defaultValue("https://api.example.com");
// 在插件其他地方读取设置值
SharedPreferences preferences = context.getPreferences();
boolean enabled = preferences.getBoolean("enable_feature", true);
String apiUrl = preferences.getString("api_url", "https://api.example.com");
// 修改设置值
preferences.edit()
.putBoolean("enable_feature", false)
.putString("api_url", "https://newapi.example.com")
.apply();
# 配置主设置界面
要配置主设置界面,需要在实现 PluginPreference 接口后,在模块的 build.gradle 中配置 mainPreference 字段。
# 在 build.gradle 中配置
mtPlugin {
pluginID = "com.example.myplugin"
versionCode = 1
versionName = "v1.0"
name = "示例插件"
// 主设置界面
mainPreference = "com.example.myplugin.MyPreference"
interfaces = [
"com.example.myplugin.MyTranslationEngine",
// 其他接口...
]
}
配置说明:
mainPreference- 主设置界面类的完整路径(包名 + 类名)- 配置主设置界面是可选的,如果插件不需要主设置界面可以不配置
- 用户在插件管理界面查看插件信息时,可点击设置按钮打开主设置界面
- 插件可以有多个设置界面,但只有配置为
mainPreference的才是主设置界面
提示:完整的
mtPlugin {}配置说明请查看 开发环境搭建。
# 打开设置界面
可以通过 pluginUI.showPreference() 方法在代码中打开任意设置界面。
void showPreference(Class<? extends PluginPreference> clazz)
参数:
clazz- 设置界面类,需实现 PluginPreference 接口,传入 null 则打开主设置界面
示例:
// 打开主设置界面
pluginUI.showPreference(null);
// 打开指定的设置界面
pluginUI.showPreference(AdvancedSettings.class);
// 在按钮点击事件中打开设置
builder.addText("高级设置")
.summary("配置高级选项")
.onClick((pluginUI, item) -> {
pluginUI.showPreference(AdvancedSettings.class);
});
应用场景:
- 在主设置界面中提供入口跳转到子设置界面
- 在文本选项的点击事件中打开相关设置
- 从其他插件功能中打开设置界面
# 完整示例
# 基础设置界面
public class MyPreference implements PluginPreference {
@Override
public void onBuild(PluginContext context, Builder builder) {
builder.title("插件设置");
builder.addHeader("基础设置");
builder.addSwitch("启用插件", "plugin_enabled")
.defaultValue(true)
.summaryOn("插件已启用")
.summaryOff("插件已禁用");
builder.addInput("用户名", "username")
.defaultValue("")
.valueAsSummary();
builder.addList("语言", "language")
.defaultValue("zh-CN")
.addItem("简体中文", "zh-CN").summary("使用简体中文")
.addItem("English", "en").summary("Use English");
builder.addHeader("关于");
builder.addText("版本")
.summary("1.0.0");
builder.addText("官方网站")
.summary("访问插件官方网站")
.url("https://example.com");
}
}
# 动态界面控制
public class DynamicPreference implements PluginPreference {
@Override
public void onBuild(PluginContext context, Builder builder) {
builder.title("动态设置");
SharedPreferences preferences = context.getPreferences();
boolean showAdvanced = preferences.getBoolean("show_advanced", false);
builder.addSwitch("显示高级选项", "show_advanced")
.defaultValue(false);
// 根据条件控制高级选项的显示
builder.addHeader("高级选项", "advanced_header")
.visible(showAdvanced);
builder.addInput("高级参数", "advanced_param")
.visible(showAdvanced);
// 监听设置变化
builder.onPreferenceChange((pluginUI, item, newValue) -> {
if ("show_advanced".equals(item.getKey())) {
// 当"显示高级选项"改变时,重建界面
item.getPreferenceScreen().recreate();
}
});
}
}
# 自定义对话框
public class AdvancedPreference implements PluginPreference {
@Override
public void onBuild(PluginContext context, Builder builder) {
builder.title("高级设置");
SharedPreferences preferences = context.getPreferences();
// 自定义输入对话框
builder.addText("自定义输入")
.summary(getSummary(preferences))
.onClick((pluginUI, item) -> {
// 创建输入框
PluginView view = pluginUI.buildVerticalLayout()
.addEditText("input")
.text(preferences.getString("custom_value", ""))
.selectAll()
.build();
PluginEditText input = view.requireViewById("input");
input.requestFocusAndShowIME();
// 显示对话框
pluginUI.buildDialog()
.setTitle("请输入内容")
.setView(view)
.setPositiveButton("{ok}", (dialog, which) -> {
String text = input.getText().toString();
preferences.edit().putString("custom_value", text).apply();
item.setSummary(getSummary(preferences));
})
.setNegativeButton("{cancel}", null)
.show();
});
}
private String getSummary(SharedPreferences preferences) {
String value = preferences.getString("custom_value", null);
return value == null || value.isEmpty() ? "点击输入" : "当前值:" + value;
}
}
# 输入校验
public class ValidationPreference implements PluginPreference {
@Override
public void onBuild(PluginContext context, Builder builder) {
builder.title("输入校验示例");
// 端口号校验
builder.addInput("服务器端口", "server_port")
.inputType(InputType.TYPE_CLASS_NUMBER)
.defaultValue("8080")
.validator(value -> {
if (value.isEmpty()) {
return "端口号不能为空";
}
try {
int port = Integer.parseInt(value);
if (port < 1 || port > 65535) {
return "端口号范围:1-65535";
}
return null;
} catch (NumberFormatException e) {
return "请输入有效的数字";
}
});
// URL 校验
builder.addInput("API 地址", "api_url")
.defaultValue("https://api.example.com")
.valueAsSummary()
.validator(value -> {
if (value.isEmpty()) {
return "地址不能为空";
}
if (!value.startsWith("http://") && !value.startsWith("https://")) {
return "地址必须以 http:// 或 https:// 开头";
}
return null;
});
}
}
# 点击拦截
public class InterceptPreference implements PluginPreference {
@Override
public void onBuild(PluginContext context, Builder builder) {
builder.title("点击拦截示例");
SharedPreferences preferences = context.getPreferences();
// 拦截开关点击,显示确认对话框
builder.addSwitch("重要选项", "important_option")
.defaultValue(false)
.interceptClick((pluginUI, preferenceItem) -> {
boolean currentValue = preferences.getBoolean("important_option", false);
String action = currentValue ? "关闭" : "开启";
pluginUI.buildDialog()
.setTitle("确认操作")
.setMessage("确定要" + action + "此选项吗?")
.setPositiveButton("{ok}", (dialog, which) -> {
preferences.edit()
.putBoolean("important_option", !currentValue)
.apply();
preferenceItem.getPreferenceScreen().recreate();
})
.setNegativeButton("{cancel}", null)
.show();
return true; // 拦截默认行为
});
// 拦截列表点击,在选择前执行检查
builder.addList("网络模式", "network_mode")
.defaultValue("auto")
.addItem("自动", "auto")
.addItem("仅WiFi", "wifi")
.addItem("仅移动数据", "mobile")
.interceptClick((pluginUI, preferenceItem) -> {
if (!isNetworkAvailable()) {
pluginUI.toast("当前无网络连接");
return true; // 拦截
}
return false; // 继续执行默认行为
});
}
private boolean isNetworkAvailable() {
// 网络检查逻辑
return true;
}
}
# 相关接口
- PluginContext - 插件上下文
- PluginUI - 插件UI核心
- LocalString - 本地化文本
← API - 弹出菜单 API - 翻译引擎 →