# 插件设置界面(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() 添加单选列表选项

# Text 接口

方法 说明
summary() 设置摘要文本
url() 设置点击后跳转的URL
onClick() 设置自定义点击事件

# Input 接口

方法 说明
defaultValue() 设置默认值
summary() 设置摘要文本
hint() 设置输入框提示文本
valueAsSummary() 使用当前值作为摘要
inputType() 设置输入类型
validator() 设置输入校验器

# Switch 接口

方法 说明
defaultValue() 设置默认状态
summary() 设置摘要文本
summaryOn() 设置开启时的摘要
summaryOff() 设置关闭时的摘要

# List 接口

方法 说明
defaultValue() 设置默认选中值
summary() 设置摘要文本
addItem() 添加子选项

# 创建设置界面

# 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

void addHeader(CharSequence title)

添加一个分组标题头,用于将相关的设置选项进行分组显示。

参数:

  • title - 分组标题文本,支持 {key} 格式的本地化文本

示例:

builder.addHeader("基础设置");
builder.addSwitch("选项1", "key1");
builder.addSwitch("选项2", "key2");

builder.addHeader("高级设置");
builder.addInput("选项3", "key3");

# 设置选项

所有设置选项的 key 参数用于 SharedPreferences 的键名,通过 context.getPreferences() 可以获取和修改这些值。

# 文本选项(Text)

# addText

Text addText(CharSequence title)

添加一个纯文本显示项,可用于显示说明信息或链接。

参数:

  • title - 显示的标题文本,支持 {key} 格式的本地化文本

返回值: 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)

设置自定义点击事件监听器。

参数:

  • listener - 点击事件监听器

监听器方法:

void onClick(PluginUI pluginUI, TextItem item)
  • 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(CharSequence defaultValue)

设置列表的默认选中值。

参数:

  • defaultValue - 默认选中项的值,支持 {key} 格式的本地化文本

# 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("当前主题:跟随系统");

# 数据存储

设置选项的值会自动保存到 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 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;
                });
    }
}

# 相关接口